Skip to content

[FEATURE] [MER-5266] Intelligent dashboard CSV download#6506

Merged
darrensiegel merged 16 commits intomasterfrom
MER-5266-dashboard-csv
Apr 28, 2026
Merged

[FEATURE] [MER-5266] Intelligent dashboard CSV download#6506
darrensiegel merged 16 commits intomasterfrom
MER-5266-dashboard-csv

Conversation

@andersweinstein
Copy link
Copy Markdown
Contributor

@andersweinstein andersweinstein commented Apr 28, 2026

• Summary

Implements MER-5266 to provide intelligent dashboard CSV download.

This introduces a dashboard-level Download dashboard data (CSV) action that generates a ZIP export from the same snapshot/projection layer used by the intelligent dashboard tiles, so the exported data stays aligned with the dashboard’s current scope and tile state rather than using a separate reporting path.

What Changed

  • Added a real instructor/admin download path for intelligent dashboard exports.
  • Replaced placeholder CSV dataset definitions with the concrete dashboard export bundle:
    • dashboard_metadata.csv
    • course_summary_metrics.csv
    • student_progress.csv
    • student_support_summary.csv
    • student_support_list.csv
    • challenging_learning_objectives.csv
    • assessment_scores_distribution.csv
    • assessment_summary.csv
  • Implemented dataset-specific serializers for the above files.
  • Kept ZIP assembly on the existing DataSnapshot.CsvExport infrastructure.
  • Moved shared export fields for summary/metadata into the summary projection so export consumes typed projection data rather than inspecting raw payloads.
  • Wired the dashboard UI to submit the current scope and tile params into the export endpoint.
  • Added browser-timezone handling for metadata so generated_at is emitted in the user’s local timezone.
  • Added metadata rows documenting the active dashboard/support thresholds used for the export, including:
    • completion_threshold
    • inactive_threshold
    • struggling_proficiency
    • struggling_progress
    • excelling_proficiency
    • excelling_progress
    • time_zone
  • Added a local dev seed task for interactive dashboard testing with realistic data across all export sheets.
  • Fixed export access for content-admin author sessions.

Behavior Notes

  • Export is snapshot/projection-driven and intended to stay in sync with the dashboard tiles.
  • Empty datasets are skipped from the ZIP.
  • The progress export currently follows the shared progress projection contract; future shared fixes to scope/resource selection should automatically flow into student_progress.csv if made in the shared oracle/projection path.

Testing

Verified with focused compile/test coverage, including:

  • concrete CSV bundle generation
  • summary projection coverage
  • delivery controller download path
  • instructor/admin access behavior

Also added a reusable mix instructor_dashboard.seed task for local interactive validation of the full export set.

@gitguardian
Copy link
Copy Markdown

gitguardian Bot commented Apr 28, 2026

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
10034199 Triggered Generic Password d5c037a .github/workflows/nightly-playwright.yml View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

Warnings
⚠️ PR is large (2641 LOC changed). Consider splitting.

Note: risk rules not loaded — micromatch is not a function

Generated by 🚫 dangerJS against 32a533d

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

AI Review — typescript

No issues found

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

AI Review — ui

No issues found

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

AI Review — security

Content admin bypass exposes section learner data

file: lib/oli_web/controllers/delivery_controller.ex
line: 984
Description: Adding author_can_download_dashboard_export?/1 as an OR condition lets any content admin download the intelligent dashboard export for any section slug, even when they are not an instructor/admin for that section. This export includes learner-level identifiers and names, so this bypasses the object-level section authorization expected for student data.
Suggestion: Remove the author-only bypass from this section export path, or require a section-scoped authorization check for content admins before allowing the download.

Seed task creates accounts with a known password

file: lib/mix/tasks/instructor_dashboard.seed.ex
line: 46
Description: The task inserts confirmed users and enrolls an instructor, but uses a hard-coded default password. If this task is accidentally run against a shared or production-like database, it creates predictable credentials with access to dashboard data.
Suggestion: Restrict the task to Mix.env() == :dev/local only and require an explicit --password, or generate a random password per run instead of using a fixed default.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

AI Review — performance

Export Oracles Run Serially

file: lib/oli_web/controllers/delivery_controller.ex
line: 794
Description: The download endpoint loads each dashboard oracle one after another inside Enum.reduce. These oracle loads are independent and likely DB-heavy, so a CSV export waits for the sum of all oracle latencies and keeps the request process occupied longer than necessary.
Suggestion: Replace the reduce with bounded parallel loading, e.g. Task.async_stream(oracle_keys, &{&1, dashboard_runtime_result(request_token, &1, context)}, max_concurrency: 4, timeout: :infinity) and collect the returned {oracle_key, result} pairs into the results map.

CSV Encoding Builds Full Intermediate Binary

file: lib/oli/instructor_dashboard/data_snapshot/csv_export/serializers/helpers.ex
line: 27
Description: CSV.encode(headers: headers) |> Enum.join() materializes each exported dataset as one large binary before it is added to the ZIP. For large courses, especially student-level exports, this can increase memory pressure and GC work during a synchronous download request.
Suggestion: Keep the CSV as iodata or a stream as long as possible, and update the ZIP builder to accept iodata/streamed entries rather than forcing every dataset through Enum.join() first.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

AI Review — elixir

Missing fallback for sections without a base project

file: lib/oli_web/controllers/delivery_controller.ex
line: 921
Description: section_course_title/1 only matches sections with an integer base_project_id. If an authorized download is requested for a section without that field populated, dashboard_export_request/3 will raise a FunctionClauseError and return a 500 instead of a controlled error or fallback title.
Suggestion: Add a fallback clause, for example defp section_course_title(%Sections.Section{title: title}), do: title || "Course", or return {:error, reason} and handle it in the existing with.

@github-actions
Copy link
Copy Markdown
Contributor

PrivSignal Risk: NONE

Scoring guide

Top 10 contributing items

  • No contributing events detected.

@darrensiegel darrensiegel merged commit c214fcb into master Apr 28, 2026
14 checks passed
@darrensiegel darrensiegel deleted the MER-5266-dashboard-csv branch April 28, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants