Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented StudentTaskView with adherence to SOLID principles and incorporated necessary stylings #46

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e6dd600
Installed react-scripts
HasiniChenchala2 Mar 18, 2024
c0f3655
Rendered StudentTask component and added StudentTaskView path
HasiniChenchala2 Mar 18, 2024
bfb24dd
Added Routes to StudentTaskView in Home
HasiniChenchala2 Mar 18, 2024
6cb052f
Implemented StudentTask component
HasiniChenchala2 Mar 18, 2024
1270bf1
Implemented StudentTaskView showing your work, your team, assignment …
HasiniChenchala2 Mar 18, 2024
7c90d94
Merge pull request #2 from Shravsssss/TaskDetails
HasiniChenchala2 Mar 18, 2024
18c4f03
Added stylings and modified your work
HasiniChenchala2 Mar 20, 2024
ac78ffe
Added StudentTask and StudentTaskView path and elements
HasiniChenchala2 Mar 24, 2024
738b217
The link to the StudentTask component was removed from the Home compo…
HasiniChenchala2 Mar 24, 2024
c26a4ad
Added Link to StudentTaskView component in StudentTask
HasiniChenchala2 Mar 24, 2024
622de25
Refactored deadlines handling into DeadlineUtil.tsx to make the code …
HasiniChenchala2 Mar 24, 2024
34422d5
Refactored StudentTaskView.tsx and obtained dynamic assignment ID
HasiniChenchala2 Mar 25, 2024
8b2282a
Refactored styles for deadlines from StudentTaskView.tsx into Student…
HasiniChenchala2 Mar 25, 2024
0e03e76
Split StudentTaskView into multiple files and refactored tasks into f…
HasiniChenchala2 Mar 25, 2024
88a56d2
Added Deadline Interface
HasiniChenchala2 Mar 25, 2024
1ea4fe5
Renamed StudentTaskView file
HasiniChenchala2 Mar 25, 2024
643729c
Imported Lazy Loading to App.tsx
HasiniChenchala2 Mar 25, 2024
3e91c0e
Implemented lazy loading for StudentTaskView component to enhance web…
HasiniChenchala2 Mar 25, 2024
8ffc03b
Splitted StudentTaskView files to adhere to SOLID principles
HasiniChenchala2 Mar 25, 2024
52dc855
Imported and Implemented LazyLoading to StudentTaskView.tsx
HasiniChenchala2 Mar 25, 2024
f199193
Merge pull request #11 from Shravsssss/TaskDetails
HasiniChenchala2 Mar 25, 2024
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
2 changes: 1 addition & 1 deletion package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"react-icons": "^4.9.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.11.1",
"react-scripts": "5.0.1",
"react-scripts": "^5.0.1",
"redux-persist": "^6.0.0",
"sass": "^1.62.1",
"save": "^2.9.0",
Expand Down
14 changes: 14 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ 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 StudentTask from "./pages/StudentTasks/StudentTask";
import LazyLoadedStudentTaskView from "pages/StudentTaskViews/LazyStudentTaskView";




function App() {
const router = createBrowserRouter([
Expand Down Expand Up @@ -74,6 +79,15 @@ function App() {
},
],
},
{
path: "/student_tasks", // Define the path for the student_task section
element: <StudentTask />, // Render the StudentTask component
},
{
path: "/student_task_view/:id",
element: <LazyLoadedStudentTaskView />
},

{
path: "student_tasks/participants",
element: <Participants type="student_tasks" id={1} />,
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
const Home = () => {
return (
<div>
<h1>Welcome Home!</h1>
<h1>Welcome Home!</h1>
</div>
);
};
Expand Down
34 changes: 34 additions & 0 deletions src/pages/StudentTaskViews/DeadlineUtil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Deadline } from "utils/interfaces";

// Define an array of deadlines
export const deadlines: Deadline[] = [
{
id: 1,
date: "2024-03-22",
description: "Submit Assignment Round 1",
},
{
id: 2,
date: "2024-03-27",
description: "Review Assignment Round 1",
},
{
id: 3,
date: "2024-04-04",
description: "Submit Assignment Round 2",
},
{
id: 4,
date: "2024-04-07",
description: "Review Assignment Round 2",
},
];

// Function to get the next upcoming deadline
export const getNextDeadline = (): Deadline | null => {
const now = new Date();
// Filter the deadlines to get only the upcoming ones
const upcomingDeadlines = deadlines.filter(deadline => new Date(deadline.date) > now);
// Return the earliest upcoming deadline, or null if there are no upcoming deadlines
return upcomingDeadlines.length > 0 ? upcomingDeadlines[0] : null;
};
40 changes: 40 additions & 0 deletions src/pages/StudentTaskViews/LazyStudentTaskView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useEffect, useState, Suspense } from 'react';
import { useParams } from 'react-router-dom';
import { loadAssignment } from 'pages/Assignments/AssignmentUtil';

