Skip to content

Require B2B data consent on the contract dashboard - #4006

Merged
gumaerc merged 10 commits into
mainfrom
cg/data-consent-modal
Sep 30, 2026
Merged

gumaerc merged 10 commits into
mainfrom
cg/data-consent-modal

Conversation

@gumaerc

@gumaerc gumaerc commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

What are the relevant tickets?

Closes https://github.com/mitodl/hq/issues/13575

Depends on mitodl/mitxonline#4039

Description (What does it do?)

B2B learners now have to consent to share their learner data with their organization before they can use a contract's dashboard. Everything is behind the b2b-data-consent PostHog flag.

  • With the flag on, the contract dashboard shows a consent dialog whenever the learner's consent for that contract isn't true. The dialog can only be closed with Agree or Decline. Design: https://www.figma.com/design/mSDdN8giMcncBwNgwcVJL9/?node-id=21368-21707
  • Agree records consent and enables the cards. Decline records it as declined and closes the dialog, but it comes back on the next load or on a different contract.
  • Until consent is true, every card on the page is disabled: disabled CTA and context menu, and a plain-text title. Certificate links keep working.
Implementation details
  • Consent is read from consented_to_data_sharing on the contracts in mitxonline's users/me and written with POST /api/v0/b2b/data_consent/<contract_id>/. useDataConsentMutation stays pending until users/me refetches, so the dialog closes and the cards enable in the same render.
  • Dialog in ol-components gets a showCloseButton prop.
  • CoursewareCard and the enrolled/unenrolled cards get a disabled prop. ContractContent sets it on every card.
  • The mitxonline contract and organization test factories now return the learner types (UserContractPage/UserOrganizationPage), with consent defaulting to null.

Screenshots (if appropriate):

consent-dialog disabled-cards consent-dialog disabled-cards consent-dialog disabled-cards

How can this be tested?

Requires mitxonline running mitodl/mitxonline#4039.

  1. Enable b2b-data-consent in PostHog.
  2. As a learner attached to a B2B contract that hasn't recorded consent, open the contract dashboard. The consent dialog appears, and Escape or clicking outside it does nothing.
  3. Click Decline. The dialog closes, and every card shows a disabled CTA, a disabled menu and a plain-text title. Reload, and the dialog is back.
  4. Check the box and click Agree and continue. The dialog closes and the cards are usable. Reload, and there is no dialog.
  5. Open a different contract. The dialog appears again for it.
  6. Turn the flag off. There is no dialog, and the cards behave as before.

Checklist:

@gumaerc
gumaerc requested a review from a team as a code owner September 28, 2026 21:38
Copilot AI balanced review requested due to automatic review settings September 28, 2026 21:38
@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

OpenAPI Changes

No changes detected

View full changelog

Unexpected changes? Ensure your branch is up-to-date with main (consider rebasing).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The dashboard remains actionable while the consent feature flag is unresolved, creating a consent-bypass window.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Adds feature-flagged B2B learner-data consent to contract dashboards.

Changes:

  • Adds a mandatory consent dialog and API mutation.
  • Disables course actions until consent is granted while preserving certificate links.
  • Updates MITx Online types, factories, dependencies, and tests.
File Description
yarn.lock Locks the updated MITx Online client.
frontends/​ol-components/​src/​components/​Dialog/​Dialog.tsx Supports hiding the close button.
frontends/​main/​src/​common/​feature_flags.ts Registers the consent flag.
frontends/​main/​src/​app-pages/​DashboardPage/​DataConsentDialog.tsx Implements the consent dialog.
frontends/​main/​src/​app-pages/​DashboardPage/​DataConsentDialog.test.tsx Tests dialog behavior.
frontends/​main/​src/​app-pages/​DashboardPage/​DashboardLayout.test.tsx Updates organization types.
frontends/​main/​src/​app-pages/​DashboardPage/​CoursewareDisplay/​UnenrolledCourseCard.tsx Supports disabled unenrolled cards.
frontends/​main/​src/​app-pages/​DashboardPage/​CoursewareDisplay/​UnenrolledCourseCard.test.tsx Tests disabled unenrolled cards.
frontends/​main/​src/​app-pages/​DashboardPage/​CoursewareDisplay/​test-utils.ts Updates contract fixture types.
frontends/​main/​src/​app-pages/​DashboardPage/​CoursewareDisplay/​SiblingRunsAccordion.tsx Disables run actions.
frontends/​main/​src/​app-pages/​DashboardPage/​CoursewareDisplay/​OrganizationCards.test.tsx Updates organization fixture types.
frontends/​main/​src/​app-pages/​DashboardPage/​CoursewareDisplay/​EnrolledCourseCard.tsx Disables enrolled-card actions.
frontends/​main/​src/​app-pages/​DashboardPage/​CoursewareDisplay/​EnrolledCourseCard.test.tsx Tests disabled enrolled cards.
frontends/​main/​src/​app-pages/​DashboardPage/​CoursewareDisplay/​CoursewareCard.tsx Propagates disabled state.
frontends/​main/​src/​app-pages/​DashboardPage/​ContractContent.tsx Integrates consent state and mutation.
frontends/​main/​src/​app-pages/​DashboardPage/​ContractContent.test.tsx Tests consent dashboard flows.
frontends/​main/​src/​app-pages/​DashboardPage/​AnalyticsContent.test.tsx Updates organization types.
frontends/​main/​package.json Updates the MITx Online client source.
frontends/​api/​src/​mitxonline/​test-utils/​urls.ts Adds the consent endpoint URL.
frontends/​api/​src/​mitxonline/​test-utils/​factories/​organization.ts Uses learner organization types.
frontends/​api/​src/​mitxonline/​test-utils/​factories/​contracts.ts Adds consent to contract fixtures.
frontends/​api/​src/​mitxonline/​hooks/​organizations/​index.ts Adds the consent mutation hook.
frontends/​api/​package.json Updates the MITx Online client source.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread frontends/main/src/app-pages/DashboardPage/ContractContent.tsx
@zamanafzal zamanafzal self-assigned this Sep 29, 2026
@gumaerc
gumaerc force-pushed the cg/data-consent-modal branch 2 times, most recently from f8a28a0 to 4136cdb Compare September 29, 2026 18:14
@gumaerc gumaerc added the Needs Review An open Pull Request that is ready for review label Sep 29, 2026
@gumaerc

gumaerc commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

@zamanafzal The API change has been released and the API package was upgraded, this is officially ready for a full review.

gumaerc and others added 10 commits September 29, 2026 17:11
…onsent

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…setup

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…pi-generator v7.25.0

The previous branch build used v7.2.0, which names some types differently
from published releases.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gumaerc
gumaerc force-pushed the cg/data-consent-modal branch from 74b7c08 to c50e26a Compare September 29, 2026 21:11

@zamanafzal zamanafzal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
Tested locally against a B2B org with contract and flag on in PostHog.

  • Dialog shows on load of the contract dashboard while consent is unset
  • Ticked the checkbox and clicked Agree and continue — dialog closes and
    does not come back on reload
  • On decline the dialog returns on the next load
  • Flag off in PostHog: no dialog regardless of consent state.
  • Until consent is true, both the enrolled and unenrolled cards stay gated —
    CTA disabled.
Image Image

@gumaerc
gumaerc merged commit ae3adc7 into main Sep 30, 2026
14 checks passed
@gumaerc
gumaerc deleted the cg/data-consent-modal branch September 30, 2026 15:18
@odlbot odlbot mentioned this pull request Sep 30, 2026
6 tasks done
mbertrand pushed a commit that referenced this pull request Oct 1, 2026
* chore(api): use the mitxonline-api-axios branch build with contract consent

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(ol-components): let Dialog hide its close button

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(api): add useDataConsentMutation and learner contract factories

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(dashboard): add a disabled state to course cards

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(dashboard): add the B2B data consent dialog behind a feature flag

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(dashboard): require data consent on the B2B contract dashboard

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(dashboard): use learner contract and organization types in test setup

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(dashboard): show the consent spinner on the button that was clicked

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(api): rebuild the mitxonline-api-axios branch client with openapi-generator v7.25.0

The previous branch build used v7.2.0, which names some types differently
from published releases.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* switch back to published api package

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
mbertrand pushed a commit that referenced this pull request Oct 1, 2026
* chore(api): use the mitxonline-api-axios branch build with contract consent

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(ol-components): let Dialog hide its close button

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(api): add useDataConsentMutation and learner contract factories

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(dashboard): add a disabled state to course cards

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(dashboard): add the B2B data consent dialog behind a feature flag

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(dashboard): require data consent on the B2B contract dashboard

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(dashboard): use learner contract and organization types in test setup

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(dashboard): show the consent spinner on the button that was clicked

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(api): rebuild the mitxonline-api-axios branch client with openapi-generator v7.25.0

The previous branch build used v7.2.0, which names some types differently
from published releases.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* switch back to published api package

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs Review An open Pull Request that is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants