Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
45 changes: 40 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 65 additions & 1 deletion src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,73 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import ReviewTable from 'components/HeatGrid/ReviewTable';

import App from './App';

test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});


describe("ReviewTable page", () => {
const setup = () =>
render(
<MemoryRouter initialEntries={["/view-team-grades"]}>
<Routes>
<Route path="/view-team-grades" element={<ReviewTable />} />
</Routes>
</MemoryRouter>
);

test("renders summary report and team info", async () => {
setup();
expect(screen.getByText(/Summary Report: Program 2/i)).toBeInTheDocument();
expect(screen.getByText(/Team:/i)).toBeInTheDocument();
});

test("renders submission links", async () => {
setup();
expect(
screen.getByText("https://github.ncsu.edu/Program-2-Ruby-on-Rails/WolfEvents")
).toBeInTheDocument();
expect(screen.getByText("README.md")).toBeInTheDocument();
});

test("renders round selector", () => {
setup();
expect(screen.getByText(/Round/i)).toBeInTheDocument();
});

test("renders word count checkboxes", () => {
setup();
expect(screen.getByLabelText(/> 10 Word Comments/i)).toBeInTheDocument();
expect(screen.getByLabelText(/> 20 Word Comments/i)).toBeInTheDocument();
});

test("shows Word Count column when checkbox is selected", async () => {
setup();

// Before clicking: Word Count column should not be visible
expect(screen.queryByText(/Word Count/i)).not.toBeInTheDocument();

// Click the checkbox to show word count
const checkbox10 = screen.getByLabelText(/> 10 Word Comments/i);
fireEvent.click(checkbox10);

// Wait for DOM update
await waitFor(() => {
expect(screen.getAllByText(/Word Count/i).length).toBeGreaterThan(0);
});
});

test("toggle sort by total score", () => {
setup();
const button = screen.getByText(/Sort by Total Review Score/i);
fireEvent.click(button);
expect(button.textContent).toMatch(/desc|asc/i);
});
});

2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { loadCourseInstructorDataAndInstitutions } from "pages/Courses/CourseUti
import TA from "pages/TA/TA";
import TAEditor from "pages/TA/TAEditor";
import { loadTAs } from "pages/TA/TAUtil";
import ReviewTable from "./pages/ViewTeamGrades/ReviewTable";
import ReviewTable from "./components/HeatGrid/ReviewTable";
import EditProfile from "pages/Profile/Edit";
import Reviews from "pages/Reviews/reviews";
import Email_the_author from "./pages/Email_the_author/email_the_author";
Expand Down
File renamed without changes.
167 changes: 167 additions & 0 deletions src/components/HeatGrid/ReviewTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import React, { useEffect, useState } from "react";
import RoundSelector from "./RoundSelector";
import dummyDataRounds from "../../pages/ViewTeamGrades/Data/heatMapData.json";
import dummyData from "../../pages/ViewTeamGrades/Data/dummyData.json";
import "../../pages/ViewTeamGrades/grades.scss";
import { Link } from "react-router-dom";
import Statistics from "./Statistics";
import Filters from "./Filters";
import ShowReviews from "./ShowReviews";
import dummyauthorfeedback from "../../pages/ViewTeamGrades/Data/authorFeedback.json";
import ReviewTableContent from "./ReviewTableContent";

interface ReviewTableProps {
currentUser?: { id: string };
project?: { student: { id: string } };
}

