diff --git a/backend/courses/util.py b/backend/courses/util.py
index 05b295c8..ad5e55f7 100644
--- a/backend/courses/util.py
+++ b/backend/courses/util.py
@@ -30,6 +30,7 @@
StatusUpdate,
User,
)
+
from review.management.commands.mergeinstructors import resolve_duplicates
@@ -738,11 +739,10 @@ def get_section_from_course_instructor_semester(course_code, professors, semeste
if not course_topic:
raise ValueError(f"No topic exists for course with code ({course_code})")
course_topic_parent = course_topic.most_recent.full_code
- sections = Section.objects.prefetch_related("instructors").filter(
+ sections = Section.objects.all().prefetch_related("instructors").filter(
course__topic__most_recent__full_code=course_topic_parent, course__semester=semester
)
- print(sections.first())
- print(sections[0].instructors)
+ print(sections)
print("HIGH")
professors_query = Q(instructors__name=professors[0])
for professor in professors[1:]:
diff --git a/backend/review/views.py b/backend/review/views.py
index a1bd01a6..9949298c 100644
--- a/backend/review/views.py
+++ b/backend/review/views.py
@@ -18,7 +18,7 @@
PreNGSSRestriction,
Section,
)
-from courses.serializers import CommentListSerializer, CommentSerializer
+from courses.serializers import CommentListSerializer, CommentSerializer, CourseDetailSerializer
from courses.util import (
get_current_semester,
get_or_create_add_drop_period,
@@ -882,7 +882,7 @@ def get(self, request, semester, course_code):
queryset = og_queryset = self.get_queryset()
- print(queryset)
+ print("I AM INSTRUCTOR", instructor)
# add filters
if semester_arg != "all":
queryset = queryset.all().filter(section__course__semester=semester_arg)
@@ -925,18 +925,25 @@ def get(self, request, semester, course_code):
def get_queryset(self):
course_code = self.kwargs["course_code"]
+
semester = self.kwargs["semester"] or "all"
+
+ print(semester)
+
print("I MADE IT HERE", semester)
try:
if semester == "all":
- course = Course.objects.filter(full_code=course_code).latest("semester")
+ course = Course.objects.all().filter(full_code=course_code).first()
else:
print("HI1")
course = get_course_from_code_semester(course_code, None)
print("HI2")
except Http404:
return Response({"message": "Course not found."}, status=status.HTTP_404_NOT_FOUND)
+ print(CourseDetailSerializer(course).data)
+
topic = course.topic
+ print("this is a topic", topic)
return Comment.objects.filter(section__course__topic=topic)
@@ -1009,6 +1016,7 @@ class CommentViewSet(viewsets.ModelViewSet):
def retrieve(self, request, pk=None):
comment = get_object_or_404(Comment, pk=pk)
+ print("this is a comment")
return Response(comment, status=status.HTTP_200_OK)
def create(self, request):
@@ -1030,6 +1038,7 @@ def create(self, request):
request.data.get("instructor"),
request.data.get("semester"),
)
+ print("ran this")
print(section)
except Exception as e:
print(e)
@@ -1038,12 +1047,13 @@ def create(self, request):
# create comment and send response
parent_id = request.data.get("parent")
- print(parent_id)
+ print("new section", section)
+ print("new comment section", section.course.topic)
parent = get_object_or_404(Comment, pk=parent_id) if parent_id is not None else None
comment = Comment.objects.create(
text=request.data.get("text"), author=request.user, section=section, parent=parent
)
- print("this is a commnet lol")
+ print("this is a commnet lol", comment)
base = parent.base if parent else comment
prefix = parent.path + "." if parent else ""
path = prefix + "{:0{}d}".format(comment.id, 10)
diff --git a/frontend/review/package.json b/frontend/review/package.json
index ca348bdd..de6a469b 100644
--- a/frontend/review/package.json
+++ b/frontend/review/package.json
@@ -27,7 +27,7 @@
},
"scripts": {
"dev": "NODE_OPTIONS=--openssl-legacy-provider react-scripts start",
- "start": "NODE_OPTIONS=--openssl-legacy-provider react-scripts start",
+ "start": "set NODE_OPTIONS=--openssl-legacy-provider && react-scripts start",
"build": "NODE_OPTIONS=--openssl-legacy-provider react-scripts build",
"test": "exit 0",
"eject": "react-scripts eject",
@@ -52,6 +52,7 @@
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-react": "^7.18.0",
"eslint-plugin-standard": "^4.0.1",
- "prettier": "^1.19.1"
+ "prettier": "^1.19.1",
+ "react-error-overlay": "6.0.9"
}
}
diff --git a/frontend/review/src/components/Comments/WriteComment.js b/frontend/review/src/components/Comments/WriteComment.js
index fe896f97..5dc8c694 100644
--- a/frontend/review/src/components/Comments/WriteComment.js
+++ b/frontend/review/src/components/Comments/WriteComment.js
@@ -1,85 +1,108 @@
-import React, { useState, forwardRef, useEffect } from 'react';
-import { Dropdown } from '../common/Dropdown';
-import { apiPostComment, apiLive } from '../../utils/api';
-import { compareSemesters } from '../../utils/helpers';
+import React, { useState, forwardRef, useEffect } from "react";
+import { Dropdown } from "../common/Dropdown";
+import { apiPostComment, apiLive } from "../../utils/api";
+import { compareSemesters } from "../../utils/helpers";
-export const WriteComment = forwardRef(({ course, setUserComment }, ref) => {
+export const WriteComment = forwardRef(
+ ({ course, setUserComment, instructor, semestersList }, ref) => {
const [isEditing, setIsEditing] = useState(false);
const [content, setContent] = useState("");
const [semester, setSemester] = useState("2022A");
- const [semestersList, setSemestersList] = useState(["2024A", "2023B", "2023A"]);
+ const [activeSemesters, setActiveSemesters] = useState([]);
+
+
+ console.log(instructor)
+ console.log(semestersList);
+
+ useEffect(() => {
+ if (isEditing) {
+ }
+ }, [course, isEditing]);
useEffect(() => {
- if (isEditing) {
- }
- }, [course, isEditing])
+ if (semestersList) {
+ const semList = semestersList.map((s) => s.semester);
+ setActiveSemesters(semList);
+ setSemester(semList[0]);
+ }
+ }, [semestersList]);
const handleSubmit = () => {
- console.log("Comment submitted");
- apiPostComment(course, semester, content).then(res => {
- console.log(res)
- res = {...res, created_at: new Date(res.created_at), modified_at: new Date(res.modified_at)}
- setUserComment(res)
- });
- // setUserComment({
- // content: content,
- // id: 1,
- // created_at: new Date(),
- // modified_at: new Date(),
- // author_name: "Engineering Student",
- // likes: 0,
- // course: course,
- // semester: semester,
- // professorId: [130],
- // parent_id: null,
- // path: "1",
- // replies: 0
- // })
- }
+ console.log("Comment submitted");
+ apiPostComment(course, semester, content, instructor).then((res) => {
+ console.log(res);
+ res = {
+ ...res,
+ created_at: new Date(res.created_at),
+ modified_at: new Date(res.modified_at),
+ };
+ setUserComment(res);
+ });
+ // setUserComment({
+ // content: content,
+ // id: 1,
+ // created_at: new Date(),
+ // modified_at: new Date(),
+ // author_name: "Engineering Student",
+ // likes: 0,
+ // course: course,
+ // semester: semester,
+ // professorId: [130],
+ // parent_id: null,
+ // path: "1",
+ // replies: 0
+ // })
+ };
- return(
-
setIsEditing(true)}
- tabIndex={100}
- ref={ref}
- >
- {isEditing &&
-
- {semestersList.map((s, i) => (
- {setSemester(s); console.log(s)}}
- >
- {s}
-
- ))}
- }
-
- )
-});
\ No newline at end of file
+ return (
+ setIsEditing(true)}
+ tabIndex={100}
+ ref={ref}
+ >
+ {isEditing && (
+
+ {activeSemesters.map((s, i) => (
+ {
+ setSemester(s);
+ }}
+ >
+ {s}
+
+ ))}
+
+ )}
+
+ );
+ }
+);
diff --git a/frontend/review/src/components/DetailsBox.js b/frontend/review/src/components/DetailsBox.js
index 8d83f3d2..05a52516 100644
--- a/frontend/review/src/components/DetailsBox.js
+++ b/frontend/review/src/components/DetailsBox.js
@@ -7,7 +7,7 @@ import {
compareSemesters,
getColumnName,
orderColumns,
- toNormalizedSemester
+ toNormalizedSemester,
} from "../utils/helpers";
import { apiComments, apiHistory, apiComment } from "../utils/api";
import { PROF_IMAGE_URL } from "../constants/routes";
@@ -25,7 +25,7 @@ const semesterCol = {
Cell: ({ value, original }) => {value} ,
sortMethod: compareSemesters,
show: true,
- required: true
+ required: true,
};
const nameCol = {
@@ -38,7 +38,7 @@ const nameCol = {
filterMethod: ({ value }, { name, semester }) =>
value === "" || // If the filter value is blank, all
name.toLowerCase().includes(value.toLowerCase()) ||
- semester.toLowerCase().includes(value.toLowerCase())
+ semester.toLowerCase().includes(value.toLowerCase()),
};
const codeCol = {
@@ -47,7 +47,7 @@ const codeCol = {
Header: "Course Code",
accessor: "course_code",
Cell: ({ value, original }) => {value} ,
- show: true
+ show: true,
};
const activityCol = {
@@ -56,7 +56,7 @@ const activityCol = {
accessor: "activity",
width: 150,
Cell: ({ value, original }) => {value} ,
- show: true
+ show: true,
};
const formsCol = {
@@ -76,7 +76,7 @@ const formsCol = {
({((value / original.forms_produced) * 100).toFixed(1)}%)
- )
+ ),
};
/**
@@ -84,59 +84,102 @@ const formsCol = {
*/
export const DetailsBox = forwardRef(
({ course, instructor, url_semester, type, isCourseEval }, ref) => {
- const [ viewRatings, setViewRatings ] = useState(false);
+ const [viewRatings, setViewRatings] = useState(false);
return (
<>
- setViewRatings(true)}>Ratings
- setViewRatings(false)}>Comments
+ setViewRatings(true)}
+ >
+ Ratings
+
+ setViewRatings(false)}
+ >
+ Comments
+
-
-
>
- )
+ );
}
);
const CommentsTab = forwardRef(
({ course, instructor, url_semester, type, isCourseEval, active }, ref) => {
const [semesterList, setSemesterList] = useState([]);
- const [isLoading, setIsLoading] = useState(false);
+ const [isLoading1, setIsLoading1] = useState(false);
+ const [isLoading2, setIsLoading2] = useState(false);
+
+ const [data, setData] = useState({});
const [comments, setComments] = useState({});
const [userComment, setUserComment] = useState({});
const [selectedSemester, setSelectedSemester] = useState(null);
+ console.log("CHECKPOINT 1")
+
+ const hasSelection =
+ (type === "course" && instructor) || (type === "instructor" && course);
+
+
useEffect(() => {
- setIsLoading(true);
- apiComments(course, "all", null, null)
- .then(res => {
+ console.log("tihs is instructor", instructor);
+ setIsLoading2(true);
+ apiComments(course, "all", instructor, null)
+ .then((res) => {
console.log("fetching comments now", res);
- setComments(res.comments.map(c => ({ ...c, created_at: new Date(c.created_at), modified_at: new Date(c.modified_at) })));
+ setComments(
+ res.comments.map((c) => ({
+ ...c,
+ created_at: new Date(c.created_at),
+ modified_at: new Date(c.modified_at),
+ }))
+ );
setSemesterList(res.semesters);
})
.finally(() => {
- setIsLoading(false);
+ setIsLoading2(false);
});
- }, [course]);
+ }, [course, instructor]);
+
+ useEffect(() => {
+ console.log("CHECKPOINT 2")
+ setIsLoading1(true);
+ if (instructor !== null && course !== null) {
+ apiHistory(course, instructor, url_semester)
+ .then((res) => {
+ console.log("fetching ratings");
+
+ console.log(res);
+ setData(res);
+ })
+ .finally(() => {
+ setIsLoading1(false);
+ });
+ }
+ }, [course, instructor, url_semester]);
useEffect(() => {
// TODO: HARDCODED USER ID BC CANT YET FETCH WHICH COMMENT BELONGS TO WHICH USER
@@ -145,15 +188,42 @@ const CommentsTab = forwardRef(
// });
}, [course]);
+
+ console.log("CHECKPOINT 2")
+ const hasData = Boolean(Object.keys(data).length);
+ const isCourse = type === "course";
+
+ if (!hasSelection && active) {
+ return ;
+ }
+
+
+ if (!active) return <>>;
+
+ // Return loading component. TODO: Add spinner/ghost loader.
+ if (!hasData && hasSelection && isLoading2) {
+ return ;
+ }
+ // Return placeholder image.
+ if (!hasData) {
+ return ;
+ }
+
+ // const {
+ // instructor: { name },
+ // sections,
+ // } = data;
+ // const sectionsList = Object.values(sections);
+
const hasComments = comments.length > 0;
const hasUserComment = Object.keys(userComment).length > 0;
- if(!active) return <>>
+ // if (!active) return <>>;
if (!hasComments && !hasUserComment) {
- if (isLoading) {
+ if (isLoading2) {
// Loading spinner
- return
+ return ;
} else {
// Return placeholder image.
return (
@@ -163,31 +233,43 @@ const CommentsTab = forwardRef(
ref={ref}
style={{ textAlign: "center" }}
>
-
-
-
-
+
+
-
-
+ {isCourse ? data.instructor.name : course}
+
+
+
+
+
+
+
+
+
+
+
+
+ No one's commented yet! Be the first to share your thoughts.
+
-
- No one's commented yet! Be the first to share your thoughts.
-
);
}
@@ -196,14 +278,15 @@ const CommentsTab = forwardRef(
return (
-
Comments
+ {isCourse ? data.instructor.name : "Comments"}
);
@@ -251,7 +335,7 @@ const RatingsTab = forwardRef(
(type === "course" && instructor) || (type === "instructor" && course);
// Return placeholder image.
if (!hasSelection && active) {
- return
+ return ;
}
const [data, setData] = useState({});
@@ -260,10 +344,10 @@ const RatingsTab = forwardRef(
const [filterAll, setFilterAll] = useState("");
const [isLoading, setIsLoading] = useState(false);
- const showCol = info =>
+ const showCol = (info) =>
REGISTRATION_METRICS_COLUMNS.includes(info) === isCourseEval;
- const generateCol = info => {
+ const generateCol = (info) => {
if (!showCol(info)) {
return null;
}
@@ -283,7 +367,7 @@ const RatingsTab = forwardRef(
? value
: value.toFixed(2)}
- )
+ ),
};
};
@@ -291,17 +375,17 @@ const RatingsTab = forwardRef(
setIsLoading(true);
if (instructor !== null && course !== null) {
apiHistory(course, instructor, url_semester)
- .then(res => {
+ .then((res) => {
console.log("fetching ratings");
const sections = Object.values(res.sections);
const fields = [
...new Set(
sections.reduce((r, s) => [...r, ...Object.keys(s.ratings)], [])
- )
+ ),
]; // union of all keys of objects in sections
const ratingCols = orderColumns(fields)
.map(generateCol)
- .filter(col => col);
+ .filter((col) => col);
setData(res);
setColumns([
semesterCol,
@@ -309,7 +393,7 @@ const RatingsTab = forwardRef(
codeCol,
activityCol,
formsCol,
- ...ratingCols
+ ...ratingCols,
]);
})
.finally(() => {
@@ -321,12 +405,11 @@ const RatingsTab = forwardRef(
const hasData = Boolean(Object.keys(data).length);
const isCourse = type === "course";
-
- if(!active) return <>>
+ if (!active) return <>>;
// Return loading component. TODO: Add spinner/ghost loader.
if (!hasData && hasSelection && isLoading) {
- return
+ return ;
}
// Return placeholder image.
if (!hasData) {
@@ -335,7 +418,7 @@ const RatingsTab = forwardRef(
const {
instructor: { name },
- sections
+ sections,
} = data;
const sectionsList = Object.values(sections);
@@ -385,7 +468,7 @@ const RatingsTab = forwardRef(
course_code,
activity,
forms_produced,
- forms_returned
+ forms_returned,
}) => ({
...ratings,
semester: toNormalizedSemester(semester),
@@ -393,7 +476,7 @@ const RatingsTab = forwardRef(
course_code,
activity,
forms_produced,
- forms_returned
+ forms_returned,
})
)}
columns={columns}
@@ -439,16 +522,14 @@ const Placeholder = forwardRef(({ type }, ref) => {
)}
-
+
{type === "course"
? "Select an instructor to see individual sections, comments, and more details."
: "Select a course to see individual sections, comments, and more details."}
);
-})
+});
const Loading = forwardRef(({ type }, ref) => {
return (
diff --git a/frontend/review/src/utils/api.js b/frontend/review/src/utils/api.js
index 00453c9e..a252a825 100644
--- a/frontend/review/src/utils/api.js
+++ b/frontend/review/src/utils/api.js
@@ -277,7 +277,7 @@ export function apiUserComment(course) {
export function apiComments(course, semester, professorId, sortBy) {
return apiFetch(
- `${API_DOMAIN}/api/review/${semester ? encodeURIComponent(semester) : "all"}/course_comments/${encodeURIComponent(course)}`
+ `${API_DOMAIN}/api/review/${"all"}/course_comments/${encodeURIComponent(course)}?instructor=${encodeURIComponent(professorId)}`
)
}
@@ -289,7 +289,7 @@ export function apiComments(course, semester, professorId, sortBy) {
// }
-export function apiPostComment(course, semester, content) {
+export function apiPostComment(course, semester, content, instructor) {
return apiFetch(
`${API_DOMAIN}/api/review/comment`,
{
@@ -302,7 +302,7 @@ export function apiPostComment(course, semester, content) {
body: JSON.stringify({
text: content,
course_code: course,
- instructor: ["Val Breazu. Tannen"],
+ instructor: [instructor],
semester: semester,
})
}
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index a6ca5037..db1bec35 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -14067,6 +14067,11 @@ react-draggable@^4.0.3:
clsx "^1.1.1"
prop-types "^15.8.1"
+react-error-overlay@6.0.9:
+ version "6.0.9"
+ resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
+ integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==
+
react-error-overlay@^6.0.7:
version "6.0.11"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"