Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
9c1a60c
Added Q&A to sidebar
Nathan-Kimm Nov 21, 2025
b54f8c3
Added routing for qa
Nathan-Kimm Nov 23, 2025
1696b44
Added front end design for Q&A dashboard
Nathan-Kimm Jan 18, 2026
02ac760
Merge pull request #1216 from thecourseforum/dev
IshanA2007 Jan 18, 2026
05b0bf4
Removed QA test from sidebar
Nathan-Kimm Jan 18, 2026
53d19d6
Reply Icon
rohansoma Jan 18, 2026
4c5e2b2
Final Design Modifications
rohansoma Jan 19, 2026
561d90e
Final Design Changes
rohansoma Jan 19, 2026
697208f
Dash Changes
rohansoma Jan 19, 2026
3f07ee5
Design Changes
rohansoma Jan 19, 2026
b647180
Added forum
Nathan-Kimm Jan 19, 2026
6501ce8
Merge pull request #1222 from thecourseforum/dev
Nathan-Kimm Feb 4, 2026
e632963
Created post listing and updated models
Nathan-Kimm Feb 4, 2026
1cdb6c4
Updated post listing and added css/html for left sidebar
Nathan-Kimm Feb 4, 2026
035baa5
Added content side of questions and started post modal and publishing…
Nathan-Kimm Feb 7, 2026
b638d4c
docs: add Q&A dashboard design document
IshanA2007 Mar 1, 2026
cc14261
docs: add Q&A dashboard implementation plan
IshanA2007 Mar 1, 2026
c937751
fix(qa): fix create_question view and add title to QuestionForm
IshanA2007 Mar 1, 2026
6459da6
feat(qa): update qa_dashboard with search, course filter, vote annota…
IshanA2007 Mar 2, 2026
20ea4ca
fix(qa): guard against non-int ?question= param and remove double-query
IshanA2007 Mar 2, 2026
a54539d
feat(qa): add question_detail AJAX endpoint
IshanA2007 Mar 2, 2026
6749de5
fix(qa): export question_detail view and clarify semesters comment
IshanA2007 Mar 2, 2026
1d35d31
feat(qa): add course search and instructor API endpoints
IshanA2007 Mar 2, 2026
da80810
fix(qa): filter hidden instructors, move imports to module level, imp…
IshanA2007 Mar 2, 2026
e39f8b9
feat(qa): export all new qa views from views/__init__.py
IshanA2007 Mar 2, 2026
2c1c566
fix(qa): remove unreachable duplicate return statements in downvote_a…
IshanA2007 Mar 2, 2026
4928ccf
feat(qa): add full _question_detail.html partial template
IshanA2007 Mar 2, 2026
92eae97
fix(qa): only render hr separator between answers, not after the last…
IshanA2007 Mar 2, 2026
9a1fb5b
feat(qa): update qa_dashboard.html with wired sidebar, modals, and AJ…
IshanA2007 Mar 2, 2026
4fc9d1d
feat(qa): rewrite qa_dashboard.js with full interactive functionality
IshanA2007 Mar 2, 2026
809b5a0
fix(qa): add missing datetime import in edit views
IshanA2007 Mar 2, 2026
3f5c824
test(qa): add integration smoke test for full Q&A flow
IshanA2007 Mar 2, 2026
1f517b3
fix(qa): robust delete AJAX, remove debug print, allow unauthenticate…
IshanA2007 Mar 2, 2026
929984a
fix(qa): correct getInstructors URL construction — broken .replace ma…
IshanA2007 Mar 2, 2026
3dd0385
fix: editing, ux
IshanA2007 Mar 2, 2026
2361617
Fix: Course search to only show recent courses
Nathan-Kimm Mar 3, 2026
faedfcb
fix: Added delete question modal and removed downvoting. Fixed reply …
Nathan-Kimm Mar 3, 2026
da84bdf
fix: Fixed upvote highlighting
Nathan-Kimm Mar 3, 2026
be2ffdd
Fix: changed filter icon
Nathan-Kimm Mar 3, 2026
ca34387
Added instructor card. Fixed and added answer deletion modal.
Nathan-Kimm Mar 3, 2026
fd210de
feat: Added reply to answer functionality
Nathan-Kimm Mar 4, 2026
85075cc
Design Changes
rohansoma Mar 15, 2026
454e4c7
Design Changes
rohansoma Mar 16, 2026
a0b9495
fix: avoid full page refresh when searching questions
Nathan-Kimm Mar 31, 2026
c92ad2e
Design Changes
rohansoma Apr 5, 2026
a33490e
fix: Removed instructor card and moved instructor name to below course
Nathan-Kimm Apr 6, 2026
25297e5
fix: Added reply nesting and updated answer counting
Nathan-Kimm Apr 6, 2026
65a3777
fix: Changed instructor and course styling
Nathan-Kimm Apr 6, 2026
5e0d56e
Design Changes
rohansoma Apr 6, 2026
7e9d1f7
fix: Fixed merge conflict
Nathan-Kimm Apr 6, 2026
5d82d72
Fix: added tooltip
Nathan-Kimm Apr 6, 2026
60ba667
Filters
rohansoma Apr 20, 2026
3d5894b
Removed implementation documents
Nathan-Kimm Apr 20, 2026
f7eeb77
removed forum
Nathan-Kimm Apr 24, 2026
dcd2d4f
Fix: changed css bug with likes
Nathan-Kimm Apr 24, 2026
d34b906
Fix: changed models.cascade to SET_NULL and soft-deleted answers
Nathan-Kimm Apr 25, 2026
9f30179
Fixed coderabbit ai recommendations
Nathan-Kimm Apr 25, 2026
6b2eaa4
(fix): Changed migration 0024 name
Nathan-Kimm Apr 26, 2026
6276c12
(fix): Added 'not taken' tag on answers and removed success messages
Nathan-Kimm May 2, 2026
b8a44e3
(fix): Allowed users to reply to questions multiple times and also ma…
Nathan-Kimm May 2, 2026
32eb53a
Did coderabbit suggested changes
Nathan-Kimm May 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions tcf_website/migrations/0024_question_title.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.28 on 2026-02-04 05:13

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("tcf_website", "0023_remove_sectionenrollment_section_and_more"),
]

operations = [
migrations.AddField(
model_name="question",
name="title",
field=models.CharField(blank=True, max_length=200),
),
]
Comment on lines +1 to +18
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Apr 24, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Migration filename doesn't match its operations.

The filename 0024_forumcategory_forumpost_forumresponse_question_title_and_more.py implies new ForumCategory, ForumPost, and ForumResponse models plus a Question.title field, but the file only contains a single AddField for Question.title. This suggests either leftover scaffolding from an abandoned approach or a partially-squashed migration. Renaming to something like 0024_question_title.py would prevent future confusion (rename only if the migration hasn't been applied to any deployed environment yet — otherwise leave it).

🧰 Tools
🪛 Ruff (0.15.11)

[warning] 8-10: Mutable default value for class attribute

(RUF012)


[warning] 12-18: Mutable default value for class attribute

(RUF012)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@tcf_website/migrations/0024_forumcategory_forumpost_forumresponse_question_title_and_more.py`
around lines 1 - 18, The migration file name implies multiple model changes but
the Migration only adds a Question.title CharField via the AddField operation
(model_name="question", name="title"); if this migration has not been applied
anywhere, rename the file to reflect the single change (e.g.,
0024_question_title.py) to avoid confusion; if the migration has already been
applied in any environment, do not rename—leave the filename and instead add a
new, clearly named migration for any further model additions (or revert and
re-create migrations consistently) and verify the Migration class still depends
on ("tcf_website", "0023_remove_sectionenrollment_section_and_more") and
contains the AddField operation unchanged.

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.

+1 on this 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.

@brandonistfan, thanks for the endorsement! To summarize the recommendation for the PR author:

The file tcf_website/migrations/0024_forumcategory_forumpost_forumresponse_question_title_and_more.py only contains a single AddField operation for Question.title, but its name implies the creation of ForumCategory, ForumPost, and ForumResponse models — none of which exist in this file. This is likely scaffolding left over from an earlier, broader plan.

Recommended action:

  • If this migration has not yet been applied to any shared/deployed environment (staging, production, teammates' local DBs): rename the file to something like 0024_question_title.py and update the dependencies reference in 0025_question_instructor_optional.py to match the new name.
  • If it has already been applied: leave the filename as-is (renaming would break Django's migration history) and simply move on — the misleading name is cosmetic at that point.

25 changes: 25 additions & 0 deletions tcf_website/migrations/0025_question_instructor_optional.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated manually

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("tcf_website", "0024_question_title"),
]

operations = [
migrations.AlterField(
model_name="question",
name="instructor",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="tcf_website.instructor",
),
),
]
25 changes: 25 additions & 0 deletions tcf_website/migrations/0026_answer_parent_answer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.2.28 on 2026-03-04 00:02

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("tcf_website", "0025_question_instructor_optional"),
]

operations = [
migrations.AddField(
model_name="answer",
name="parent_answer",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="replies",
to="tcf_website.answer",
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.2.28 on 2026-03-04 00:11

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("tcf_website", "0026_answer_parent_answer"),
]

operations = [
migrations.RemoveConstraint(
model_name="answer",
name="unique answer per user and question",
),
migrations.AddConstraint(
model_name="answer",
constraint=models.UniqueConstraint(
condition=models.Q(("parent_answer__isnull", True)),
fields=("user", "question"),
name="unique answer per user and question",
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated manually

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("tcf_website", "0027_remove_answer_unique_answer_per_user_and_question_and_more"),
]

operations = [
migrations.AddField(
model_name="question",
name="department",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="tcf_website.department",
),
),
migrations.AlterField(
model_name="question",
name="course",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="tcf_website.course",
),
),
]
22 changes: 22 additions & 0 deletions tcf_website/migrations/0029_alter_answer_semester.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("tcf_website", "0028_question_department_and_optional_course"),
]

operations = [
migrations.AlterField(
model_name="answer",
name="semester",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=models.SET_NULL,
to="tcf_website.semester",
),
),
Comment on lines +11 to +21
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

on_delete=CASCADE on the now-nullable semester FK risks silent data loss — see models.py.

The Django docs explicitly show SET_NULL as the correct on_delete choice for a nullable ForeignKey. With CASCADE, deleting any Semester row will also delete all Answer rows that reference it — including answers that merely tagged a semester for context. Since the intent of making the field nullable is to represent "Not Taken" (no semester), SET_NULL is the correct semantic.

Fix both this migration and the field definition in models.py:

🛡️ Proposed fix
-                on_delete=django.db.models.deletion.CASCADE,
+                on_delete=django.db.models.deletion.SET_NULL,

Update models.py correspondingly (see detailed comment there).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
migrations.AlterField(
model_name="answer",
name="semester",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="tcf_website.semester",
),
),
migrations.AlterField(
model_name="answer",
name="semester",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="tcf_website.semester",
),
),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tcf_website/migrations/0029_alter_answer_semester.py` around lines 12 - 22,
The migration AlterField for model "answer" and the corresponding ForeignKey in
models.py use on_delete=CASCADE which will delete Answer rows when a Semester is
removed; change both the migration (0029_alter_answer_semester.py) and the
Answer model's semester field to use on_delete=models.SET_NULL (and keep
null=True, blank=True, default=None) so deleting a Semester sets semester to
NULL instead of cascading deletions; also ensure the migration imports models
(or django.db.models.deletion) and references models.SET_NULL consistently and
update the models.py import if necessary.

]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.28 on 2026-05-01

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("tcf_website", "0029_alter_answer_semester"),
]

operations = [
migrations.RemoveConstraint(
model_name="answer",
name="unique answer per user and question",
),
]
Loading