Refactor: Migrate from course_name strings to course_id FKs - #51

Closed
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema
Closed

Refactor: Migrate from course_name strings to course_id FKs#51
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema

Conversation

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
Member

Summary

This PR refactors the backend and frontend to use the new database schema where courses are canonical (no user_id) and user_courses is the enrollment join table.

Database Changes (already applied in Supabase)

  • courses is now canonical (no user_id): id, course_code, course_name, department, school, etc.
  • user_courses is the enrollment join table
  • All dependent tables now use course_id FK to courses.id:
    • assignments, sessions, graph_nodes, documents, study_guides
  • New tables: course_concept_stats, course_summary
  • Removed: course_context table

Backend Changes

services/course_context_service.py (COMPLETE REWRITE)

  • Aggregates graph_nodes mastery data across all students enrolled in a course
  • Computes avg_mastery_score, pct_mastered, pct_struggling, pct_unexplored per concept
  • Pulls common_misconceptions, effective_explanations, prerequisite_gaps from quiz_context
  • Upserts into course_concept_stats keyed on (course_id, concept_name, semester)
  • Maintains course_summary with top 5 struggling/mastered concepts
  • Regenerates summary_text via Gemini only when data hash changes

services/graph_service.py

  • Updated to join user_courses -> courses for enrolled courses
  • get_graph: builds subject_root hubs from canonical courses (course_code + course_name)
  • apply_graph_update: now accepts course_id parameter for all node inserts/updates
  • get_courses: returns enriched data: course_code, course_name, school, department, color, nickname

routes/graph.py

  • Course endpoints now accept course_id instead of course_name
  • Returns joined data from user_courses + courses

routes/learn.py

  • Sessions now store course_id instead of resolving from topic strings
  • start-session accepts optional course_id parameter
  • Passes course_id through to apply_graph_update

routes/calendar.py

  • save endpoint uses course_id instead of course_name
  • upcoming/all endpoints join with courses to return course_code and course_name

models/init.py

  • Added course_id fields to StartSessionBody, AssignmentItem, AddCourseBody

Frontend Changes

src/lib/api.ts

  • getCourses: returns EnrolledCourse with course_code, course_name, school, department, etc.
  • addCourse: takes courseId instead of courseName
  • updateCourseColor, deleteCourse: use courseId
  • startSession: accepts optional courseId parameter
  • saveAssignments: uses course_id in SaveAssignmentItem

Testing

  • All backend modules import successfully
  • Pydantic models validate correctly with new course_id fields
  • Frontend TypeScript types are updated

Migration Notes

  • Frontend components that called addCourse(userId, courseName) need to now call addCourse(userId, courseId) where courseId is from the canonical courses catalog
  • The enrollment flow should first show available courses, then enroll via course_id

Commit:25dedba
Branch: refactor/course-id-schema

This is a major schema refactoring to support canonical courses:
Backend Changes:
- course_context_service.py: Complete rewrite to use new course_concept_stats
and course_summary tables with Gemini-powered summary generation
- graph_service.py: Updated to join user_courses->courses, use course_id FK
- routes/graph.py: Endpoints now accept course_id instead of course_name
- routes/learn.py: Sessions store course_id, pass through to graph updates
- routes/calendar.py: Assignments use course_id, join with courses for display
- calendar_service.py: Updated to use course_id instead of course_name
- models/__init__.py: Added course_id fields to Pydantic models
Frontend Changes:
- api.ts: Updated all API functions to use course_id instead of course_name
- getCourses returns enriched data: course_code, course_name, school, dept
- addCourse, updateCourseColor, deleteCourse all use course_id
- startSession accepts optional course_id parameter
- saveAssignments uses course_id
Database Schema Migration (already applied in Supabase):
- courses table is now canonical (no user_id)
- user_courses is the enrollment join table
- All dependent tables use course_id FK: assignments, sessions, graph_nodes,
documents, study_guides
- New tables: course_concept_stats, course_summary
- Removed: course_context table
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:25dedba
Status:🚫 Build failed.

View logs

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae51972-68a5-4960-8bee-39fab9ab3079

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
MemberAuthor

Superseded by combined PR #53 (course_id migration + calendar normalization). All migration changes are included there.

@AndresL230
AndresL230 deleted the refactor/course-id-schema branch April 15, 2026 01:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Jose-Gael-Cruz-Lopez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Refactor: Migrate from course_name strings to course_id FKs - #51

Closed
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema
Closed

Refactor: Migrate from course_name strings to course_id FKs#51
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema

Conversation

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
Member

Summary

This PR refactors the backend and frontend to use the new database schema where courses are canonical (no user_id) and user_courses is the enrollment join table.

Database Changes (already applied in Supabase)

  • courses is now canonical (no user_id): id, course_code, course_name, department, school, etc.
  • user_courses is the enrollment join table
  • All dependent tables now use course_id FK to courses.id:
    • assignments, sessions, graph_nodes, documents, study_guides
  • New tables: course_concept_stats, course_summary
  • Removed: course_context table

Backend Changes

services/course_context_service.py (COMPLETE REWRITE)

  • Aggregates graph_nodes mastery data across all students enrolled in a course
  • Computes avg_mastery_score, pct_mastered, pct_struggling, pct_unexplored per concept
  • Pulls common_misconceptions, effective_explanations, prerequisite_gaps from quiz_context
  • Upserts into course_concept_stats keyed on (course_id, concept_name, semester)
  • Maintains course_summary with top 5 struggling/mastered concepts
  • Regenerates summary_text via Gemini only when data hash changes

services/graph_service.py

  • Updated to join user_courses -> courses for enrolled courses
  • get_graph: builds subject_root hubs from canonical courses (course_code + course_name)
  • apply_graph_update: now accepts course_id parameter for all node inserts/updates
  • get_courses: returns enriched data: course_code, course_name, school, department, color, nickname

routes/graph.py

  • Course endpoints now accept course_id instead of course_name
  • Returns joined data from user_courses + courses

routes/learn.py

  • Sessions now store course_id instead of resolving from topic strings
  • start-session accepts optional course_id parameter
  • Passes course_id through to apply_graph_update

routes/calendar.py

  • save endpoint uses course_id instead of course_name
  • upcoming/all endpoints join with courses to return course_code and course_name

models/init.py

  • Added course_id fields to StartSessionBody, AssignmentItem, AddCourseBody

Frontend Changes

src/lib/api.ts

  • getCourses: returns EnrolledCourse with course_code, course_name, school, department, etc.
  • addCourse: takes courseId instead of courseName
  • updateCourseColor, deleteCourse: use courseId
  • startSession: accepts optional courseId parameter
  • saveAssignments: uses course_id in SaveAssignmentItem

Testing

  • All backend modules import successfully
  • Pydantic models validate correctly with new course_id fields
  • Frontend TypeScript types are updated

Migration Notes

  • Frontend components that called addCourse(userId, courseName) need to now call addCourse(userId, courseId) where courseId is from the canonical courses catalog
  • The enrollment flow should first show available courses, then enroll via course_id

Commit:25dedba
Branch: refactor/course-id-schema

This is a major schema refactoring to support canonical courses:
Backend Changes:
- course_context_service.py: Complete rewrite to use new course_concept_stats
and course_summary tables with Gemini-powered summary generation
- graph_service.py: Updated to join user_courses->courses, use course_id FK
- routes/graph.py: Endpoints now accept course_id instead of course_name
- routes/learn.py: Sessions store course_id, pass through to graph updates
- routes/calendar.py: Assignments use course_id, join with courses for display
- calendar_service.py: Updated to use course_id instead of course_name
- models/__init__.py: Added course_id fields to Pydantic models
Frontend Changes:
- api.ts: Updated all API functions to use course_id instead of course_name
- getCourses returns enriched data: course_code, course_name, school, dept
- addCourse, updateCourseColor, deleteCourse all use course_id
- startSession accepts optional course_id parameter
- saveAssignments uses course_id
Database Schema Migration (already applied in Supabase):
- courses table is now canonical (no user_id)
- user_courses is the enrollment join table
- All dependent tables use course_id FK: assignments, sessions, graph_nodes,
documents, study_guides
- New tables: course_concept_stats, course_summary
- Removed: course_context table
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:25dedba
Status:🚫 Build failed.

View logs

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae51972-68a5-4960-8bee-39fab9ab3079

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
MemberAuthor

Superseded by combined PR #53 (course_id migration + calendar normalization). All migration changes are included there.

@AndresL230
AndresL230 deleted the refactor/course-id-schema branch April 15, 2026 01:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Jose-Gael-Cruz-Lopez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor: Migrate from course_name strings to course_id FKs - #51

Closed
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema
Closed

Refactor: Migrate from course_name strings to course_id FKs#51
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema

Conversation

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
Member

Summary

This PR refactors the backend and frontend to use the new database schema where courses are canonical (no user_id) and user_courses is the enrollment join table.

Database Changes (already applied in Supabase)

  • courses is now canonical (no user_id): id, course_code, course_name, department, school, etc.
  • user_courses is the enrollment join table
  • All dependent tables now use course_id FK to courses.id:
    • assignments, sessions, graph_nodes, documents, study_guides
  • New tables: course_concept_stats, course_summary
  • Removed: course_context table

Backend Changes

services/course_context_service.py (COMPLETE REWRITE)

  • Aggregates graph_nodes mastery data across all students enrolled in a course
  • Computes avg_mastery_score, pct_mastered, pct_struggling, pct_unexplored per concept
  • Pulls common_misconceptions, effective_explanations, prerequisite_gaps from quiz_context
  • Upserts into course_concept_stats keyed on (course_id, concept_name, semester)
  • Maintains course_summary with top 5 struggling/mastered concepts
  • Regenerates summary_text via Gemini only when data hash changes

services/graph_service.py

  • Updated to join user_courses -> courses for enrolled courses
  • get_graph: builds subject_root hubs from canonical courses (course_code + course_name)
  • apply_graph_update: now accepts course_id parameter for all node inserts/updates
  • get_courses: returns enriched data: course_code, course_name, school, department, color, nickname

routes/graph.py

  • Course endpoints now accept course_id instead of course_name
  • Returns joined data from user_courses + courses

routes/learn.py

  • Sessions now store course_id instead of resolving from topic strings
  • start-session accepts optional course_id parameter
  • Passes course_id through to apply_graph_update

routes/calendar.py

  • save endpoint uses course_id instead of course_name
  • upcoming/all endpoints join with courses to return course_code and course_name

models/init.py

  • Added course_id fields to StartSessionBody, AssignmentItem, AddCourseBody

Frontend Changes

src/lib/api.ts

  • getCourses: returns EnrolledCourse with course_code, course_name, school, department, etc.
  • addCourse: takes courseId instead of courseName
  • updateCourseColor, deleteCourse: use courseId
  • startSession: accepts optional courseId parameter
  • saveAssignments: uses course_id in SaveAssignmentItem

Testing

  • All backend modules import successfully
  • Pydantic models validate correctly with new course_id fields
  • Frontend TypeScript types are updated

Migration Notes

  • Frontend components that called addCourse(userId, courseName) need to now call addCourse(userId, courseId) where courseId is from the canonical courses catalog
  • The enrollment flow should first show available courses, then enroll via course_id

Commit:25dedba
Branch: refactor/course-id-schema

This is a major schema refactoring to support canonical courses:
Backend Changes:
- course_context_service.py: Complete rewrite to use new course_concept_stats
and course_summary tables with Gemini-powered summary generation
- graph_service.py: Updated to join user_courses->courses, use course_id FK
- routes/graph.py: Endpoints now accept course_id instead of course_name
- routes/learn.py: Sessions store course_id, pass through to graph updates
- routes/calendar.py: Assignments use course_id, join with courses for display
- calendar_service.py: Updated to use course_id instead of course_name
- models/__init__.py: Added course_id fields to Pydantic models
Frontend Changes:
- api.ts: Updated all API functions to use course_id instead of course_name
- getCourses returns enriched data: course_code, course_name, school, dept
- addCourse, updateCourseColor, deleteCourse all use course_id
- startSession accepts optional course_id parameter
- saveAssignments uses course_id
Database Schema Migration (already applied in Supabase):
- courses table is now canonical (no user_id)
- user_courses is the enrollment join table
- All dependent tables use course_id FK: assignments, sessions, graph_nodes,
documents, study_guides
- New tables: course_concept_stats, course_summary
- Removed: course_context table
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:25dedba
Status:🚫 Build failed.

View logs

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae51972-68a5-4960-8bee-39fab9ab3079

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
MemberAuthor

Superseded by combined PR #53 (course_id migration + calendar normalization). All migration changes are included there.

@AndresL230
AndresL230 deleted the refactor/course-id-schema branch April 15, 2026 01:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Jose-Gael-Cruz-Lopez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor: Migrate from course_name strings to course_id FKs - #51

Closed
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema
Closed

Refactor: Migrate from course_name strings to course_id FKs#51
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema

Conversation

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
Member

Summary

This PR refactors the backend and frontend to use the new database schema where courses are canonical (no user_id) and user_courses is the enrollment join table.

Database Changes (already applied in Supabase)

  • courses is now canonical (no user_id): id, course_code, course_name, department, school, etc.
  • user_courses is the enrollment join table
  • All dependent tables now use course_id FK to courses.id:
    • assignments, sessions, graph_nodes, documents, study_guides
  • New tables: course_concept_stats, course_summary
  • Removed: course_context table

Backend Changes

services/course_context_service.py (COMPLETE REWRITE)

  • Aggregates graph_nodes mastery data across all students enrolled in a course
  • Computes avg_mastery_score, pct_mastered, pct_struggling, pct_unexplored per concept
  • Pulls common_misconceptions, effective_explanations, prerequisite_gaps from quiz_context
  • Upserts into course_concept_stats keyed on (course_id, concept_name, semester)
  • Maintains course_summary with top 5 struggling/mastered concepts
  • Regenerates summary_text via Gemini only when data hash changes

services/graph_service.py

  • Updated to join user_courses -> courses for enrolled courses
  • get_graph: builds subject_root hubs from canonical courses (course_code + course_name)
  • apply_graph_update: now accepts course_id parameter for all node inserts/updates
  • get_courses: returns enriched data: course_code, course_name, school, department, color, nickname

routes/graph.py

  • Course endpoints now accept course_id instead of course_name
  • Returns joined data from user_courses + courses

routes/learn.py

  • Sessions now store course_id instead of resolving from topic strings
  • start-session accepts optional course_id parameter
  • Passes course_id through to apply_graph_update

routes/calendar.py

  • save endpoint uses course_id instead of course_name
  • upcoming/all endpoints join with courses to return course_code and course_name

models/init.py

  • Added course_id fields to StartSessionBody, AssignmentItem, AddCourseBody

Frontend Changes

src/lib/api.ts

  • getCourses: returns EnrolledCourse with course_code, course_name, school, department, etc.
  • addCourse: takes courseId instead of courseName
  • updateCourseColor, deleteCourse: use courseId
  • startSession: accepts optional courseId parameter
  • saveAssignments: uses course_id in SaveAssignmentItem

Testing

  • All backend modules import successfully
  • Pydantic models validate correctly with new course_id fields
  • Frontend TypeScript types are updated

Migration Notes

  • Frontend components that called addCourse(userId, courseName) need to now call addCourse(userId, courseId) where courseId is from the canonical courses catalog
  • The enrollment flow should first show available courses, then enroll via course_id

Commit:25dedba
Branch: refactor/course-id-schema

This is a major schema refactoring to support canonical courses:
Backend Changes:
- course_context_service.py: Complete rewrite to use new course_concept_stats
and course_summary tables with Gemini-powered summary generation
- graph_service.py: Updated to join user_courses->courses, use course_id FK
- routes/graph.py: Endpoints now accept course_id instead of course_name
- routes/learn.py: Sessions store course_id, pass through to graph updates
- routes/calendar.py: Assignments use course_id, join with courses for display
- calendar_service.py: Updated to use course_id instead of course_name
- models/__init__.py: Added course_id fields to Pydantic models
Frontend Changes:
- api.ts: Updated all API functions to use course_id instead of course_name
- getCourses returns enriched data: course_code, course_name, school, dept
- addCourse, updateCourseColor, deleteCourse all use course_id
- startSession accepts optional course_id parameter
- saveAssignments uses course_id
Database Schema Migration (already applied in Supabase):
- courses table is now canonical (no user_id)
- user_courses is the enrollment join table
- All dependent tables use course_id FK: assignments, sessions, graph_nodes,
documents, study_guides
- New tables: course_concept_stats, course_summary
- Removed: course_context table
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:25dedba
Status:🚫 Build failed.

View logs

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae51972-68a5-4960-8bee-39fab9ab3079

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
MemberAuthor

Superseded by combined PR #53 (course_id migration + calendar normalization). All migration changes are included there.

@AndresL230
AndresL230 deleted the refactor/course-id-schema branch April 15, 2026 01:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Jose-Gael-Cruz-Lopez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Refactor: Migrate from course_name strings to course_id FKs - #51

Closed
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema
Closed

Refactor: Migrate from course_name strings to course_id FKs#51
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema

Conversation

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
Member

Summary

This PR refactors the backend and frontend to use the new database schema where courses are canonical (no user_id) and user_courses is the enrollment join table.

Database Changes (already applied in Supabase)

  • courses is now canonical (no user_id): id, course_code, course_name, department, school, etc.
  • user_courses is the enrollment join table
  • All dependent tables now use course_id FK to courses.id:
    • assignments, sessions, graph_nodes, documents, study_guides
  • New tables: course_concept_stats, course_summary
  • Removed: course_context table

Backend Changes

services/course_context_service.py (COMPLETE REWRITE)

  • Aggregates graph_nodes mastery data across all students enrolled in a course
  • Computes avg_mastery_score, pct_mastered, pct_struggling, pct_unexplored per concept
  • Pulls common_misconceptions, effective_explanations, prerequisite_gaps from quiz_context
  • Upserts into course_concept_stats keyed on (course_id, concept_name, semester)
  • Maintains course_summary with top 5 struggling/mastered concepts
  • Regenerates summary_text via Gemini only when data hash changes

services/graph_service.py

  • Updated to join user_courses -> courses for enrolled courses
  • get_graph: builds subject_root hubs from canonical courses (course_code + course_name)
  • apply_graph_update: now accepts course_id parameter for all node inserts/updates
  • get_courses: returns enriched data: course_code, course_name, school, department, color, nickname

routes/graph.py

  • Course endpoints now accept course_id instead of course_name
  • Returns joined data from user_courses + courses

routes/learn.py

  • Sessions now store course_id instead of resolving from topic strings
  • start-session accepts optional course_id parameter
  • Passes course_id through to apply_graph_update

routes/calendar.py

  • save endpoint uses course_id instead of course_name
  • upcoming/all endpoints join with courses to return course_code and course_name

models/init.py

  • Added course_id fields to StartSessionBody, AssignmentItem, AddCourseBody

Frontend Changes

src/lib/api.ts

  • getCourses: returns EnrolledCourse with course_code, course_name, school, department, etc.
  • addCourse: takes courseId instead of courseName
  • updateCourseColor, deleteCourse: use courseId
  • startSession: accepts optional courseId parameter
  • saveAssignments: uses course_id in SaveAssignmentItem

Testing

  • All backend modules import successfully
  • Pydantic models validate correctly with new course_id fields
  • Frontend TypeScript types are updated

Migration Notes

  • Frontend components that called addCourse(userId, courseName) need to now call addCourse(userId, courseId) where courseId is from the canonical courses catalog
  • The enrollment flow should first show available courses, then enroll via course_id

Commit:25dedba
Branch: refactor/course-id-schema

This is a major schema refactoring to support canonical courses:
Backend Changes:
- course_context_service.py: Complete rewrite to use new course_concept_stats
and course_summary tables with Gemini-powered summary generation
- graph_service.py: Updated to join user_courses->courses, use course_id FK
- routes/graph.py: Endpoints now accept course_id instead of course_name
- routes/learn.py: Sessions store course_id, pass through to graph updates
- routes/calendar.py: Assignments use course_id, join with courses for display
- calendar_service.py: Updated to use course_id instead of course_name
- models/__init__.py: Added course_id fields to Pydantic models
Frontend Changes:
- api.ts: Updated all API functions to use course_id instead of course_name
- getCourses returns enriched data: course_code, course_name, school, dept
- addCourse, updateCourseColor, deleteCourse all use course_id
- startSession accepts optional course_id parameter
- saveAssignments uses course_id
Database Schema Migration (already applied in Supabase):
- courses table is now canonical (no user_id)
- user_courses is the enrollment join table
- All dependent tables use course_id FK: assignments, sessions, graph_nodes,
documents, study_guides
- New tables: course_concept_stats, course_summary
- Removed: course_context table
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:25dedba
Status:🚫 Build failed.

View logs

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae51972-68a5-4960-8bee-39fab9ab3079

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
MemberAuthor

Superseded by combined PR #53 (course_id migration + calendar normalization). All migration changes are included there.

@AndresL230
AndresL230 deleted the refactor/course-id-schema branch April 15, 2026 01:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Jose-Gael-Cruz-Lopez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor: Migrate from course_name strings to course_id FKs - #51

Closed
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema
Closed

