John-sCC / jcc_frontend

Apache License 2.0
0 stars 0 forks source link

Drew Reed - Plan for the Remainder of the Project Cycle (Assignment Grading/Viewing) #88

Open drewreed2005 opened 1 month ago

drewreed2005 commented 1 month ago

Current State

As things currently are, the assignment object has the following attributes:

The frontend only currently has the capacity to:

The frontend is also unfinished in terms of design:

Screen Shot 2024-05-15 at 10 49 49 AM

There are unfinished and not completely functional measures that have been tested to accept file uploads to assignments.

The Ideal Final Product

Assignment Object and Methods

These should all be implemented as attributes of the assignment class:

Methods should be added/modified such that...

Assignment Submission Object and Methods

The object exists already and is in progress, but should eventually contain:

Methods that should exist (many currently exist) are...

Frontend Redesign

This is the plan for the appearance of the page for students and their submissions:

Screen Shot 2024-05-15 at 12 19 45 PM

The teachers should be able to see student submissions based on the time and order of their submissions and to view a preview to the left (see below). They should also be able to submit a grade for submissions on this page (to be implemented where the bolded ratio numbers are listed):

Screen Shot 2024-05-20 at 11 23 34 AM

Ideal Event Demonstration

After user creation (Kevin), site navigation (Ekam/Ishi), and class period creation (Drew?)...

Then continue to teacher communication...

Timeline

Feature Deadline Details
Backend: New Methods, Attributes Tuesday, May 21 Finish methods for Assignment and AssignmentSubmission classes detailed in the issue above.
Frontend: Student Submission View Thursday, May 23 Finish styling and communication of backend data to the student frontend screen, including a pull that determines student relationship to an assignment
Frontend: Teacher Submission View Friday, May 24 Should be primarily adapted from the student view, but with accommodation of teacher grading capability. Raymond's preview feature will be implemented if possible, but if not, grading will at least be accommodated. Worst case, file downloads are utilized.
Backend: Testing and Update to Deployment Monday, May 27 Over this weekend, I will ensure that all changes made locally to the Assignment branch are reflected to the deployed format. Deployed link will be used on the frontend as well.
drewreed2005 commented 1 month ago

Presentation Point

drewreed2005 commented 1 month ago

Progress Checkpoint: End of Monday, May 20

Code Contributions

All current progress has been on the backend in the assignment-object branch.

Reimplementing Assignment Object

The Assignment object had the points, allowed file types, and submissions attributes added and implemented in this commit. I realized I missed the allowed number of submissions attribute, so I added them in this commit.

This is the current state of the Entity:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Convert(attributeName ="assignment", converter = JsonType.class)
public class Assignment {
    // basic variable initialization goes here...
    // Constructor used when building object from an API
    public Assignment(String name, Date dateCreated, Date dateDue, String content, int points, int allowedSubmissions, String[] allowedFileTypes) {
        this.name = name;
        this.dateCreated = dateCreated;
        this.dateDue = dateDue;
        this.content = content;
        this.points = points;
        this.allowedSubmissions = allowedSubmissions;
        for (String allowedFileType : allowedFileTypes) {
            this.allowedFileTypes.add(allowedFileType);
        }
    }

Assignment Submission Object

This was all implemented quite a while ago for testing (see this commit with the starter version (non-entity, changed later) and this commit with working version). Now, it looks like the following:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Convert(attributeName ="assignmentSubmission", converter = JsonType.class)
public class AssignmentSubmission {
    // automatic unique identifier for Person record
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
    private Person submitter;

    @NonNull
    private String filePath;

    @Temporal(TemporalType.TIMESTAMP)
    private Date timeSubmitted;

    private int submissionNumber;

    private int score;

    public AssignmentSubmission(Person submitter, String filePath, Date timeSubmitted, int submissionNumber) {
        this.submitter = submitter;
        this.filePath = filePath;
        this.timeSubmitted = timeSubmitted;
        this.submissionNumber = submissionNumber;
        this.score = -1; // score is always initialized to -1 until graded
    }
}

Prior to commits, its full functionality was confirmed.

New Backend Methods

All methods are in the AssignmentAPIController file.

In the most recent commits, this method was changed to fetch all previous submissions to an assignment by the user for frontend functionality. This is what is called when a student accesses assignment data on the frontend.

    @GetMapping("/cookie/{id}")
    public ResponseEntity<?> getAssignmentWithCookie(@CookieValue("jwt") String jwtToken,
                                                              @PathVariable long id) {
        // cookie verification; person assigned to existingPerson variable...
        Assignment assignment = repository.findById(id);
        if (assignment == null) {  // bad ID
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);  // OK HTTP response: status code, headers, and body
        }
        HashMap<String, Object> assignmentData = new HashMap<>();
        assignmentData.put("role", null);
        // good ID, so continue to check relationship
        for (ClassPeriod cp : classService.getClassPeriodsByAssignment(assignment)) {
            for (Person student : cp.getStudents()) {
                if (student.getEmail().equals(existingPerson.getEmail())) {
                    assignmentData.put("role", "student"); // person has teacher access to the assignment
                }
            }
            for (Person leader : cp.getLeaders()) {
                if (leader.getEmail().equals(existingPerson.getEmail())) {
                    assignmentData.put("role", "teacher"); // person has teacher access to the assignment
                }
            }
        }
        // handler for invalid user accessing data
        if (assignmentData.get("role") == null) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
        // if the student is determined to have no relationship to the assignment, null indicates they cannot access w/ role
        assignmentData.put("data", assignment);
        // NOW MAKE IT ALSO FETCH PREVIOUS SUBMISSION
        ArrayList<AssignmentSubmission> personSubmissions = new ArrayList<>();
        for (AssignmentSubmission submission : assignment.getSubmissions()) {
            if (submission.getSubmitter().getEmail().equals(existingPerson.getEmail())) { // verifying user identity with email
                personSubmissions.add(submission);
            }
        }
        assignmentData.put("submissions", personSubmissions.toArray());
        return new ResponseEntity<>(assignmentData, HttpStatus.OK);    
    }

Here's a tester call made from the frontend that shows all of the data grabbed by a user:

Screen Shot 2024-05-21 at 11 14 54 AM

Here is a method that was created in this commit for fetching from the teacher page:

    @GetMapping("/cookie/{id}/grading")
    public ResponseEntity<?> getAssignmentSubmissionsWithCookie(@CookieValue("jwt") String jwtToken,
                                                                @PathVariable long id) {
        // reading cookie data to identify existingPerson in said variable...
        boolean isTeacher = false;
        // good ID, so continue to check relationship
        for (ClassPeriod cp : classService.getClassPeriodsByAssignment(assignment)) {
            for (Person leader : cp.getLeaders()) {
                if (leader.getEmail().equals(existingPerson.getEmail())) {
                    isTeacher = true; // person has teacher access to the assignment
                }
            }
        }
        // handler for invalid user accessing data
        if (!(isTeacher)) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
        // sending all submissions from a given assignment
        return new ResponseEntity<>(assignment.getSubmissions(), HttpStatus.OK);    
    }

Remaining Work

I realized earlier that I did not make a method for easy teacher grading that utilizes the JWT. I will finish this today before beginning work with the frontend wireframe.

drewreed2005 commented 1 month ago

Frontend Pull Request

Click here to access.

Backend Pull Request

Click here