// Lazy load the StudentTaskView component
const LazyStudentTaskView = React.lazy(() => import('./StudentTaskView'));

const LazyLoadedStudentTaskView: React.FC = () => {
const { id } = useParams<{ id: string }>();
const [assignment, setAssignment] = useState<any>(null); // State for assignment data

useEffect(() => { // Fetch assignment data on component mount
const fetchAssignment = async () => {
try {
const assignmentData = await loadAssignment({ params: { id } });
setAssignment(assignmentData);
} catch (error) {
console.error('Error fetching assignment:', error);
}
};

fetchAssignment(); // Call fetchAssignment function

return () => {
// Cleanup code here
};
}, [id]); // Include id in the dependency array to re-fetch assignment data when ID changes

if (!assignment) { // If assignment data hasn't been fetched yet, display loading message
return <div>Loading...</div>;
}

return (
<Suspense fallback={<div>Loading Student Task View...</div>}>
<LazyStudentTaskView />
</Suspense>
);
};

export default LazyLoadedStudentTaskView;
208 changes: 208 additions & 0 deletions src/pages/StudentTaskViews/StudentTaskView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { loadAssignment } from 'pages/Assignments/AssignmentUtil';
import { RootState } from "../../store/store";
import { ROLE } from '../../utils/interfaces';
import { styles } from './StudentTaskViewStyle';
import { deadlines, getNextDeadline } from './DeadlineUtil';