Refactor: Migrate from course_name strings to course_id FKs#51
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema

Conversation

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
Member

Summary

This PR refactors the backend and frontend to use the new database schema where courses are canonical (no user_id) and user_courses is the enrollment join table.

Database Changes (already applied in Supabase)

  • courses is now canonical (no user_id): id, course_code, course_name, department, school, etc.
  • user_courses is the enrollment join table
  • All dependent tables now use course_id FK to courses.id:
    • assignments, sessions, graph_nodes, documents, study_guides
  • New tables: course_concept_stats, course_summary
  • Removed: course_context table

Backend Changes

services/course_context_service.py (COMPLETE REWRITE)

  • Aggregates graph_nodes mastery data across all students enrolled in a course
  • Computes avg_mastery_score, pct_mastered, pct_struggling, pct_unexplored per concept
  • Pulls common_misconceptions, effective_explanations, prerequisite_gaps from quiz_context
  • Upserts into course_concept_stats keyed on (course_id, concept_name, semester)
  • Maintains course_summary with top 5 struggling/mastered concepts
  • Regenerates summary_text via Gemini only when data hash changes

services/graph_service.py

  • Updated to join user_courses -> courses for enrolled courses
  • get_graph: builds subject_root hubs from canonical courses (course_code + course_name)
  • apply_graph_update: now accepts course_id parameter for all node inserts/updates
  • get_courses: returns enriched data: course_code, course_name, school, department, color, nickname

routes/graph.py

  • Course endpoints now accept course_id instead of course_name
  • Returns joined data from user_courses + courses

routes/learn.py

  • Sessions now store course_id instead of resolving from topic strings
  • start-session accepts optional course_id parameter
  • Passes course_id through to apply_graph_update

routes/calendar.py

  • save endpoint uses course_id instead of course_name
  • upcoming/all endpoints join with courses to return course_code and course_name

models/init.py

  • Added course_id fields to StartSessionBody, AssignmentItem, AddCourseBody

Frontend Changes

src/lib/api.ts

  • getCourses: returns EnrolledCourse with course_code, course_name, school, department, etc.
  • addCourse: takes courseId instead of courseName
  • updateCourseColor, deleteCourse: use courseId
  • startSession: accepts optional courseId parameter
  • saveAssignments: uses course_id in SaveAssignmentItem

Testing

  • All backend modules import successfully
  • Pydantic models validate correctly with new course_id fields
  • Frontend TypeScript types are updated

Migration Notes

  • Frontend components that called addCourse(userId, courseName) need to now call addCourse(userId, courseId) where courseId is from the canonical courses catalog
  • The enrollment flow should first show available courses, then enroll via course_id

Commit:25dedba
Branch: refactor/course-id-schema

This is a major schema refactoring to support canonical courses:
Backend Changes:
- course_context_service.py: Complete rewrite to use new course_concept_stats
and course_summary tables with Gemini-powered summary generation
- graph_service.py: Updated to join user_courses->courses, use course_id FK
- routes/graph.py: Endpoints now accept course_id instead of course_name
- routes/learn.py: Sessions store course_id, pass through to graph updates
- routes/calendar.py: Assignments use course_id, join with courses for display
- calendar_service.py: Updated to use course_id instead of course_name
- models/__init__.py: Added course_id fields to Pydantic models
Frontend Changes:
- api.ts: Updated all API functions to use course_id instead of course_name
- getCourses returns enriched data: course_code, course_name, school, dept
- addCourse, updateCourseColor, deleteCourse all use course_id
- startSession accepts optional course_id parameter
- saveAssignments uses course_id
Database Schema Migration (already applied in Supabase):
- courses table is now canonical (no user_id)
- user_courses is the enrollment join table
- All dependent tables use course_id FK: assignments, sessions, graph_nodes,
documents, study_guides
- New tables: course_concept_stats, course_summary
- Removed: course_context table
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:25dedba
Status:🚫 Build failed.

View logs

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae51972-68a5-4960-8bee-39fab9ab3079

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
MemberAuthor

Superseded by combined PR #53 (course_id migration + calendar normalization). All migration changes are included there.

@AndresL230
AndresL230 deleted the refactor/course-id-schema branch April 15, 2026 01:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Jose-Gael-Cruz-Lopez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Refactor: Migrate from course_name strings to course_id FKs - #51

Closed
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema
Closed

Refactor: Migrate from course_name strings to course_id FKs#51
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema

Conversation

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
Member

Summary

This PR refactors the backend and frontend to use the new database schema where courses are canonical (no user_id) and user_courses is the enrollment join table.

Database Changes (already applied in Supabase)

  • courses is now canonical (no user_id): id, course_code, course_name, department, school, etc.
  • user_courses is the enrollment join table
  • All dependent tables now use course_id FK to courses.id:
    • assignments, sessions, graph_nodes, documents, study_guides
  • New tables: course_concept_stats, course_summary
  • Removed: course_context table

Backend Changes

services/course_context_service.py (COMPLETE REWRITE)

  • Aggregates graph_nodes mastery data across all students enrolled in a course
  • Computes avg_mastery_score, pct_mastered, pct_struggling, pct_unexplored per concept
  • Pulls common_misconceptions, effective_explanations, prerequisite_gaps from quiz_context
  • Upserts into course_concept_stats keyed on (course_id, concept_name, semester)
  • Maintains course_summary with top 5 struggling/mastered concepts
  • Regenerates summary_text via Gemini only when data hash changes

services/graph_service.py

  • Updated to join user_courses -> courses for enrolled courses
  • get_graph: builds subject_root hubs from canonical courses (course_code + course_name)
  • apply_graph_update: now accepts course_id parameter for all node inserts/updates
  • get_courses: returns enriched data: course_code, course_name, school, department, color, nickname

routes/graph.py

  • Course endpoints now accept course_id instead of course_name
  • Returns joined data from user_courses + courses

routes/learn.py

  • Sessions now store course_id instead of resolving from topic strings
  • start-session accepts optional course_id parameter
  • Passes course_id through to apply_graph_update

routes/calendar.py

  • save endpoint uses course_id instead of course_name
  • upcoming/all endpoints join with courses to return course_code and course_name

models/init.py

  • Added course_id fields to StartSessionBody, AssignmentItem, AddCourseBody

Frontend Changes

src/lib/api.ts

  • getCourses: returns EnrolledCourse with course_code, course_name, school, department, etc.
  • addCourse: takes courseId instead of courseName
  • updateCourseColor, deleteCourse: use courseId
  • startSession: accepts optional courseId parameter
  • saveAssignments: uses course_id in SaveAssignmentItem

Testing

  • All backend modules import successfully
  • Pydantic models validate correctly with new course_id fields
  • Frontend TypeScript types are updated

Migration Notes

  • Frontend components that called addCourse(userId, courseName) need to now call addCourse(userId, courseId) where courseId is from the canonical courses catalog
  • The enrollment flow should first show available courses, then enroll via course_id

Commit:25dedba
Branch: refactor/course-id-schema

This is a major schema refactoring to support canonical courses:
Backend Changes:
- course_context_service.py: Complete rewrite to use new course_concept_stats
and course_summary tables with Gemini-powered summary generation
- graph_service.py: Updated to join user_courses->courses, use course_id FK
- routes/graph.py: Endpoints now accept course_id instead of course_name
- routes/learn.py: Sessions store course_id, pass through to graph updates
- routes/calendar.py: Assignments use course_id, join with courses for display
- calendar_service.py: Updated to use course_id instead of course_name
- models/__init__.py: Added course_id fields to Pydantic models
Frontend Changes:
- api.ts: Updated all API functions to use course_id instead of course_name
- getCourses returns enriched data: course_code, course_name, school, dept
- addCourse, updateCourseColor, deleteCourse all use course_id
- startSession accepts optional course_id parameter
- saveAssignments uses course_id
Database Schema Migration (already applied in Supabase):
- courses table is now canonical (no user_id)
- user_courses is the enrollment join table
- All dependent tables use course_id FK: assignments, sessions, graph_nodes,
documents, study_guides
- New tables: course_concept_stats, course_summary
- Removed: course_context table
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:25dedba
Status:🚫 Build failed.

View logs

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae51972-68a5-4960-8bee-39fab9ab3079

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
MemberAuthor

Superseded by combined PR #53 (course_id migration + calendar normalization). All migration changes are included there.

@AndresL230
AndresL230 deleted the refactor/course-id-schema branch April 15, 2026 01:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Jose-Gael-Cruz-Lopez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Refactor: Migrate from course_name strings to course_id FKs - #51

Closed
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema
Closed

