Skip to content

Commit

Permalink
comment UI progress
Browse files Browse the repository at this point in the history
  • Loading branch information
luke-rt committed Apr 22, 2024
1 parent 177eff6 commit 3b1a18e
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 10 deletions.
28 changes: 24 additions & 4 deletions frontend/review/public/static/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -439,13 +439,13 @@ input {
}

#course-details-comments .list {
width: 200px;
width: 100px;
float: left;
padding-right: 10px;
}

#course-details-comments .list div {
padding: 5px;
padding: 10px;
font-size: 1.1em;
border-radius: 3px;
cursor: pointer;
Expand All @@ -458,9 +458,29 @@ input {

#course-details-comments .comments {
width: calc(100% - 200px);
padding-left: 10px;
float: left;
border-left: 1px solid #eee;
border: 1px solid #eee;
border-radius: 5px;
}

#course-details-comments .comment {
border-bottom: 1px solid #eee;
padding: 10px 20px;
}

#course-details-comments .comment .top {
display: flex;
align-items: center;
}

#course-details-comments .comment .top b {
color: black;
font-size: 1.2em;
}

#course-details-comments .comment .top sub {
color: #b2b2b2;
margin-left: 10px;
}

.table-search {
Expand Down
167 changes: 162 additions & 5 deletions frontend/review/src/components/DetailsBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
orderColumns,
toNormalizedSemester
} from "../utils/helpers";
import { apiHistory } from "../utils/api";
import { apiComments, apiHistory } from "../utils/api";
import { PROF_IMAGE_URL } from "../constants/routes";
import { REGISTRATION_METRICS_COLUMNS } from "../constants";

Expand Down Expand Up @@ -82,6 +82,161 @@ const formsCol = {
* The box below the course ratings table that contains student comments and semester information.
*/
export const DetailsBox = forwardRef(
({ course, instructor, url_semester, type, isCourseEval }, ref) => {
if((type === "course" && instructor) || (type === "instructor")) {
return (
<SelectedDetailsBox
course={course}
instructor={instructor}
url_semester={url_semester}
type={type}
isCourseEval={isCourseEval}
ref={ref}
/>
);
} else {
return (
<UnselectedDetailsBox
course={course}
instructor={instructor}
url_semester={url_semester}
type={type}
isCourseEval={isCourseEval}
ref={ref}
/>
);
}
}
)

const UnselectedDetailsBox = forwardRef(
({ course, instructor, url_semester, type, isCourseEval }, ref) => {
const [data, setData] = useState({});
const [isLoading, setIsLoading] = useState(false);

const [selectedSemester, setSelectedSemester] = useState(null);
const [semesterList, setSemesterList] = useState([]);

useEffect(() => {
setIsLoading(true);
apiComments(course)
.then(res => {
console.log(res);
const semesterSet = new Set(
res.comments
.map(c => c.semester)
.sort(compareSemesters)
);
const semesters = [...semesterSet];
setData(res);
setSemesterList(semesters);
})
.finally(() => {
setIsLoading(false);
});
}, [course]);

const hasData = Boolean(Object.keys(data).length) && data.comments.length > 0;

if (!hasData) {
if(isLoading) {
// Loading spinner
return (
<div
id="course-details"
className="box"
style={{ textAlign: "center", padding: 45 }}
ref={ref}
>
<i
className="fa fa-spin fa-cog fa-fw"
style={{ fontSize: "150px", color: "#aaa" }}
/>
<h1 style={{ fontSize: "2em", marginTop: 15 }}>Loading...</h1>
</div>
);
} else {
// Return placeholder image.
return (
<div
id="course-details"
className="box"
ref={ref}
style={{ textAlign: "center" }}
>
<div>
<div>
<object
type="image/svg+xml"
id="select-course-icon"
data="/static/image/books-and-bag.svg"
width="250"
>
<img alt="Class Icon" src="/static/image/books-and-bag.png" />
</object>
</div>
</div>
<h3
style={{ color: "#b2b2b2", margin: "1.5em", marginBottom: ".5em" }}
>
No one's commented yet! Be the first to share your thoughts.
</h3>
</div>
);

}
}

return (
<div
id="course-details"
className="box"
ref={ref}
>
<div id="course-details-wrapper">
<h3>
Comments
</h3>
<div id="course-details-comments" className="clearfix mt-2">
<div className="list">
<div
onClick={() => setSelectedSemester(null)}
className={selectedSemester === null ? "selected" : ""}
>
Overall
</div>
{semesterList.map(sem => (
<div
key={sem}
onClick={() => setSelectedSemester(sem)}
className={selectedSemester === sem ? "selected" : ""}
>
{sem}
</div>
))}
</div>
<div className="comments">
{data.comments
.filter(c => !selectedSemester || c.semester === selectedSemester)
.map(c =>
<div key={c.id} className="comment">
<div className="top">
<b>{c.title}</b>
<sub>{c.modified_at.toLocaleString("en-US")}</sub>
</div>
<p>{c.content}</p>
</div>
)
}
</div>
</div>
</div>
</div>
)
}
);

const SelectedDetailsBox = forwardRef(
({ course, instructor, url_semester, type, isCourseEval }, ref) => {
const [data, setData] = useState({});
const [viewingRatings, setViewingRatings] = useState(true);
Expand Down Expand Up @@ -129,6 +284,7 @@ export const DetailsBox = forwardRef(
if (instructor !== null && course !== null) {
apiHistory(course, instructor, url_semester)
.then(res => {
console.log(res);
const sections = Object.values(res.sections);
const fields = [
...new Set(
Expand Down Expand Up @@ -174,7 +330,7 @@ export const DetailsBox = forwardRef(
const isCourse = type === "course";

// Return loading component. TODO: Add spinner/ghost loader.
if (!hasData && hasSelection && isLoading)
if (!hasData && hasSelection && isLoading) {
return (
<div
id="course-details"
Expand All @@ -189,9 +345,9 @@ export const DetailsBox = forwardRef(
<h1 style={{ fontSize: "2em", marginTop: 15 }}>Loading...</h1>
</div>
);

}
// Return placeholder image.
if (!hasData || !hasSelection)
if (!hasData || !hasSelection) {
return (
<div
id="course-details"
Expand Down Expand Up @@ -226,7 +382,8 @@ export const DetailsBox = forwardRef(
</h3>
</div>
);

}

const {
instructor: { name },
sections
Expand Down
2 changes: 1 addition & 1 deletion frontend/review/src/pages/ReviewPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,10 @@ export class ReviewPage extends Component {
<DetailsBox
type={type}
course={code}
url_semester={url_semester}
instructor={rowCode}
isCourseEval={isCourseEval}
ref={this.tableRef}
url_semester={url_semester}
/>
)}

Expand Down
73 changes: 73 additions & 0 deletions frontend/review/src/utils/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,79 @@ export function apiReviewData(type, code, semester) {
);
}

export function apiComments(code) {
if(code === "CIS-1200") {
return Promise.resolve({
comments: [
{
title: "Hi 1",
content: "I love this course :)",
id: 10,
created_at: new Date(),
modified_at: new Date(),
author_name: "Luke Tong",
likes: 69,
course: "CIS-1200",
semester: "2024A",
parent_id: null,
path: "10",
},
{
title: "Hi 2",
content: "Luke is so cool and awesome",
id: 11,
created_at: new Date(new Date() - 10),
modified_at: new Date(new Date() - 10),
author_name: "Penn Labs",
likes: 100,
course: "CIS-1200",
semester: "2024A",
parent_id: 10,
path: "10.11",
},
{
title: "Hi 3",
content: "I hate this course :(",
id: 20,
created_at: new Date(new Date() - 10),
modified_at: new Date(new Date() - 10),
author_name: "Shiva Mehta",
likes: 0,
course: "CIS-1200",
semester: "2022A",
parent_id: null,
path: "20",
},
{
title: "Hi 4",
content: "I TA this course :|",
id: 30,
created_at: new Date(new Date() - 5),
modified_at: new Date(new Date() - 5),
author_name: "Eunsoo Shin",
likes: 10,
course: "CIS-1200",
semester: "2022A",
parent_id: null,
path: "30",
},
],
});
} else {
return Promise.resolve({
comments: [],
})
}

/*
return apiFetch(
`${API_DOMAIN}/api/review/${encodeURIComponent(type)}/${encodeURIComponent(
code
)}/comments?token=${encodeURIComponent(API_TOKEN)}` + getSemesterQParam(semester)
);
*/
}

export function apiContact(name) {
return apiFetch(
`https://api.pennlabs.org/directory/search?name=${encodeURIComponent(name)}`
Expand Down

0 comments on commit 3b1a18e

Please sign in to comment.