const StudentTaskView: React.FC = () => {
const [assignment, setAssignment] = useState<any>(null); // State for assignment data
const { id } = useParams<{ id: string }>();
const auth = useSelector( // Using useSelector hook to access Redux store
(state: RootState) => state.authentication,
(prev, next) => prev.isAuthenticated === next.isAuthenticated
);

useEffect(() => { // Fetch assignment data on component mount
const fetchAssignment = async () => {
try {
const assignmentData = await loadAssignment({ params: { id } });
setAssignment(assignmentData);
} catch (error) {
console.error('Error fetching assignment:', error);
}
};

fetchAssignment(); // Call fetchAssignment function

return () => {
// Cleanup code here
};
}, [id]); // Include id in the dependency array to re-fetch assignment data when ID changes

if (!assignment) { // If assignment data hasn't been fetched yet, display loading message
return <div>Loading...</div>;
}

const authorization = 'participant'; // Mock authorization data
const can_review = true; // Mock data for review permission
const team = true; // Mock data for team permission
const can_take_quiz = true; // Mock data for quiz permission
const can_provide_suggestions = true; // Mock data for suggestion permission
const nextDeadline = getNextDeadline(); // Get next deadline
const showWork = checkShowWork(authorization, nextDeadline); // Check if work should be shown

return (
<div className="container">
<h1 className="display-4 font-custom">
<span style={styles.statusP} className="font-custom">
Submit or Review work for {assignment.name}
</span>
</h1>
{can_review && checkReviewAvailability() && checkReviewableTopics() && ( // Conditionally render button based on review availability
<div className="d-flex justify-content-end">
<button className="btn btn-primary">
{/* <a href={`email_reviewers_student_task_index_path?id=${auth.user.id}&assignment_id=${assignment.id}`} style={{ color: 'white', textDecoration: 'none' }}> */}
<a href={``} style={{ color: 'white', textDecoration: 'none' }}>
Send Email to Reviewers
</a>
</button>
</div>
)}
{assignment.spec_location && assignment.spec_location.length > 0 && ( // Display assignment description if available
<div className="mb-4">
<a href={assignment.spec_location} target="_blank" rel="noopener noreferrer">
Assignment Description
</a>
</div>
)}
<ul className="list-unstyled mb-4">
{authorization === 'participant' && ( // Display team management option for participants
<li className="mb-2">
<a href="#" className="btn btn-outline-primary">
Your team
</a>{' '}
View and manage your team
</li>
)}
{auth.user.role === ROLE.TA && ( // Display all teams option for TAs
<li className="mb-2">
<a href="#" className="btn btn-outline-primary">All teams</a> View teams
</li>
)}

{showWork && ( // Display work submission/review options
<li className="mb-2">
{checkIsSubmitDeadline(nextDeadline) && (
<span>
<a href="#" className="btn btn-outline-success">Your work</a>
<span> Submit work </span>
</span>
)}
{checkIsReviewDeadline(nextDeadline) && (
<span>
Your work <span style={{ color: 'red' }}>You are not allowed to submit you work right now</span>
</span>
)}
</li>
)}
{!showWork && ( // Display message if user is not allowed to submit work
<li className="mb-2">
You are not allowed to submit you work right now
</li>
)}

{(authorization === 'participant' || can_review) && ( // Display option to give feedback to others
<li className="mb-2">
<a href="#" className="btn btn-outline-primary">Others' work</a> Give feedback to others on their work
</li>
)}
{auth.user.role === ROLE.TA && assignment.require_quiz && (authorization === 'participant' || can_take_quiz) && ( // Display option to take quizzes
<li className="mb-2">
<a href="#" className="btn btn-outline-primary">Take quizzes</a> Quizzes read
</li>
)}
{team && (authorization === 'participant' || checkIsSubmitDeadline(nextDeadline)) && ( // Display option to view scores
<li className="mb-2">
<a href="#" className="btn btn-outline-primary">Your scores</a> View feedback on your work &nbsp;
<a href="#" className="btn btn-outline-secondary">Alternate view</a>
</li>
)}
{auth.user.role === ROLE.TA && can_provide_suggestions && ( // Display option to suggest topics
<li className="mb-2">
<a href="#" className="btn btn-outline-primary">Suggest topic</a>
</li>
)}
<li className="mb-2">
<a href="#" className="btn btn-outline-primary">Change handle</a> Provide a different handle for this assignment
</li>
</ul>
<br />
<br />
<h2>Deadlines</h2>
<div style={styles.scrollable} className="scrollable">
<ul style={styles.timeline} className="timeline">
{deadlines.map(renderDeadline)} {/* Map deadlines to renderDeadline function */}
</ul>
</div>
<button className="btn btn-secondary mt-3" onClick={() => window.history.back()}>
Back
</button>
</div>
);

function checkShowWork(authorization: string, nextDeadline: any) { // Check if work should be shown
const isReview = checkIsReviewDeadline(nextDeadline);
const isSubmit = checkIsSubmitDeadline(nextDeadline);
return authorization === 'participant' && (isReview || isSubmit);
}

function checkIsReviewDeadline(deadline: any) { // Check if deadline is for review
return deadline && deadline.description.startsWith('Review');
}

function checkIsSubmitDeadline(deadline: any) { // Check if deadline is for submission
return deadline && deadline.description.startsWith('Submit');
}

function checkReviewAvailability() { // Logic to determine review availability
return true;
}

function checkReviewableTopics() { // Logic to check if topics are reviewable
return true;
}

function isDeadlinePassed(deadline: any) { // Check if deadline is passed
const now = new Date();
return new Date(deadline.date) <= now;
}

function checkShowLink(index: number, deadlines: any[]) { // Check if link should be shown for a deadline
if (index === 0) {
return !isDeadlinePassed(deadlines[index]);
} else {
const previousDeadline = deadlines[index - 1];
const isPreviousDeadlinePassed = isDeadlinePassed(previousDeadline);
const isPresentDeadlinePassed = isDeadlinePassed(deadlines[index]);
return isPreviousDeadlinePassed && !isPresentDeadlinePassed;
}
}

function renderDeadline(deadline: any, index: number) { // Render each deadline
return (
<li key={deadline.id} style={styles.li} className={isDeadlinePassed(deadline) ? 'li complete' : 'li'}>
<div style={styles.timestamp} className="timestamp">
<p>{deadline.date}</p>
</div>
<div style={styles.status} className="status">
<p style={styles.statusP}>
{deadline.id && checkShowLink(index, deadlines) ? ( // Conditionally render link based on deadline status
<a href={`controller: 'response', action: 'view', id: ${deadline.id}`} target="_blank">
{deadline.description}
</a>
) : (
deadline.description
)}
</p>
<div style={isDeadlinePassed(deadline) ? { ...styles.statusBefore, ...styles.completeStatusBefore } : styles.statusBefore}></div>
</div>
</li>
);
}
};

export default StudentTaskView;
52 changes: 52 additions & 0 deletions src/pages/StudentTaskViews/StudentTaskViewStyle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Define styles for the StudentTaskView component
export const styles = {
timeline: {
listStyleType: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
li: {
transition: 'all 200ms ease-in',
height: '140px',
},
timestamp: {
marginBottom: '40px',
},
status: {
display: 'flex',
justifyContent: 'center',
borderTop: '2px solid #D6DCE0',
position: 'relative' as const,
transition: 'all 200ms ease-in',
},
statusP: {
marginTop: '20px',
padding: '10px',
},
statusBefore: {
content: "''",
width: '25px',
height: '25px',
backgroundColor: 'white',
borderRadius: '25px',
border: '1px solid #ddd',
position: 'absolute' as const,
top: '-15px',
left: '8%',
transition: 'all 200ms ease-in',
},
completeStatus: {
borderTop: '2px solid #A90201',
},
completeStatusBefore: {
backgroundColor: '#A90201',
border: 'none',
transition: 'all 200ms ease-in',
},
scrollable: {
height: 'auto',
overflowY: 'auto' as const,
},
};

Loading