Skip to content

better bad data handling for the org dashboard #2427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 11, 2025

Conversation

gumaerc
Copy link
Contributor

@gumaerc gumaerc commented Aug 9, 2025

What are the relevant tickets?

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

Description (What does it do?)

This PR primarily fixes an issue where if you put programs from multiple orgs in a program collection, you would see an infinite loading skeleton for the programs that aren't part of the currently displayed org. This is because the API call to get the program detail filters on org_id, but the program collection endpoint returns program ids that are not a part of the given org. This acts as a safegaurd against that, although there should maybe be a PR in MITx Online as well to make sure that programs returned for a collection are also filtered on org_id. This PR also adds a message if no programs are found to be associated with the org being viewed.

Screenshots (if appropriate):

image image

How can this be tested?

In order to test this, you need a basic installation of mitxonline up and running with example data in it. You may be able to skip one or more steps if you have already done them:

  • Ensure you have local hosts redirects for the following domains, replacing the example IP with your local IP address (Google how to get this if unsure, mine is 192.168.1.50)
192.168.1.50 open.odl.local
192.168.1.50 api.open.odl.local
192.168.1.50 kc.ol.local
192.168.1.50 mitxonline.odl.local
CELERY_TASK_ALWAYS_EAGER=True
DJANGO_LOG_LEVEL=INFO
LOG_LEVEL=INFO
SENTRY_LOG_LEVEL=ERROR
MAILGUN_KEY=fake
MAILGUN_URL=
MAILGUN_RECIPIENT_OVERRIDE=
MAILGUN_SENDER_DOMAIN=.odl.local
SECRET_KEY=
STATUS_TOKEN=
UWSGI_THREADS=5
SENTRY_DSN=
MITX_ONLINE_BASE_URL=http://open.odl.local:8065/mitxonline
MITX_ONLINE_ADMIN_CLIENT_ID=refine-local-client-id
MITX_ONLINE_ADMIN_BASE_URL=http://mitxonline.odl.local:8016
POSTHOG_PROJECT_API_KEY=
POSTHOG_API_HOST=https://app.posthog.com/
HUBSPOT_HOME_PAGE_FORM_GUID=
HUBSPOT_PORTAL_ID=
APISIX_PORT=9080

# APISIX/Keycloak settings
APISIX_LOGOUT_URL=http://api.open.odl.local:8065/logout/
APISIX_SESSION_SECRET_KEY=supertopsecret1234
KC_SPI_THEME_WELCOME_THEME=scim
KC_SPI_REALM_RESTAPI_EXTENSION_SCIM_LICENSE_KEY=
KEYCLOAK_BASE_URL=http://kc.ol.local:8066
KEYCLOAK_CLIENT_ID=apisix
# This is not a secret. This is for the Keycloak container, only for local use.
KEYCLOAK_CLIENT_SECRET=HckCZXToXfaetbBx0Fo3xbjnC468oMi4 # pragma: allowlist-secret
KEYCLOAK_DISCOVERY_URL=http://kc.ol.local:8066/realms/ol-local/.well-known/openid-configuration
KEYCLOAK_REALM_NAME=ol-local
KEYCLOAK_SCOPES="openid profile ol-profile"
KEYCLOAK_SVC_KEYSTORE_PASSWORD=supertopsecret1234
KEYCLOAK_SVC_HOSTNAME=kc.ol.local
KEYCLOAK_SVC_ADMIN=admin
KEYCLOAK_SVC_ADMIN_PASSWORD=admin
AUTHORIZATION_URL=http://kc.ol.local:8066/realms/ol-local/protocol/openid-connect/auth
ACCESS_TOKEN_URL=http://kc.ol.local:8066/realms/ol-local/protocol/openid-connect/token
OIDC_ENDPOINT=http://kc.ol.local:8066/realms/ol-local
SOCIAL_AUTH_OL_OIDC_OIDC_ENDPOINT=http://kc.ol.local:8066/realms/ol-local
SOCIAL_AUTH_OL_OIDC_KEY=apisix
# This is not a secret. This is for the Keycloak container, only for local use.
SOCIAL_AUTH_OL_OIDC_SECRET=HckCZXToXfaetbBx0Fo3xbjnC468oMi4 # pragma: allowlist-secret
USERINFO_URL=http://kc.ol.local:8066/realms/ol-local/protocol/openid-connect/userinfo
MITOL_APIGATEWAY_DISABLE_MIDDLEWARE=False

FEATURE_IGNORE_EDX_FAILURES=True
OPENEDX_API_CLIENT_ID=fake
OPENEDX_API_CLIENT_SECRET=fake
OPENEDX_SERVICE_WORKER_API_TOKEN=fake

CSRF_COOKIE_DOMAIN=.odl.local
CORS_ALLOWED_ORIGINS=http://mitxonline.odl.local:8065, http://open.odl.local:8062, http://api.open.odl.local:8065
CSRF_TRUSTED_ORIGINS=http://mitxonline.odl.local:8065, http://open.odl.local:8062, http://api.open.odl.local:8065
  • Spin up mitxonline with docker compose up --build -d
  • Promote the admin user with docker compose exec web ./manage.py promote_user promote --superuser --email [email protected]
  • Populate test course data with docker compose exec web ./manage.py populate_course_data
  • Generate docs with pants docs ::
  • In dist/sphinx/index.html, read the section on generating a B2B organization / contract and create two, adding some of the test courses to both, and some to only org a / only org b
  • In Django admin, create a Program and add some courses to the program that are included in your B2B org, making sure to mark the program as "live"
  • Create a few more programs with different courses in them that are not part of your B2B org
  • Navigate to Wagtail at http://mitxonline.odl.local:8065/cms
  • Browse to Home Page -> Program Collections
  • Create a new program collection
  • Add both programs to your collection, the one that's part of your org and the one that isn't
  • Make sure you have a personal Posthog project configured and have the API key at the ready
  • Before we spin up mit-learn, we need to set some env variables:
.env
...
MITX_ONLINE_UPSTREAM=mitxonline.odl.local:8013
MITX_ONLINE_DOMAIN=mitxonline.odl.local
MITX_ONLINE_BASE_URL=http://mitxonline.odl.local:8065
POSTHOG_ENABLED=True
CSRF_COOKIE_DOMAIN=.odl.local

shared.local.env
POSTHOG_PROJECT_API_KEY=YOUR_API_KEY_HERE
POSTHOG_PROJECT_ID=YOUR_PROJECT_ID_HERE
POSTHOG_TIMEOUT_MS=1500
  • In your Posthog project, enable the enrollment-dashboard and mitlearn-organization-dashboard feature flags for all users
  • Spin up MIT Learn
  • Log in with the [email protected] test user
  • Navigate to the org dashboard
  • Make sure you do not see any infinite loading skeletons
  • If you make it so there are no programs associated with an org, or only programs that don't match your org, you should see "No programs found"

@gumaerc gumaerc added the Needs Review An open Pull Request that is ready for review label Aug 9, 2025
Copy link
Contributor

@jonkafton jonkafton left a comment

Choose a reason for hiding this comment

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

Looks clean!


const programsWithCourses = programQueries
.map((query, index) => {
if (!query.data?.results || !query.data.results.length) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (!query.data?.results || !query.data.results.length) {
if (!query.data?.results?.length) {

}

// Only render if at least one program has courses
if (!hasAnyCourses) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we likely to ever hit this scenario or this just the bad data defense? Thinking if it's ever expected under normal conditions it's odd to display the program title and description with load skeleton and then to disappear it once loaded with no courses (as opposed to just display e.g. "No courses are available in this program at this time").

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It will show the loading skeleton for the program while the API response is still coming though, but if it's determined that the program isn't returning courses, then nothing will be shown. This is mostly a bad data defense, realistically this should never happen in production. I will ask Steve / Bilal what might be expected here when I talk to them next, but just leave it as-is for now.

@gumaerc gumaerc force-pushed the cg/program-collection-handle-empty-response branch from f4f11a0 to 5596b04 Compare August 11, 2025 19:56
@gumaerc gumaerc merged commit c2b32ef into main Aug 11, 2025
12 of 13 checks passed
@gumaerc gumaerc deleted the cg/program-collection-handle-empty-response branch August 11, 2025 20:47
@odlbot odlbot mentioned this pull request Aug 13, 2025
6 tasks
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.

2 participants