const ReviewTable: React.FC<ReviewTableProps> = ({ currentUser, project }) => {
const [currentRound, setCurrentRound] = useState<number>(-1);
const [sortOrderRow, setSortOrderRow] = useState<"asc" | "desc" | "none">("none");
const [sortByTotalScore, setSortByTotalScore] = useState<"asc" | "desc" | "none">("none");
const [showToggleQuestion, setShowToggleQuestion] = useState(false);
const [teamMembers, setTeamMembers] = useState<string[]>([]);
const [showReviews, setShowReviews] = useState(false);
const [ShowAuthorFeedback, setShowAuthorFeedback] = useState(false);
const [roundSelected, setRoundSelected] = useState(-1);

useEffect(() => {
setTeamMembers(dummyData.members);
}, []);

const toggleSortOrderRow = () => {
setSortOrderRow((prev) =>
prev === "asc" ? "desc" : prev === "desc" ? "none" : "asc"
);
};

const toggleSortByTotalScore = () => {
setSortByTotalScore((prev) =>
prev === "asc" ? "desc" : prev === "desc" ? "none" : "asc"
);
};

const toggleShowReviews = () => setShowReviews((prev) => !prev);
const toggleAuthorFeedback = () => setShowAuthorFeedback((prev) => !prev);
const selectRound = (r: number) => setRoundSelected(r);
const toggleShowQuestion = () => setShowToggleQuestion(!showToggleQuestion);
const handleRoundChange = (roundIndex: number) => setCurrentRound(roundIndex);

return (
<div className="p-4">
<h2 className="text-2xl font-bold mb-2">Summary Report: Program 2</h2>
<h5 className="text-xl font-semibold mb-1">Team: {dummyData.team}</h5>
<span className="ml-4">
Team members:{" "}
{teamMembers.map((member, index) => (
<span key={index}>
{member}
{index !== teamMembers.length - 1 && ", "}
</span>
))}
</span>

<div className="mt-2">
<h5>Submission Links</h5>
<ul>
<li>
<a
href="https://github.ncsu.edu/Program-2-Ruby-on-Rails/WolfEvents"
target="_blank"
rel="noopener noreferrer"
>
https://github.ncsu.edu/Program-2-Ruby-on-Rails/WolfEvents
</a>
</li>
<li>
<a href="http://152.7.177.44:8080/" target="_blank" rel="noopener noreferrer">
http://152.7.177.44:8080/
</a>
</li>
<li>
<a
href="https://github.ncsu.edu/Program-2-Ruby-on-Rails/WolfEvents/raw/main/README.md"
download="README.md"
target="_blank"
rel="noopener noreferrer"
>
README.md
</a>
</li>
</ul>
</div>

<Statistics />
<br />

<RoundSelector currentRound={currentRound} handleRoundChange={handleRoundChange} />


{/* Render Round(s) */}
{currentRound === -1
? dummyDataRounds.map((roundData, index) => (
<ReviewTableContent
key={index}
roundData={roundData}
roundIndex={index}
currentUser={currentUser}
project={project}
sortOrderRow={sortOrderRow}
toggleSortOrderRow={toggleSortOrderRow}
sortByTotalScore={sortByTotalScore}
toggleSortByTotalScore={toggleSortByTotalScore}
showToggleQuestion={showToggleQuestion}
toggleShowQuestion={toggleShowQuestion}
/>
))
: (
<ReviewTableContent
roundData={dummyDataRounds[currentRound]}
roundIndex={currentRound}
currentUser={currentUser}
project={project}
sortOrderRow={sortOrderRow}
toggleSortOrderRow={toggleSortOrderRow}
sortByTotalScore={sortByTotalScore}
toggleSortByTotalScore={toggleSortByTotalScore}
showToggleQuestion={showToggleQuestion}
toggleShowQuestion={toggleShowQuestion}
/>
)}

<Filters
toggleShowReviews={toggleShowReviews}
toggleAuthorFeedback={toggleAuthorFeedback}
selectRound={selectRound}
/>

{showReviews && (
<div>
<h2>Reviews</h2>
<ShowReviews data={dummyDataRounds} roundSelected={roundSelected} />
</div>
)}

{ShowAuthorFeedback && (
<div>
<h2>Author Feedback</h2>
<ShowReviews data={dummyauthorfeedback} roundSelected={roundSelected} />
</div>
)}

<div className="mt-4">
<h3>Grade and comment for submission</h3>
Grade: {dummyData.grade}
<br />
Comment: {dummyData.comment}
<br />
Late Penalty: {dummyData.late_penalty}
<br />
</div>

<Link to="/">Back</Link>
</div>
);
};

export default ReviewTable;
Loading