Refactor: Migrate from course_name strings to course_id FKs#51
Jose-Gael-Cruz-Lopez wants to merge 1 commit into
mainfrom
refactor/course-id-schema

Conversation

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
Member

Summary

This PR refactors the backend and frontend to use the new database schema where courses are canonical (no user_id) and user_courses is the enrollment join table.

Database Changes (already applied in Supabase)

  • courses is now canonical (no user_id): id, course_code, course_name, department, school, etc.
  • user_courses is the enrollment join table
  • All dependent tables now use course_id FK to courses.id:
    • assignments, sessions, graph_nodes, documents, study_guides
  • New tables: course_concept_stats, course_summary
  • Removed: course_context table

Backend Changes

services/course_context_service.py (COMPLETE REWRITE)

  • Aggregates graph_nodes mastery data across all students enrolled in a course
  • Computes avg_mastery_score, pct_mastered, pct_struggling, pct_unexplored per concept
  • Pulls common_misconceptions, effective_explanations, prerequisite_gaps from quiz_context
  • Upserts into course_concept_stats keyed on (course_id, concept_name, semester)
  • Maintains course_summary with top 5 struggling/mastered concepts
  • Regenerates summary_text via Gemini only when data hash changes

services/graph_service.py

  • Updated to join user_courses -> courses for enrolled courses
  • get_graph: builds subject_root hubs from canonical courses (course_code + course_name)
  • apply_graph_update: now accepts course_id parameter for all node inserts/updates
  • get_courses: returns enriched data: course_code, course_name, school, department, color, nickname

routes/graph.py

  • Course endpoints now accept course_id instead of course_name
  • Returns joined data from user_courses + courses

routes/learn.py

  • Sessions now store course_id instead of resolving from topic strings
  • start-session accepts optional course_id parameter
  • Passes course_id through to apply_graph_update

routes/calendar.py

  • save endpoint uses course_id instead of course_name
  • upcoming/all endpoints join with courses to return course_code and course_name

models/init.py

  • Added course_id fields to StartSessionBody, AssignmentItem, AddCourseBody

Frontend Changes

src/lib/api.ts

  • getCourses: returns EnrolledCourse with course_code, course_name, school, department, etc.
  • addCourse: takes courseId instead of courseName
  • updateCourseColor, deleteCourse: use courseId
  • startSession: accepts optional courseId parameter
  • saveAssignments: uses course_id in SaveAssignmentItem

Testing

  • All backend modules import successfully
  • Pydantic models validate correctly with new course_id fields
  • Frontend TypeScript types are updated

Migration Notes

  • Frontend components that called addCourse(userId, courseName) need to now call addCourse(userId, courseId) where courseId is from the canonical courses catalog
  • The enrollment flow should first show available courses, then enroll via course_id

Commit:25dedba
Branch: refactor/course-id-schema

This is a major schema refactoring to support canonical courses:
Backend Changes:
- course_context_service.py: Complete rewrite to use new course_concept_stats
and course_summary tables with Gemini-powered summary generation
- graph_service.py: Updated to join user_courses->courses, use course_id FK
- routes/graph.py: Endpoints now accept course_id instead of course_name
- routes/learn.py: Sessions store course_id, pass through to graph updates
- routes/calendar.py: Assignments use course_id, join with courses for display
- calendar_service.py: Updated to use course_id instead of course_name
- models/__init__.py: Added course_id fields to Pydantic models
Frontend Changes:
- api.ts: Updated all API functions to use course_id instead of course_name
- getCourses returns enriched data: course_code, course_name, school, dept
- addCourse, updateCourseColor, deleteCourse all use course_id
- startSession accepts optional course_id parameter
- saveAssignments uses course_id
Database Schema Migration (already applied in Supabase):
- courses table is now canonical (no user_id)
- user_courses is the enrollment join table
- All dependent tables use course_id FK: assignments, sessions, graph_nodes,
documents, study_guides
- New tables: course_concept_stats, course_summary
- Removed: course_context table
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:25dedba
Status:🚫 Build failed.

View logs

@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae51972-68a5-4960-8bee-39fab9ab3079

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jose-Gael-Cruz-Lopez

Copy link
Copy Markdown
MemberAuthor

Superseded by combined PR #53 (course_id migration + calendar normalization). All migration changes are included there.

@AndresL230
AndresL230 deleted the refactor/course-id-schema branch April 15, 2026 01:25
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Jose-Gael-Cruz-Lopez