Skip to content
Snippets Groups Projects
Commit 43587f5b authored by ywb16155's avatar ywb16155
Browse files

commit #30 - refactoring student submission and drafting functionality in...

commit #30 - refactoring student submission and drafting functionality in components and backend services
parent 2faad21f
No related branches found
No related tags found
No related merge requests found
Showing
with 80 additions and 71 deletions
......@@ -3,6 +3,7 @@ package com.diss.omppapp.api;
import com.diss.omppapp.entities.AnswerEntity;
import com.diss.omppapp.entities.ClassEntity;
import com.diss.omppapp.entities.MinutePaperEntity;
import com.diss.omppapp.pojo.ResponseDetails;
import com.diss.omppapp.pojo.ResponseDetailsWrapper;
import com.diss.omppapp.services.ClassInfoService;
import com.diss.omppapp.services.StudentInfoService;
......@@ -31,13 +32,14 @@ public class StudentController {
@PostMapping(value = "/getOpenPapers",consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<MinutePaperEntity> getOpenPapers(@RequestBody Map<String,String> request) {
return studentInfoService.getOpenPapers(request.get("username"));
return studentInfoService.getOpenPapers(request.get("username"), classInfoService.getClasses(request.get("username")));
}
@PostMapping(value = "/getSubmittedClassPapers",consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<MinutePaperEntity> getSubmittedClassPapers(@RequestBody Map<String,String> request) {
return studentInfoService.getClassPapers(request.get("username"),request.get("classCode"),true);
return studentInfoService.getClosedClassPapers(request.get("username"),request.get("classCode"));
}
@PostMapping(value = "/getStudentAnswers",consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
......@@ -48,14 +50,14 @@ public class StudentController {
@PostMapping(value = "/saveDraft",consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public void saveDraft(@RequestBody ResponseDetailsWrapper answers) {
studentInfoService.save(answers,true);
public void saveDraft(@RequestBody ResponseDetailsWrapper response) {
studentInfoService.save(response,false);
}
@PostMapping(value = "/submitResponse",consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public void submitResponse(@RequestBody ResponseDetailsWrapper answers) {
studentInfoService.save(answers,false);
public void submitResponse(@RequestBody ResponseDetailsWrapper response) {
studentInfoService.save(response,true);
}
}
......@@ -13,8 +13,9 @@ public interface AnswerEntityRepository extends CrudRepository<AnswerEntity, Int
Optional<List<AnswerEntity>> findAllByUsernameAndSubmitted(String username, Boolean submitted);
Optional<List<AnswerEntity>> findAllByPaperIdAndSubmitted(int paperId, boolean submitted);
Optional<List<AnswerEntity>> findAllByUsernameAndPaperIdOrderByAnswerIdAsc(String username, int paperId);
boolean existsByUsernameAndPaperIdAndQuestionId(String username, int paperId, int QuestionId);
Optional<AnswerEntity> findByUsernameAndPaperIdAndQuestionId(String username, int paperId, int QuestionId);
boolean existsByUsernameAndPaperIdAndQuestionId(String username, int paperId, int QuestionId);
boolean existsByUsernameAndPaperId(String username, int paperId);
@Transactional
void deleteByPaperId(int paperId);
}
package com.diss.omppapp.services;
import com.diss.omppapp.entities.AnswerEntity;
import com.diss.omppapp.entities.ClassEntity;
import com.diss.omppapp.entities.MinutePaperEntity;
import com.diss.omppapp.entities.QuestionEntity;
import com.diss.omppapp.pojo.ResponseDetails;
import com.diss.omppapp.pojo.ResponseDetailsWrapper;
import com.diss.omppapp.repositories.AnswerEntityRepository;
import com.diss.omppapp.repositories.MinutePaperEntityRepository;
import com.diss.omppapp.repositories.QuestionEntityRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
......@@ -19,18 +23,32 @@ public class StudentInfoService {
@Autowired
private AnswerEntityRepository answerEntityRepository;
public List<MinutePaperEntity> getOpenPapers(String username) {
if(username == null || username.isEmpty()) {
@Autowired
private QuestionEntityRepository questionEntityRepository;
public List<MinutePaperEntity> getOpenPapers(String username, List<ClassEntity> classes) {
if(username == null || username.isEmpty() || classes.size() <= 0) {
return new ArrayList<>();
}
Optional<List<AnswerEntity>> responses = answerEntityRepository.findAllByUsernameAndSubmitted(username,false);
List<MinutePaperEntity> result = new ArrayList<>();
List<MinutePaperEntity> papersForAllClasses = new ArrayList<>();
Set<Integer> paperIdSet = new HashSet<>();
Optional<List<AnswerEntity>> responses = answerEntityRepository.findAllByUsernameAndSubmitted(username,false);
responses.ifPresent(response -> response.forEach( e -> {
paperIdSet.add(e.getPaperId());
}));
classes.forEach(c -> {
minutePaperEntityRepository.findAllByClassCodeAndTemplate(c.getClassCode(), false).ifPresent(papersForAllClasses::addAll);
});
papersForAllClasses.forEach(paper -> {
if(!answerEntityRepository.existsByUsernameAndPaperId(username, paper.getPaperId())) {
paperIdSet.add(paper.getPaperId());
}
});
paperIdSet.forEach(id -> {
minutePaperEntityRepository.findByPaperId(id).ifPresent(result::add);
});
......@@ -38,14 +56,14 @@ public class StudentInfoService {
return result;
}
public List<MinutePaperEntity> getClassPapers(String username, String classCode, Boolean submitted) {
public List<MinutePaperEntity> getClosedClassPapers(String username, String classCode) {
if((username == null || username.isEmpty()) || (classCode == null || classCode.isEmpty())) {
return new ArrayList<>();
}
List<MinutePaperEntity> result = new ArrayList<>();
Optional<List<MinutePaperEntity>> possiblePapers = minutePaperEntityRepository.findAllByClassCodeAndTemplate(classCode,false);
Optional<List<AnswerEntity>> possibleSubmissions = answerEntityRepository.findAllByUsernameAndSubmitted(username,submitted);
Optional<List<AnswerEntity>> possibleSubmissions = answerEntityRepository.findAllByUsernameAndSubmitted(username,true);
Set<Integer> paperIds = new LinkedHashSet<>();
possibleSubmissions.ifPresent(submissions -> submissions.forEach(e -> {paperIds.add(e.getPaperId());}));
......@@ -64,25 +82,26 @@ public class StudentInfoService {
return new ArrayList<>();
}
Optional<List<AnswerEntity>> answerEntities = answerEntityRepository.findAllByUsernameAndPaperIdOrderByAnswerIdAsc(username,parseId(paperId));
return answerEntities.orElseGet(ArrayList::new);
}
public void save(ResponseDetailsWrapper answers, Boolean isDraft) {
public void save(ResponseDetailsWrapper answers, Boolean submitted) {
if(answers.getResponses().size() > 0) {
try {
answers.getResponses().forEach(r -> {
answers.getResponses().forEach(response -> {
AnswerEntity entity = new AnswerEntity();
int existing = hasExistingAnswer(r.getUsername(),parseId(r.getPaperId()),parseId(r.getQuestionId()));
int existing = hasExistingAnswer(response.getUsername(),parseId(response.getPaperId()),parseId(response.getQuestionId()));
if( existing != -1) {
entity.setAnswerId(existing);
}
entity.setAnswerText(r.getAnswerText());
entity.setUsername(r.getUsername());
entity.setSubmitted(isDraft);
entity.setPaperId(parseId(r.getPaperId()));
entity.setQuestionId(parseId(r.getQuestionId()));
entity.setAnswerText(response.getAnswerText());
entity.setUsername(response.getUsername());
entity.setSubmitted(submitted);
entity.setPaperId(parseId(response.getPaperId()));
entity.setQuestionId(parseId(response.getQuestionId()));
entity.setSubmissionDate(new Date());
answerEntityRepository.save(entity);
});
......
......@@ -13,9 +13,6 @@
<div>
<h3>Your Classes</h3>
</div>
<div>
<h4 *ngIf="classList.length <= 0">It appears you aren't enrolled anywhere!</h4>
</div>
<ag-grid-angular
style="width: 1000px; height: 500px;"
class="ag-theme-balham"
......
......@@ -15,6 +15,9 @@ import {ViewClassesButtonComponent} from 'src/app/GridComponents/ViewClassesButt
})
export class LecturerDashboardComponent implements OnInit, OnDestroy {
private isAlive = true;
private lecturerId: String;
public rowData: any;
public gridOptions: GridOptions;
public columnDefs = [
{headerName: 'Class Code', field: 'classCode', sortable: true, lockPosition: true},
......@@ -23,11 +26,6 @@ export class LecturerDashboardComponent implements OnInit, OnDestroy {
{headerName: 'View', field: '', cellRendererFramework: ViewClassesButtonComponent, lockPosition: true},
];
private isAlive = true;
private lecturerId: String;
public classList: OmpClassDao[];
public rowData: any;
constructor(private lecturerInfoService: LecturerInfoService,
private lecturerDataService: LecturerDataService,
private lecturerViewService: LecturerViewService,
......@@ -38,25 +36,16 @@ export class LecturerDashboardComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.route.params.subscribe(params => { this.lecturerId = params.id; }).add(takeWhile(() => this.isAlive));
this.lecturerDataService.lecturerId = this.lecturerId;
this.classList = [];
this.gridOptions = {
context: {componentParent: this}
};
this.rowData = this.lecturerInfoService.getLecturerClasses(this.lecturerId);
this.getClasses();
}
ngOnDestroy(): void {
this.classList = [];
this.isAlive = false;
}
private getClasses() {
this.lecturerInfoService.getLecturerClasses(this.lecturerId).subscribe((data: OmpClassDao[]) => {
data.forEach(c => this.classList.push(c));
});
}
public goToPaperView(classCode: String) {
this.lecturerDataService.classCode = classCode;
this.lecturerViewService.changeToDashboard(false);
......
......@@ -3,7 +3,7 @@
<div id="closed-papers" class="col">
<h3>Your Created One-minute Papers</h3>
<ag-grid-angular
style="width: 2000px; height: 500px;"
style="width: 1500px; height: 500px;"
class="ag-theme-balham"
[columnDefs]="columnDefs"
[rowData]="classPapers | async"
......
<app-navbar></app-navbar>
<div class="container">
<div *ngFor="let pair of questionAnswerPairs; let i = index" [attr.data-index]="i">
<div class="row">
<span>Question {{i+1}}:</span>
......
......@@ -2,9 +2,6 @@
<div class="row">
<div id="closed-papers" class="col">
<h3>One-minute Paper Responses</h3>
<div *ngIf="answers.length <= 0">
<h4>You have no submitted responses for this class!</h4>
</div>
<div *ngFor="let set of answers; let i = index" [attr.data-index]="i">
<div class="container">
<span class="row">{{set.answerSets[i].username}}</span>
......@@ -13,4 +10,5 @@
</div>
</div>
</div>
<router-outlet></router-outlet>
</div>
......@@ -4,6 +4,8 @@ import {LecturerInfoService} from 'src/app/services/lecturer-info.service';
import {Router} from '@angular/router';
import {QuestionDao} from 'src/app/dao/question.dao';
import {AnswerSetDao} from 'src/app/dao/answer-set.dao';
import {ViewClassesButtonComponent} from '../../GridComponents/ViewClassesButton/view-classes-button.component';
import {GridOptions} from 'ag-grid-community';
@Component({
selector: 'app-lecturer-submissionsview',
......@@ -17,6 +19,14 @@ export class LecturerSubmissionsViewComponent implements OnInit, OnDestroy {
public paperId;
public questions: QuestionDao[];
public answers: AnswerSetDao[];
public rowData: any;
public gridOptions: GridOptions;
public columnDefs = [
{headerName: 'Class Code', field: 'classCode', sortable: true, lockPosition: true},
{headerName: 'Class Name', field: 'classname', sortable: true, lockPosition: true},
{headerName: 'Year', field: 'year', sortable: true, lockPosition: true},
{headerName: 'View', field: '', cellRendererFramework: ViewClassesButtonComponent, lockPosition: true},
];
constructor(private lecturerDataService: LecturerDataService,
private lecturerInfoService: LecturerInfoService,
......
......@@ -4,15 +4,16 @@
<h4>{{currentPaper.name}}</h4>
<h4>Write a response about {{currentPaper.topic}} for {{currentPaper.classCode}}</h4>
</div>
<form [formGroup]="submissionForm">
<div formArrayName="questions">
<div *ngFor="let question of questionList; let i = index" [attr.data-index]="i">
<form #submissionForm>
<div>
<div *ngFor="let pair of questionAnswerPairs; let i = index" [attr.data-index]="i">
<div class="row">
<span>Question {{i+1}}:</span>
</div>
<div class="row">
<label for="{{i}}">{{question.questionText}}</label>
<textarea id="{{i}}" [formControlName]="i" class="form-control" type="text" rows="3" [value]="answerList[i].answerText" placeholder="Start typing your response here.."></textarea>
<label for="{{i}}">{{pair.question.questionText}}</label>
<textarea id="{{i}}" class="form-control" type="text" rows="3" name="{{i}}"
[(ngModel)]="pair.answer.answerText" placeholder="Start typing your response here.."></textarea>
</div>
</div>
<!-- Buttons -->
......
......@@ -5,9 +5,9 @@ import {StudentDataService} from 'src/app/services/student-data.service';
import {QuestionDao} from 'src/app/dao/question.dao';
import {AnswerDao} from 'src/app/dao/answer.dao';
import {MinutePaperDao} from 'src/app/dao/minute-paper.dao';
import {FormArray, FormBuilder, FormGroup} from '@angular/forms';
import {StudentResponseDao} from 'src/app/dao/student-response.dao';
import {Router} from '@angular/router';
import {QuestionAnswerPairDao} from '../../dao/question-answer-pair.dao';
@Component({
selector: 'app-student-submission-view',
......@@ -17,27 +17,25 @@ import {Router} from '@angular/router';
export class StudentSubmissionViewComponent implements OnInit, OnDestroy {
private studentResponse: StudentResponseDao[];
public submissionForm: FormGroup;
public currentPaper: MinutePaperDao;
public studentId: String;
public answerList: AnswerDao[];
public questionList: QuestionDao[];
public questionAnswerPairs: QuestionAnswerPairDao[];
constructor(private studentViewService: StudentViewService,
private studentInfoService: StudentInfoService,
private studentDataService: StudentDataService,
private formBuilder: FormBuilder,
private router: Router) {
}
ngOnInit(): void {
this.submissionForm = this.formBuilder.group({
questions: this.formBuilder.array([])
});
this.currentPaper = this.studentDataService.currentPaper;
this.studentId = this.studentDataService.studentId;
this.questionList = [];
this.answerList = [];
this.questionAnswerPairs = [];
this.studentResponse = [];
this.getQuestions();
this.getAnswers();
......@@ -49,40 +47,32 @@ export class StudentSubmissionViewComponent implements OnInit, OnDestroy {
this.studentResponse = [];
}
private populateAnswers(): void {
let index = 0;
this.questionList.forEach(q => {
if (this.submissionForm.get('questions').get(index.toString()) !== null) {
this.questionAnswerPairs.forEach(q => {
this.studentResponse.push(new StudentResponseDao(this.studentId, this.currentPaper.paperId,
q.questionId, this.submissionForm.get('questions').get(index.toString()).value));
q.question.questionId, q.answer.answerText));
index++;
}
});
}
private getFormQuestions(): FormArray {
return this.submissionForm.get('questions') as FormArray;
}
private organise(): void {
private organise() {
this.questionAnswerPairs = [];
for (let i = 0; i < this.questionList.length; i++) {
if (this.questionList[i] && this.answerList[i]) {
this.getFormQuestions().push(this.formBuilder.control(this.answerList[i].answerText));
} else {
this.getFormQuestions().push(this.formBuilder.control(''));
this.questionAnswerPairs.push(new QuestionAnswerPairDao(this.questionList[i], this.answerList[i]));
}
}
}
private getQuestions(): void {
private getQuestions() {
this.studentInfoService.getPaperQuestions(this.studentId, this.currentPaper.paperId).subscribe((data: QuestionDao[]) => {
data.forEach(e => this.questionList.push(e));
this.organise();
});
}
private getAnswers(): void {
private getAnswers() {
this.studentInfoService.getStudentAnswers(this.studentId, this.currentPaper.paperId).subscribe((data: AnswerDao[]) => {
data.forEach(e => this.answerList.push(e));
this.organise();
......@@ -92,10 +82,14 @@ export class StudentSubmissionViewComponent implements OnInit, OnDestroy {
public submit(): void {
this.populateAnswers();
this.studentInfoService.submitResponse(this.studentResponse).subscribe();
this.router.navigate(['/sdashboard', {id: this.studentId}]);
this.ngOnDestroy();
}
public save(): void {
this.populateAnswers();
this.studentInfoService.saveDraft(this.studentResponse).subscribe();
this.router.navigate(['/sdashboard', {id: this.studentId}]);
this.ngOnDestroy();
}
}
......@@ -48,13 +48,13 @@ export class StudentInfoService {
}
public saveDraft(answers: StudentResponseDao[]): Observable<String | Object> {
return this.http$.post('http://localhost:8080/saveDraft', {answers: answers}, httpOptions).pipe(
return this.http$.post('http://localhost:8080/saveDraft', {responses: answers}, httpOptions).pipe(
catchError(this.errorService.handleError)
);
}
public submitResponse(answers: StudentResponseDao[]): Observable<String | Object> {
return this.http$.post('http://localhost:8080/submitResponse', {answers: answers}, httpOptions).pipe(
return this.http$.post('http://localhost:8080/submitResponse', {responses: answers}, httpOptions).pipe(
catchError(this.errorService.handleError)
);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment