This commit is contained in:
parent
9188913cf4
commit
084a612a1f
60
package.json
60
package.json
@ -4,7 +4,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@f0rce/ace-widget": "1.0.2",
|
"@f0rce/ace-widget": "1.0.2",
|
||||||
"@polymer/polymer": "3.5.1",
|
"@polymer/polymer": "3.5.2",
|
||||||
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
||||||
"@vaadin/bundles": "24.5.1",
|
"@vaadin/bundles": "24.5.1",
|
||||||
"@vaadin/common-frontend": "0.0.19",
|
"@vaadin/common-frontend": "0.0.19",
|
||||||
@ -19,29 +19,30 @@
|
|||||||
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
||||||
"construct-style-sheets-polyfill": "3.1.0",
|
"construct-style-sheets-polyfill": "3.1.0",
|
||||||
"date-fns": "2.29.3",
|
"date-fns": "2.29.3",
|
||||||
"lit": "3.1.4",
|
"lit": "3.2.1",
|
||||||
"print-js": "1.6.0",
|
"print-js": "1.6.0",
|
||||||
"proj4": "2.12.1",
|
"proj4": "2.12.1",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-router-dom": "6.23.1"
|
"react-router-dom": "6.26.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/preset-react": "7.24.7",
|
"@babel/preset-react": "7.25.7",
|
||||||
"@rollup/plugin-replace": "5.0.7",
|
"@preact/signals-react-transform": "0.4.0",
|
||||||
"@rollup/pluginutils": "5.1.0",
|
"@rollup/plugin-replace": "6.0.1",
|
||||||
"@types/react": "18.3.3",
|
"@rollup/pluginutils": "5.1.2",
|
||||||
"@types/react-dom": "18.3.0",
|
"@types/react": "18.3.11",
|
||||||
"@vitejs/plugin-react": "4.3.1",
|
"@types/react-dom": "18.3.1",
|
||||||
"async": "3.2.5",
|
"@vitejs/plugin-react": "4.3.3",
|
||||||
"glob": "10.4.1",
|
"async": "3.2.6",
|
||||||
|
"glob": "10.4.5",
|
||||||
"rollup-plugin-brotli": "3.1.0",
|
"rollup-plugin-brotli": "3.1.0",
|
||||||
"rollup-plugin-visualizer": "5.12.0",
|
"rollup-plugin-visualizer": "5.12.0",
|
||||||
"strip-css-comments": "5.0.0",
|
"strip-css-comments": "5.0.0",
|
||||||
"transform-ast": "2.4.4",
|
"transform-ast": "2.4.4",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.6.3",
|
||||||
"vite": "5.3.3",
|
"vite": "5.4.9",
|
||||||
"vite-plugin-checker": "0.6.4",
|
"vite-plugin-checker": "0.8.0",
|
||||||
"workbox-build": "7.1.1",
|
"workbox-build": "7.1.1",
|
||||||
"workbox-core": "7.1.0",
|
"workbox-core": "7.1.0",
|
||||||
"workbox-precaching": "7.1.0"
|
"workbox-precaching": "7.1.0"
|
||||||
@ -49,7 +50,7 @@
|
|||||||
"vaadin": {
|
"vaadin": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@f0rce/ace-widget": "1.0.2",
|
"@f0rce/ace-widget": "1.0.2",
|
||||||
"@polymer/polymer": "3.5.1",
|
"@polymer/polymer": "3.5.2",
|
||||||
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
||||||
"@vaadin/bundles": "24.5.1",
|
"@vaadin/bundles": "24.5.1",
|
||||||
"@vaadin/common-frontend": "0.0.19",
|
"@vaadin/common-frontend": "0.0.19",
|
||||||
@ -64,34 +65,35 @@
|
|||||||
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
||||||
"construct-style-sheets-polyfill": "3.1.0",
|
"construct-style-sheets-polyfill": "3.1.0",
|
||||||
"date-fns": "2.29.3",
|
"date-fns": "2.29.3",
|
||||||
"lit": "3.1.4",
|
"lit": "3.2.1",
|
||||||
"print-js": "1.6.0",
|
"print-js": "1.6.0",
|
||||||
"proj4": "2.12.1",
|
"proj4": "2.12.1",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-router-dom": "6.23.1"
|
"react-router-dom": "6.26.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/preset-react": "7.24.7",
|
"@babel/preset-react": "7.25.7",
|
||||||
"@rollup/plugin-replace": "5.0.7",
|
"@preact/signals-react-transform": "0.4.0",
|
||||||
"@rollup/pluginutils": "5.1.0",
|
"@rollup/plugin-replace": "6.0.1",
|
||||||
"@types/react": "18.3.3",
|
"@rollup/pluginutils": "5.1.2",
|
||||||
"@types/react-dom": "18.3.0",
|
"@types/react": "18.3.11",
|
||||||
"@vitejs/plugin-react": "4.3.1",
|
"@types/react-dom": "18.3.1",
|
||||||
"async": "3.2.5",
|
"@vitejs/plugin-react": "4.3.3",
|
||||||
"glob": "10.4.1",
|
"async": "3.2.6",
|
||||||
|
"glob": "10.4.5",
|
||||||
"rollup-plugin-brotli": "3.1.0",
|
"rollup-plugin-brotli": "3.1.0",
|
||||||
"rollup-plugin-visualizer": "5.12.0",
|
"rollup-plugin-visualizer": "5.12.0",
|
||||||
"strip-css-comments": "5.0.0",
|
"strip-css-comments": "5.0.0",
|
||||||
"transform-ast": "2.4.4",
|
"transform-ast": "2.4.4",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.6.3",
|
||||||
"vite": "5.3.3",
|
"vite": "5.4.9",
|
||||||
"vite-plugin-checker": "0.6.4",
|
"vite-plugin-checker": "0.8.0",
|
||||||
"workbox-build": "7.1.1",
|
"workbox-build": "7.1.1",
|
||||||
"workbox-core": "7.1.0",
|
"workbox-core": "7.1.0",
|
||||||
"workbox-precaching": "7.1.0"
|
"workbox-precaching": "7.1.0"
|
||||||
},
|
},
|
||||||
"hash": "1a0f17d48b329307b5862bc57499307d1b89f7d89260121c2b7189f76957c436"
|
"hash": "2dc40a4f634ae025081ca2239cba00b14a35fe94ab78ac0a4dd3023d882081d5"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@vaadin/bundles": "$@vaadin/bundles",
|
"@vaadin/bundles": "$@vaadin/bundles",
|
||||||
|
@ -6,8 +6,6 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ -16,7 +14,4 @@ import java.util.List;
|
|||||||
public class Candidate extends BaseEntity {
|
public class Candidate extends BaseEntity {
|
||||||
@Column(unique = true)
|
@Column(unique = true)
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "candidate")
|
|
||||||
private List<Assessment> assessments;
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
public enum EmployeePosition {
|
||||||
|
JUNIOR_DEV,
|
||||||
|
JUNIOR_QA,
|
||||||
|
SENIOR_DEV,
|
||||||
|
SENIOR_QA
|
||||||
|
}
|
30
src/main/java/com/primefactorsolutions/model/Evaluation.java
Normal file
30
src/main/java/com/primefactorsolutions/model/Evaluation.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import io.hypersistence.utils.hibernate.type.json.JsonType;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
import org.hibernate.annotations.Type;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class Evaluation extends BaseEntity {
|
||||||
|
@ManyToOne
|
||||||
|
private Candidate candidate;
|
||||||
|
private EmployeePosition candidatePosition;
|
||||||
|
private Employee interviewer;
|
||||||
|
@Type(JsonType.class)
|
||||||
|
@Column(columnDefinition = "json")
|
||||||
|
@ColumnDefault("JSON_ARRAY()")
|
||||||
|
private List<SkillEvaluation> skillEvaluations = Lists.newArrayList();
|
||||||
|
private Integer points;
|
||||||
|
@OneToMany(fetch = FetchType.EAGER, mappedBy = "evaluation")
|
||||||
|
private List<Exam> exams;
|
||||||
|
}
|
@ -15,30 +15,33 @@ import java.util.Optional;
|
|||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class Assessment extends BaseEntity {
|
public class Exam extends BaseEntity {
|
||||||
@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
|
@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
|
||||||
@JoinTable(name = "ASSESSMENT_QUESTIONS", joinColumns = @JoinColumn(name = "assessment_id"),
|
@JoinTable(name = "EXAM_QUESTIONS", joinColumns = @JoinColumn(name = "exam_id"),
|
||||||
inverseJoinColumns = @JoinColumn(name = "question_id"))
|
inverseJoinColumns = @JoinColumn(name = "question_id"))
|
||||||
private List<Question> questions = new ArrayList<>();
|
private List<Question> questions = new ArrayList<>();
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "assessment", cascade = {CascadeType.ALL})
|
@OneToMany(fetch = FetchType.EAGER, mappedBy = "exam", cascade = {CascadeType.ALL})
|
||||||
private List<Submission> submissions = new ArrayList<>();
|
private List<Submission> submissions = new ArrayList<>();
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
private Candidate candidate;
|
private Candidate candidate;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Evaluation evaluation;
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
|
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
|
||||||
@JoinColumn(name = "ASSESSMENT_ID")
|
@JoinColumn(name = "EXAM_ID")
|
||||||
private List<AssessmentEvent> assessmentEvents = new ArrayList<>();
|
private List<ExamEvent> examEvents = new ArrayList<>();
|
||||||
|
|
||||||
public Submission getCurrentSubmission() {
|
public Submission getCurrentSubmission() {
|
||||||
return submissions.getLast();
|
return submissions.getLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getRemainingTimeSeconds() {
|
public Long getRemainingTimeSeconds() {
|
||||||
final Optional<Instant> started = assessmentEvents.stream()
|
final Optional<Instant> started = examEvents.stream()
|
||||||
.filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
.filter(e -> e.getStatus() == ExamStatus.STARTED)
|
||||||
.map(AssessmentEvent::getTimestamp)
|
.map(ExamEvent::getTimestamp)
|
||||||
.findFirst();
|
.findFirst();
|
||||||
|
|
||||||
final Integer totalTimeMinutes = questions.stream()
|
final Integer totalTimeMinutes = questions.stream()
|
||||||
@ -52,24 +55,24 @@ public class Assessment extends BaseEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Instant getStartingTime() {
|
public Instant getStartingTime() {
|
||||||
final Optional<Instant> started = assessmentEvents.stream()
|
final Optional<Instant> started = examEvents.stream()
|
||||||
.filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
.filter(e -> e.getStatus() == ExamStatus.STARTED)
|
||||||
.map(AssessmentEvent::getTimestamp)
|
.map(ExamEvent::getTimestamp)
|
||||||
.findFirst();
|
.findFirst();
|
||||||
|
|
||||||
return started.orElse(null);
|
return started.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCompleted() {
|
public boolean isCompleted() {
|
||||||
return assessmentEvents.stream().filter(e -> e.getStatus() == AssessmentStatus.COMPLETED)
|
return examEvents.stream().filter(e -> e.getStatus() == ExamStatus.COMPLETED)
|
||||||
.map(AssessmentEvent::getTimestamp)
|
.map(ExamEvent::getTimestamp)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.isPresent();
|
.isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStarted() {
|
public boolean isStarted() {
|
||||||
return assessmentEvents.stream().filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
return examEvents.stream().filter(e -> e.getStatus() == ExamStatus.STARTED)
|
||||||
.map(AssessmentEvent::getTimestamp)
|
.map(ExamEvent::getTimestamp)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.isPresent();
|
.isPresent();
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ import java.time.Instant;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class AssessmentEvent extends BaseEntity {
|
public class ExamEvent extends BaseEntity {
|
||||||
private Instant timestamp;
|
private Instant timestamp;
|
||||||
private AssessmentStatus status;
|
private ExamStatus status;
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package com.primefactorsolutions.model;
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
public enum AssessmentStatus {
|
public enum ExamStatus {
|
||||||
CREATED,
|
CREATED,
|
||||||
STARTED,
|
STARTED,
|
||||||
COMPLETED
|
COMPLETED
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
public record SkillEvaluation (SkillType skillType, SkillLevel level, String comments) {
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
public enum SkillLevel {
|
||||||
|
NEEDS_IMPROVEMENT,
|
||||||
|
FAIR,
|
||||||
|
VERY_GOOD,
|
||||||
|
EXCELLENT
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.primefactorsolutions.model;
|
||||||
|
|
||||||
|
public enum SkillType {
|
||||||
|
TECHNICAL_KNOWLEDGE,
|
||||||
|
ASSERTIVENESS,
|
||||||
|
COMPLETENESS_AND_CONCISENESS,
|
||||||
|
COMMUNICATION
|
||||||
|
}
|
@ -23,7 +23,7 @@ public class Submission extends BaseEntity {
|
|||||||
private Question question;
|
private Question question;
|
||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
private String response;
|
private String text;
|
||||||
|
|
||||||
@Type(JsonType.class)
|
@Type(JsonType.class)
|
||||||
@Column(columnDefinition = "json")
|
@Column(columnDefinition = "json")
|
||||||
@ -32,5 +32,5 @@ public class Submission extends BaseEntity {
|
|||||||
private SubmissionStatus submissionStatus;
|
private SubmissionStatus submissionStatus;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
private Assessment assessment;
|
private Exam exam;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.primefactorsolutions.repositories;
|
package com.primefactorsolutions.repositories;
|
||||||
|
|
||||||
import com.primefactorsolutions.model.Assessment;
|
import com.primefactorsolutions.model.Exam;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface AssessmentRepository extends JpaRepository<Assessment, UUID> {
|
public interface ExamRepository extends JpaRepository<Exam, UUID> {
|
||||||
}
|
}
|
@ -1,199 +0,0 @@
|
|||||||
package com.primefactorsolutions.service;
|
|
||||||
|
|
||||||
import com.primefactorsolutions.model.*;
|
|
||||||
import com.primefactorsolutions.repositories.AssessmentRepository;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.mail.SimpleMailMessage;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Slf4j
|
|
||||||
public class AssessmentService {
|
|
||||||
|
|
||||||
private final AssessmentRepository assessmentRepository;
|
|
||||||
private final EntityManager entityManager;
|
|
||||||
private final JavaMailSender emailSender;
|
|
||||||
|
|
||||||
public Assessment createOrUpdate(final Assessment assessment) {
|
|
||||||
final Assessment saved = assessmentRepository.save(assessment);
|
|
||||||
|
|
||||||
return saved;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendEmail(final Assessment assessment) {
|
|
||||||
try {
|
|
||||||
final String evaluationLink = String.format("https://careers.primefactorsolutions.com/evaluation/%s",
|
|
||||||
assessment.getId());
|
|
||||||
final SimpleMailMessage message = new SimpleMailMessage();
|
|
||||||
message.setFrom("no-reply@primefactorsolutions.com");
|
|
||||||
message.setBcc("no-reply@primefactorsolutions.com");
|
|
||||||
message.setTo(assessment.getCandidate().getEmail());
|
|
||||||
message.setSubject("PFS - Evaluacion Tecnica");
|
|
||||||
message.setText(String.format("Estimado candidato,\n\nGracias por su candidatura. En esta etapa del "
|
|
||||||
+ "proceso de seleccion, usted debe completar "
|
|
||||||
+ "una evaluacion tecnica de programacion en JAVA. La prueba tiene una duracion de 30 minutos y "
|
|
||||||
+ "puede completarla cuando tenga una buena "
|
|
||||||
+ "conexion de internet.\n\n"
|
|
||||||
+ "Haga click aca: " + evaluationLink + "\n\n"
|
|
||||||
+ "Exito!"));
|
|
||||||
|
|
||||||
emailSender.send(message);
|
|
||||||
log.info("Sent email to {}", assessment.getCandidate().getEmail());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error sending email to {}", assessment.getCandidate().getEmail(), e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Assessment> getAssessments() {
|
|
||||||
return assessmentRepository.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Assessment getAssessment(final UUID id) {
|
|
||||||
return assessmentRepository.findById(id).orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Assessment startAssessment(final UUID id) {
|
|
||||||
final Assessment assessment = assessmentRepository.findById(id).get();
|
|
||||||
if (assessment.isStarted()) {
|
|
||||||
return assessment;
|
|
||||||
}
|
|
||||||
|
|
||||||
assessment.getAssessmentEvents().add(new AssessmentEvent(Instant.now(), AssessmentStatus.STARTED));
|
|
||||||
|
|
||||||
return assessmentRepository.save(assessment);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Submission getNextSubmission(final UUID assessmentId, final UUID currSubmissionId) {
|
|
||||||
return getNextSubmission(assessmentId, currSubmissionId, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Submission getNextSubmission(final UUID assessmentId, final UUID currSubmissionId,
|
|
||||||
final boolean checkCompleted) {
|
|
||||||
final Assessment assessment = assessmentRepository.findById(assessmentId).get();
|
|
||||||
|
|
||||||
Assessment saved;
|
|
||||||
if (currSubmissionId == null) {
|
|
||||||
if (checkCompleted && assessment.isCompleted()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Question firstQuestion = assessment.getQuestions().stream().findFirst().get();
|
|
||||||
final Optional<Submission> submissionToReturn = assessment.getSubmissions().stream()
|
|
||||||
.filter(s -> s.getQuestion().equals(firstQuestion))
|
|
||||||
.findFirst();
|
|
||||||
|
|
||||||
if (submissionToReturn.isEmpty()) {
|
|
||||||
final Submission result = new Submission(firstQuestion, firstQuestion.getContent(), Map.of(),
|
|
||||||
SubmissionStatus.FAIL, assessment);
|
|
||||||
assessment.getSubmissions().add(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
saved = assessmentRepository.save(assessment);
|
|
||||||
final Optional<Submission> submissionToReturn2 = saved.getSubmissions().stream()
|
|
||||||
.filter(s -> s.getQuestion().equals(firstQuestion))
|
|
||||||
.findFirst();
|
|
||||||
|
|
||||||
return submissionToReturn2.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
final Submission currSubmission = assessment.getSubmissions().stream()
|
|
||||||
.filter(s -> s.getId().equals(currSubmissionId))
|
|
||||||
.findFirst().get();
|
|
||||||
final Question currQuestion = currSubmission.getQuestion();
|
|
||||||
int idx = assessment.getQuestions().indexOf(currQuestion);
|
|
||||||
|
|
||||||
if (idx == assessment.getQuestions().size() - 1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Question nextQuestion = assessment.getQuestions().get(idx + 1);
|
|
||||||
|
|
||||||
final Optional<Submission> submissionToReturn = assessment.getSubmissions().stream()
|
|
||||||
.filter(s -> s.getQuestion().equals(nextQuestion))
|
|
||||||
.findFirst();
|
|
||||||
|
|
||||||
if (submissionToReturn.isEmpty()) {
|
|
||||||
final Submission result = new Submission(nextQuestion, nextQuestion.getContent(), Map.of(),
|
|
||||||
SubmissionStatus.FAIL, assessment);
|
|
||||||
assessment.getSubmissions().add(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
saved = assessmentRepository.save(assessment);
|
|
||||||
final Optional<Submission> submissionToReturn2 = saved.getSubmissions().stream()
|
|
||||||
.filter(s -> s.getQuestion().equals(nextQuestion))
|
|
||||||
.findFirst();
|
|
||||||
|
|
||||||
return submissionToReturn2.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Submission getPrevSubmission(final UUID assessmentId, final Submission currSubmission) {
|
|
||||||
if (currSubmission == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Question currQuestion = currSubmission.getQuestion();
|
|
||||||
Assessment assessment = assessmentRepository.findById(assessmentId).get();
|
|
||||||
int idx = assessment.getQuestions().indexOf(currQuestion);
|
|
||||||
|
|
||||||
if (idx == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Question prevQuestion = assessment.getQuestions().get(idx - 1);
|
|
||||||
|
|
||||||
return assessment.getSubmissions().stream()
|
|
||||||
.filter(s -> s.getQuestion().equals(prevQuestion))
|
|
||||||
.findFirst().orElseThrow(() -> new IllegalStateException("submission invalid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Assessment completeAssessment(final UUID id) {
|
|
||||||
Assessment assessment = assessmentRepository.findById(id).get();
|
|
||||||
Optional<AssessmentEvent> completed = assessment.getAssessmentEvents().stream()
|
|
||||||
.filter(e -> e.getStatus() == AssessmentStatus.COMPLETED)
|
|
||||||
.findFirst();
|
|
||||||
|
|
||||||
if (completed.isPresent()) {
|
|
||||||
return assessment;
|
|
||||||
}
|
|
||||||
|
|
||||||
assessment.getAssessmentEvents().add(new AssessmentEvent(Instant.now(), AssessmentStatus.COMPLETED));
|
|
||||||
Assessment saved = assessmentRepository.save(assessment);
|
|
||||||
|
|
||||||
return saved;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveSubmission(final UUID id, final Submission currSubmission) {
|
|
||||||
Assessment assessment = assessmentRepository.findById(id).get();
|
|
||||||
final Submission submission = assessment.getSubmissions().stream()
|
|
||||||
.filter(s -> s.getId().equals(currSubmission.getId()))
|
|
||||||
.findFirst().get();
|
|
||||||
|
|
||||||
submission.setResponse(currSubmission.getResponse());
|
|
||||||
Assessment saved = assessmentRepository.save(assessment);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Assessment saveAssessment(final Assessment assessment) {
|
|
||||||
Candidate merged = entityManager.merge(assessment.getCandidate());
|
|
||||||
List<Question> mergedQuestions = assessment.getQuestions().stream().map(entityManager::merge)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
assessment.setCandidate(merged);
|
|
||||||
assessment.setQuestions(mergedQuestions);
|
|
||||||
|
|
||||||
return assessmentRepository.save(assessment);
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,8 +13,8 @@ import java.util.UUID;
|
|||||||
public class CandidateService {
|
public class CandidateService {
|
||||||
private final CandidateRepository candidateRepository;
|
private final CandidateRepository candidateRepository;
|
||||||
|
|
||||||
public Candidate createOrUpdate(final Candidate assessment) {
|
public Candidate createOrUpdate(final Candidate candidate) {
|
||||||
final Candidate saved = candidateRepository.save(assessment);
|
final Candidate saved = candidateRepository.save(candidate);
|
||||||
|
|
||||||
return saved;
|
return saved;
|
||||||
}
|
}
|
||||||
|
198
src/main/java/com/primefactorsolutions/service/ExamService.java
Normal file
198
src/main/java/com/primefactorsolutions/service/ExamService.java
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
package com.primefactorsolutions.service;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.*;
|
||||||
|
import com.primefactorsolutions.repositories.ExamRepository;
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class ExamService {
|
||||||
|
|
||||||
|
private final ExamRepository examRepository;
|
||||||
|
private final EntityManager entityManager;
|
||||||
|
private final JavaMailSender emailSender;
|
||||||
|
|
||||||
|
public Exam createOrUpdate(final Exam exam) {
|
||||||
|
return examRepository.save(exam);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendEmail(final Exam exam) {
|
||||||
|
try {
|
||||||
|
final String evaluationLink = String.format("https://careers.primefactorsolutions.com/evaluation/%s",
|
||||||
|
exam.getId());
|
||||||
|
final SimpleMailMessage message = new SimpleMailMessage();
|
||||||
|
message.setFrom("no-reply@primefactorsolutions.com");
|
||||||
|
message.setBcc("no-reply@primefactorsolutions.com");
|
||||||
|
message.setTo(exam.getCandidate().getEmail());
|
||||||
|
message.setSubject("PFS - Evaluacion Tecnica");
|
||||||
|
message.setText(String.format("Estimado candidato,\n\nGracias por su candidatura. En esta etapa del "
|
||||||
|
+ "proceso de seleccion, usted debe completar "
|
||||||
|
+ "una evaluacion tecnica de programacion en JAVA. La prueba tiene una duracion de 30 minutos y "
|
||||||
|
+ "puede completarla cuando tenga una buena "
|
||||||
|
+ "conexion de internet.\n\n"
|
||||||
|
+ "Haga click aca: " + evaluationLink + "\n\n"
|
||||||
|
+ "Exito!"));
|
||||||
|
|
||||||
|
emailSender.send(message);
|
||||||
|
log.info("Sent email to {}", exam.getCandidate().getEmail());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error sending email to {}", exam.getCandidate().getEmail(), e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Exam> getExams() {
|
||||||
|
return examRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exam getExam(final UUID id) {
|
||||||
|
return examRepository.findById(id).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exam startExam(final UUID id) {
|
||||||
|
final Exam exam = examRepository.findById(id).get();
|
||||||
|
|
||||||
|
if (exam.isStarted()) {
|
||||||
|
return exam;
|
||||||
|
}
|
||||||
|
|
||||||
|
exam.getExamEvents().add(new ExamEvent(Instant.now(), ExamStatus.STARTED));
|
||||||
|
|
||||||
|
return examRepository.save(exam);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Submission getNextSubmission(final UUID examId, final UUID currSubmissionId) {
|
||||||
|
return getNextSubmission(examId, currSubmissionId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Submission getNextSubmission(final UUID examId, final UUID currSubmissionId,
|
||||||
|
final boolean checkCompleted) {
|
||||||
|
final Exam exam = examRepository.findById(examId).get();
|
||||||
|
|
||||||
|
Exam saved;
|
||||||
|
if (currSubmissionId == null) {
|
||||||
|
if (checkCompleted && exam.isCompleted()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question firstQuestion = exam.getQuestions().stream().findFirst().get();
|
||||||
|
final Optional<Submission> submissionToReturn = exam.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getQuestion().equals(firstQuestion))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (submissionToReturn.isEmpty()) {
|
||||||
|
final Submission result = new Submission(firstQuestion, firstQuestion.getContent(), Map.of(),
|
||||||
|
SubmissionStatus.FAIL, exam);
|
||||||
|
exam.getSubmissions().add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
saved = examRepository.save(exam);
|
||||||
|
final Optional<Submission> submissionToReturn2 = saved.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getQuestion().equals(firstQuestion))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
return submissionToReturn2.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Submission currSubmission = exam.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getId().equals(currSubmissionId))
|
||||||
|
.findFirst().get();
|
||||||
|
final Question currQuestion = currSubmission.getQuestion();
|
||||||
|
int idx = exam.getQuestions().indexOf(currQuestion);
|
||||||
|
|
||||||
|
if (idx == exam.getQuestions().size() - 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question nextQuestion = exam.getQuestions().get(idx + 1);
|
||||||
|
|
||||||
|
final Optional<Submission> submissionToReturn = exam.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getQuestion().equals(nextQuestion))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (submissionToReturn.isEmpty()) {
|
||||||
|
final Submission result = new Submission(nextQuestion, nextQuestion.getContent(), Map.of(),
|
||||||
|
SubmissionStatus.FAIL, exam);
|
||||||
|
exam.getSubmissions().add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
saved = examRepository.save(exam);
|
||||||
|
final Optional<Submission> submissionToReturn2 = saved.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getQuestion().equals(nextQuestion))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
return submissionToReturn2.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Submission getPrevSubmission(final UUID examId, final Submission currSubmission) {
|
||||||
|
if (currSubmission == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question currQuestion = currSubmission.getQuestion();
|
||||||
|
Exam exam = examRepository.findById(examId).get();
|
||||||
|
int idx = exam.getQuestions().indexOf(currQuestion);
|
||||||
|
|
||||||
|
if (idx == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Question prevQuestion = exam.getQuestions().get(idx - 1);
|
||||||
|
|
||||||
|
return exam.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getQuestion().equals(prevQuestion))
|
||||||
|
.findFirst().orElseThrow(() -> new IllegalStateException("submission invalid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exam completeExam(final UUID id) {
|
||||||
|
Exam exam = examRepository.findById(id).get();
|
||||||
|
Optional<ExamEvent> completed = exam.getExamEvents().stream()
|
||||||
|
.filter(e -> e.getStatus() == ExamStatus.COMPLETED)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (completed.isPresent()) {
|
||||||
|
return exam;
|
||||||
|
}
|
||||||
|
|
||||||
|
exam.getExamEvents().add(new ExamEvent(Instant.now(), ExamStatus.COMPLETED));
|
||||||
|
Exam saved = examRepository.save(exam);
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveSubmission(final UUID id, final Submission currSubmission) {
|
||||||
|
Exam exam = examRepository.findById(id).get();
|
||||||
|
final Submission submission = exam.getSubmissions().stream()
|
||||||
|
.filter(s -> s.getId().equals(currSubmission.getId()))
|
||||||
|
.findFirst().get();
|
||||||
|
|
||||||
|
submission.setText(currSubmission.getText());
|
||||||
|
Exam saved = examRepository.save(exam);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Exam saveExam(final Exam exam) {
|
||||||
|
Candidate merged = entityManager.merge(exam.getCandidate());
|
||||||
|
List<Question> mergedQuestions = exam.getQuestions().stream().map(entityManager::merge)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
exam.setCandidate(merged);
|
||||||
|
exam.setQuestions(mergedQuestions);
|
||||||
|
|
||||||
|
return examRepository.save(exam);
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ import com.hilerio.ace.AceEditor;
|
|||||||
import com.hilerio.ace.AceMode;
|
import com.hilerio.ace.AceMode;
|
||||||
import com.hilerio.ace.AceTheme;
|
import com.hilerio.ace.AceTheme;
|
||||||
import com.primefactorsolutions.model.*;
|
import com.primefactorsolutions.model.*;
|
||||||
import com.primefactorsolutions.service.AssessmentService;
|
import com.primefactorsolutions.service.ExamService;
|
||||||
import com.primefactorsolutions.service.CompilerService;
|
import com.primefactorsolutions.service.CompilerService;
|
||||||
import com.vaadin.flow.component.*;
|
import com.vaadin.flow.component.*;
|
||||||
import com.vaadin.flow.component.button.Button;
|
import com.vaadin.flow.component.button.Button;
|
||||||
@ -60,13 +60,13 @@ import java.util.stream.Collectors;
|
|||||||
public class EvaluationView extends Main implements HasUrlParameter<String> {
|
public class EvaluationView extends Main implements HasUrlParameter<String> {
|
||||||
|
|
||||||
private final CompilerService compilerService;
|
private final CompilerService compilerService;
|
||||||
private final AssessmentService assessmentService;
|
private final ExamService examService;
|
||||||
|
|
||||||
private AceEditor questionEditor = null;
|
private AceEditor questionEditor = null;
|
||||||
private Dialog dialog = null;
|
private Dialog dialog = null;
|
||||||
private Dialog completeDialog = null;
|
private Dialog completeDialog = null;
|
||||||
private AceEditor result = null;
|
private AceEditor result = null;
|
||||||
private Assessment assessment = null;
|
private Exam exam = null;
|
||||||
private Submission currSubmission = null;
|
private Submission currSubmission = null;
|
||||||
private Boolean isCompleted = false;
|
private Boolean isCompleted = false;
|
||||||
|
|
||||||
@ -83,9 +83,9 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
private H3 questionTitle = null;
|
private H3 questionTitle = null;
|
||||||
private Text questionDescription = null;
|
private Text questionDescription = null;
|
||||||
|
|
||||||
public EvaluationView(final CompilerService compilerService, final AssessmentService assessmentService) {
|
public EvaluationView(final CompilerService compilerService, final ExamService examService) {
|
||||||
this.compilerService = compilerService;
|
this.compilerService = compilerService;
|
||||||
this.assessmentService = assessmentService;
|
this.examService = examService;
|
||||||
|
|
||||||
addClassNames(Display.FLEX, Flex.GROW, Height.FULL);
|
addClassNames(Display.FLEX, Flex.GROW, Height.FULL);
|
||||||
|
|
||||||
@ -128,8 +128,8 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
dialog.add(dialogLayout);
|
dialog.add(dialogLayout);
|
||||||
|
|
||||||
final Button saveButton = new Button("Guardar y Siguiente", e -> {
|
final Button saveButton = new Button("Guardar y Siguiente", e -> {
|
||||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
this.currSubmission.setText(this.questionEditor.getValue());
|
||||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||||
dialog.close();
|
dialog.close();
|
||||||
goToNext();
|
goToNext();
|
||||||
});
|
});
|
||||||
@ -156,9 +156,9 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
|
|
||||||
final Button completeButton = new Button("Terminar", e -> {
|
final Button completeButton = new Button("Terminar", e -> {
|
||||||
completeDialog.close();
|
completeDialog.close();
|
||||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
this.currSubmission.setText(this.questionEditor.getValue());
|
||||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||||
this.assessment = assessmentService.completeAssessment(assessment.getId());
|
this.exam = examService.completeExam(exam.getId());
|
||||||
goToCompleted();
|
goToCompleted();
|
||||||
updateUI();
|
updateUI();
|
||||||
});
|
});
|
||||||
@ -196,20 +196,20 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
final MenuBar navMenuBar = new MenuBar();
|
final MenuBar navMenuBar = new MenuBar();
|
||||||
prev = navMenuBar.addItem("Anterior pregunta",
|
prev = navMenuBar.addItem("Anterior pregunta",
|
||||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
this.currSubmission.setText(this.questionEditor.getValue());
|
||||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||||
this.currSubmission = this.assessmentService.getPrevSubmission(assessment.getId(), this.currSubmission);
|
this.currSubmission = this.examService.getPrevSubmission(exam.getId(), this.currSubmission);
|
||||||
updateUI();
|
updateUI();
|
||||||
});
|
});
|
||||||
next = navMenuBar.addItem("Siguiente pregunta",
|
next = navMenuBar.addItem("Siguiente pregunta",
|
||||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
this.currSubmission.setText(this.questionEditor.getValue());
|
||||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||||
goToNext();
|
goToNext();
|
||||||
});
|
});
|
||||||
reset = navMenuBar.addItem("Reiniciar pregunta (deshacer todos los cambios)",
|
reset = navMenuBar.addItem("Reiniciar pregunta (deshacer todos los cambios)",
|
||||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||||
this.currSubmission.setResponse(this.currSubmission.getQuestion().getContent());
|
this.currSubmission.setText(this.currSubmission.getQuestion().getContent());
|
||||||
this.questionEditor.setValue(this.currSubmission.getQuestion().getContent());
|
this.questionEditor.setValue(this.currSubmission.getQuestion().getContent());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -252,9 +252,9 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
start = new Button("Empezar");
|
start = new Button("Empezar");
|
||||||
start.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
start.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||||
start.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
start.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||||
this.assessment = this.assessmentService.startAssessment(this.assessment.getId());
|
this.exam = this.examService.startExam(this.exam.getId());
|
||||||
|
|
||||||
if (tf.getValue().trim().equalsIgnoreCase(this.assessment.getCandidate().getEmail())) {
|
if (tf.getValue().trim().equalsIgnoreCase(this.exam.getCandidate().getEmail())) {
|
||||||
this.getUI().get().getPage().reload();
|
this.getUI().get().getPage().reload();
|
||||||
} else {
|
} else {
|
||||||
Notification notification = new Notification();
|
Notification notification = new Notification();
|
||||||
@ -316,7 +316,7 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void goToNext() {
|
private void goToNext() {
|
||||||
Submission found = this.assessmentService.getNextSubmission(assessment.getId(),
|
Submission found = this.examService.getNextSubmission(exam.getId(),
|
||||||
this.currSubmission.getId());
|
this.currSubmission.getId());
|
||||||
|
|
||||||
if (found == null) {
|
if (found == null) {
|
||||||
@ -343,9 +343,9 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
timer.setMinutes(true);
|
timer.setMinutes(true);
|
||||||
timer.addTimerEndEvent((ComponentEventListener<SimpleTimer.TimerEndedEvent>) timerEndedEvent -> {
|
timer.addTimerEndEvent((ComponentEventListener<SimpleTimer.TimerEndedEvent>) timerEndedEvent -> {
|
||||||
Notification.show("Tiempo completado.", 5_000, Notification.Position.TOP_CENTER);
|
Notification.show("Tiempo completado.", 5_000, Notification.Position.TOP_CENTER);
|
||||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
this.currSubmission.setText(this.questionEditor.getValue());
|
||||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||||
this.assessment = assessmentService.completeAssessment(assessment.getId());
|
this.exam = examService.completeExam(exam.getId());
|
||||||
goToCompleted();
|
goToCompleted();
|
||||||
updateUI();
|
updateUI();
|
||||||
});
|
});
|
||||||
@ -362,13 +362,13 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateUI() {
|
private void updateUI() {
|
||||||
if (assessment == null || !assessment.isStarted()) {
|
if (exam == null || !exam.isStarted()) {
|
||||||
editorSection.setVisible(false);
|
editorSection.setVisible(false);
|
||||||
startSection.setVisible(true);
|
startSection.setVisible(true);
|
||||||
sidebar.setVisible(false);
|
sidebar.setVisible(false);
|
||||||
} else {
|
} else {
|
||||||
if (currSubmission != null) {
|
if (currSubmission != null) {
|
||||||
questionEditor.setValue(this.currSubmission.getResponse());
|
questionEditor.setValue(this.currSubmission.getText());
|
||||||
questionTitle.setText(this.currSubmission.getQuestion().getTitle());
|
questionTitle.setText(this.currSubmission.getQuestion().getTitle());
|
||||||
questionDescription.setText(this.currSubmission.getQuestion().getDescription());
|
questionDescription.setText(this.currSubmission.getQuestion().getDescription());
|
||||||
}
|
}
|
||||||
@ -377,10 +377,10 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
startSection.setVisible(false);
|
startSection.setVisible(false);
|
||||||
sidebar.setVisible(true);
|
sidebar.setVisible(true);
|
||||||
|
|
||||||
prev.setEnabled(currSubmission != null && !assessment.isFirst(currSubmission));
|
prev.setEnabled(currSubmission != null && !exam.isFirst(currSubmission));
|
||||||
next.setEnabled(currSubmission == null || !assessment.isLast(currSubmission));
|
next.setEnabled(currSubmission == null || !exam.isLast(currSubmission));
|
||||||
|
|
||||||
if (this.assessment.isCompleted()) {
|
if (this.exam.isCompleted()) {
|
||||||
goToCompleted();
|
goToCompleted();
|
||||||
this.editorSection.setVisible(false);
|
this.editorSection.setVisible(false);
|
||||||
this.sidebar.setVisible(false);
|
this.sidebar.setVisible(false);
|
||||||
@ -390,15 +390,15 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
|
|
||||||
if (dl.getChildren().collect(Collectors.toList()).isEmpty()) {
|
if (dl.getChildren().collect(Collectors.toList()).isEmpty()) {
|
||||||
dl.add(
|
dl.add(
|
||||||
createItem("Candidato:", assessment.getCandidate().getEmail()),
|
createItem("Candidato:", exam.getCandidate().getEmail()),
|
||||||
createItem("Hora de inicio:", Optional.ofNullable(assessment.getStartingTime())
|
createItem("Hora de inicio:", Optional.ofNullable(exam.getStartingTime())
|
||||||
.map(t -> ZonedDateTime.ofInstant(t,
|
.map(t -> ZonedDateTime.ofInstant(t,
|
||||||
ZoneId.of("GMT-4")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
|
ZoneId.of("GMT-4")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
|
||||||
.orElse("N/A"))
|
.orElse("N/A"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Long remainingTime = this.assessment.getRemainingTimeSeconds();
|
final Long remainingTime = this.exam.getRemainingTimeSeconds();
|
||||||
timer.pause();
|
timer.pause();
|
||||||
timer.setStartTime(remainingTime > 0 ? remainingTime : 3);
|
timer.setStartTime(remainingTime > 0 ? remainingTime : 3);
|
||||||
timer.setMinutes(true);
|
timer.setMinutes(true);
|
||||||
@ -434,18 +434,18 @@ public class EvaluationView extends Main implements HasUrlParameter<String> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||||
this.assessment = this.assessmentService.getAssessment(UUID.fromString(s));
|
this.exam = this.examService.getExam(UUID.fromString(s));
|
||||||
|
|
||||||
if (this.assessment == null) {
|
if (this.exam == null) {
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.assessment.isCompleted()) {
|
if (this.exam.isCompleted()) {
|
||||||
goToCompleted();
|
goToCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currSubmission = this.assessment.isStarted()
|
this.currSubmission = this.exam.isStarted()
|
||||||
? this.assessmentService.getNextSubmission(assessment.getId(), null)
|
? this.examService.getNextSubmission(exam.getId(), null)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
updateUI();
|
updateUI();
|
||||||
|
@ -4,7 +4,7 @@ import com.primefactorsolutions.model.Employee;
|
|||||||
import com.primefactorsolutions.views.employee.DocumentsListView;
|
import com.primefactorsolutions.views.employee.DocumentsListView;
|
||||||
import com.primefactorsolutions.views.employee.EmployeesListView;
|
import com.primefactorsolutions.views.employee.EmployeesListView;
|
||||||
import com.primefactorsolutions.views.admin.TimeOffListView;
|
import com.primefactorsolutions.views.admin.TimeOffListView;
|
||||||
import com.primefactorsolutions.views.assessment.AssessmentsListView;
|
import com.primefactorsolutions.views.assessment.ExamsListView;
|
||||||
import com.primefactorsolutions.views.assessment.CandidatesListView;
|
import com.primefactorsolutions.views.assessment.CandidatesListView;
|
||||||
import com.primefactorsolutions.views.assessment.QuestionsListView;
|
import com.primefactorsolutions.views.assessment.QuestionsListView;
|
||||||
import com.primefactorsolutions.views.timeoff.TimeOffRequestsListView;
|
import com.primefactorsolutions.views.timeoff.TimeOffRequestsListView;
|
||||||
@ -148,7 +148,7 @@ public class MainLayout extends AppLayout {
|
|||||||
|
|
||||||
SideNavItem recruiting = new SideNavItem("Recruiting");
|
SideNavItem recruiting = new SideNavItem("Recruiting");
|
||||||
recruiting.setPrefixComponent(LineAwesomeIcon.BUSINESS_TIME_SOLID.create());
|
recruiting.setPrefixComponent(LineAwesomeIcon.BUSINESS_TIME_SOLID.create());
|
||||||
recruiting.addItem(new SideNavItem("Assessments", AssessmentsListView.class,
|
recruiting.addItem(new SideNavItem("Exams", ExamsListView.class,
|
||||||
LineAwesomeIcon.RIBBON_SOLID.create()));
|
LineAwesomeIcon.RIBBON_SOLID.create()));
|
||||||
recruiting.addItem(new SideNavItem("Candidates", CandidatesListView.class,
|
recruiting.addItem(new SideNavItem("Candidates", CandidatesListView.class,
|
||||||
LineAwesomeIcon.USER.create()));
|
LineAwesomeIcon.USER.create()));
|
||||||
|
@ -3,9 +3,9 @@ package com.primefactorsolutions.views;
|
|||||||
import com.hilerio.ace.AceEditor;
|
import com.hilerio.ace.AceEditor;
|
||||||
import com.hilerio.ace.AceMode;
|
import com.hilerio.ace.AceMode;
|
||||||
import com.hilerio.ace.AceTheme;
|
import com.hilerio.ace.AceTheme;
|
||||||
import com.primefactorsolutions.model.Assessment;
|
import com.primefactorsolutions.model.Exam;
|
||||||
import com.primefactorsolutions.model.Submission;
|
import com.primefactorsolutions.model.Submission;
|
||||||
import com.primefactorsolutions.service.AssessmentService;
|
import com.primefactorsolutions.service.ExamService;
|
||||||
import com.primefactorsolutions.service.CompilerService;
|
import com.primefactorsolutions.service.CompilerService;
|
||||||
import com.vaadin.flow.component.ClickEvent;
|
import com.vaadin.flow.component.ClickEvent;
|
||||||
import com.vaadin.flow.component.ComponentEventListener;
|
import com.vaadin.flow.component.ComponentEventListener;
|
||||||
@ -43,11 +43,11 @@ import java.util.stream.Collectors;
|
|||||||
public class SubmissionView extends Main implements HasUrlParameter<String> {
|
public class SubmissionView extends Main implements HasUrlParameter<String> {
|
||||||
|
|
||||||
private final CompilerService compilerService;
|
private final CompilerService compilerService;
|
||||||
private final AssessmentService assessmentService;
|
private final ExamService examService;
|
||||||
private AceEditor questionEditor = null;
|
private AceEditor questionEditor = null;
|
||||||
private AceEditor result = null;
|
private AceEditor result = null;
|
||||||
private Dialog dialog = null;
|
private Dialog dialog = null;
|
||||||
private Assessment assessment = null;
|
private Exam exam = null;
|
||||||
private Submission currSubmission = null;
|
private Submission currSubmission = null;
|
||||||
private MenuItem prev = null;
|
private MenuItem prev = null;
|
||||||
private MenuItem next = null;
|
private MenuItem next = null;
|
||||||
@ -56,9 +56,9 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
|||||||
private Section editorSection = null;
|
private Section editorSection = null;
|
||||||
private H3 questionTitle = null;
|
private H3 questionTitle = null;
|
||||||
|
|
||||||
public SubmissionView(final CompilerService compilerService, final AssessmentService assessmentService) {
|
public SubmissionView(final CompilerService compilerService, final ExamService examService) {
|
||||||
this.compilerService = compilerService;
|
this.compilerService = compilerService;
|
||||||
this.assessmentService = assessmentService;
|
this.examService = examService;
|
||||||
|
|
||||||
addClassNames(Display.FLEX, Flex.GROW, Height.FULL);
|
addClassNames(Display.FLEX, Flex.GROW, Height.FULL);
|
||||||
|
|
||||||
@ -130,13 +130,13 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
|||||||
prev = navMenuBar.addItem("Anterior pregunta",
|
prev = navMenuBar.addItem("Anterior pregunta",
|
||||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||||
log.info(">>> prev");
|
log.info(">>> prev");
|
||||||
this.currSubmission = this.assessmentService.getPrevSubmission(assessment.getId(),
|
this.currSubmission = this.examService.getPrevSubmission(exam.getId(),
|
||||||
this.currSubmission);
|
this.currSubmission);
|
||||||
updateUI();
|
updateUI();
|
||||||
});
|
});
|
||||||
next = navMenuBar.addItem("Siguiente pregunta",
|
next = navMenuBar.addItem("Siguiente pregunta",
|
||||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
this.currSubmission.setText(this.questionEditor.getValue());
|
||||||
goToNext();
|
goToNext();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
|||||||
|
|
||||||
private void goToNext() {
|
private void goToNext() {
|
||||||
log.info(">>> next");
|
log.info(">>> next");
|
||||||
Submission found = this.assessmentService.getNextSubmission(assessment.getId(),
|
Submission found = this.examService.getNextSubmission(exam.getId(),
|
||||||
this.currSubmission.getId(), false);
|
this.currSubmission.getId(), false);
|
||||||
|
|
||||||
if (found != null) {
|
if (found != null) {
|
||||||
@ -208,25 +208,25 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateUI() {
|
private void updateUI() {
|
||||||
if (assessment == null || !assessment.isStarted()) {
|
if (exam == null || !exam.isStarted()) {
|
||||||
editorSection.setVisible(false);
|
editorSection.setVisible(false);
|
||||||
sidebar.setVisible(false);
|
sidebar.setVisible(false);
|
||||||
} else {
|
} else {
|
||||||
if (currSubmission != null) {
|
if (currSubmission != null) {
|
||||||
questionEditor.setValue(this.currSubmission.getResponse());
|
questionEditor.setValue(this.currSubmission.getText());
|
||||||
questionTitle.setText(this.currSubmission.getQuestion().getTitle());
|
questionTitle.setText(this.currSubmission.getQuestion().getTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
editorSection.setVisible(true);
|
editorSection.setVisible(true);
|
||||||
sidebar.setVisible(true);
|
sidebar.setVisible(true);
|
||||||
|
|
||||||
prev.setEnabled(currSubmission != null && !assessment.isFirst(currSubmission));
|
prev.setEnabled(currSubmission != null && !exam.isFirst(currSubmission));
|
||||||
next.setEnabled(currSubmission == null || !assessment.isLast(currSubmission));
|
next.setEnabled(currSubmission == null || !exam.isLast(currSubmission));
|
||||||
|
|
||||||
if (dl.getChildren().collect(Collectors.toList()).isEmpty()) {
|
if (dl.getChildren().collect(Collectors.toList()).isEmpty()) {
|
||||||
dl.add(
|
dl.add(
|
||||||
createItem("Candidato:", assessment.getCandidate().getEmail()),
|
createItem("Candidato:", exam.getCandidate().getEmail()),
|
||||||
createItem("Hora de inicio:", Optional.ofNullable(assessment.getStartingTime())
|
createItem("Hora de inicio:", Optional.ofNullable(exam.getStartingTime())
|
||||||
.map(t -> ZonedDateTime.ofInstant(t,
|
.map(t -> ZonedDateTime.ofInstant(t,
|
||||||
ZoneId.of("GMT-4")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
|
ZoneId.of("GMT-4")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
|
||||||
.orElse("N/A"))
|
.orElse("N/A"))
|
||||||
@ -258,14 +258,14 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||||
this.assessment = this.assessmentService.getAssessment(UUID.fromString(s));
|
this.exam = this.examService.getExam(UUID.fromString(s));
|
||||||
|
|
||||||
if (this.assessment == null) {
|
if (this.exam == null) {
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currSubmission = this.assessment.isStarted()
|
this.currSubmission = this.exam.isStarted()
|
||||||
? this.assessmentService.getNextSubmission(assessment.getId(), null, false)
|
? this.examService.getNextSubmission(exam.getId(), null, false)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
updateUI();
|
updateUI();
|
||||||
|
@ -21,7 +21,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
@PageTitle("Assessments")
|
@PageTitle("Candidates")
|
||||||
@Route(value = "/candidates", layout = MainLayout.class)
|
@Route(value = "/candidates", layout = MainLayout.class)
|
||||||
@PermitAll
|
@PermitAll
|
||||||
public class CandidateView extends BaseEntityForm<Candidate> implements HasUrlParameter<String> {
|
public class CandidateView extends BaseEntityForm<Candidate> implements HasUrlParameter<String> {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.primefactorsolutions.views.assessment;
|
package com.primefactorsolutions.views.assessment;
|
||||||
|
|
||||||
import com.primefactorsolutions.model.Candidate;
|
import com.primefactorsolutions.model.Candidate;
|
||||||
import com.primefactorsolutions.model.Assessment;
|
import com.primefactorsolutions.model.Exam;
|
||||||
import com.primefactorsolutions.model.Question;
|
import com.primefactorsolutions.model.Question;
|
||||||
import com.primefactorsolutions.service.AssessmentService;
|
import com.primefactorsolutions.service.ExamService;
|
||||||
import com.primefactorsolutions.service.QuestionService;
|
import com.primefactorsolutions.service.QuestionService;
|
||||||
import com.primefactorsolutions.service.CandidateService;
|
import com.primefactorsolutions.service.CandidateService;
|
||||||
import com.primefactorsolutions.views.MainLayout;
|
import com.primefactorsolutions.views.MainLayout;
|
||||||
@ -28,20 +28,20 @@ import java.util.UUID;
|
|||||||
@SpringComponent
|
@SpringComponent
|
||||||
@PermitAll
|
@PermitAll
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
@PageTitle("Assessments")
|
@PageTitle("Exams")
|
||||||
@Route(value = "/assessments", layout = MainLayout.class)
|
@Route(value = "/exams", layout = MainLayout.class)
|
||||||
@Uses(ComboBox.class)
|
@Uses(ComboBox.class)
|
||||||
public class AssessmentView extends BeanValidationForm<Assessment> implements HasUrlParameter<String> {
|
public class ExamView extends BeanValidationForm<Exam> implements HasUrlParameter<String> {
|
||||||
private final AssessmentService assessmentService;
|
private final ExamService examService;
|
||||||
|
|
||||||
private ComboBox<Candidate> candidate = null;
|
private ComboBox<Candidate> candidate = null;
|
||||||
private SubListSelector<Question> questions = null;
|
private SubListSelector<Question> questions = null;
|
||||||
|
|
||||||
public AssessmentView(final AssessmentService assessmentService, final QuestionService questionService,
|
public ExamView(final ExamService examService, final QuestionService questionService,
|
||||||
final CandidateService candidateService) {
|
final CandidateService candidateService) {
|
||||||
super(Assessment.class);
|
super(Exam.class);
|
||||||
|
|
||||||
this.assessmentService = assessmentService;
|
this.examService = examService;
|
||||||
|
|
||||||
candidate = new ComboBox<>("Candidate", candidateService.getCandidates());
|
candidate = new ComboBox<>("Candidate", candidateService.getCandidates());
|
||||||
candidate.setItemLabelGenerator((ItemLabelGenerator<Candidate>) Candidate::getEmail);
|
candidate.setItemLabelGenerator((ItemLabelGenerator<Candidate>) Candidate::getEmail);
|
||||||
@ -52,8 +52,8 @@ public class AssessmentView extends BeanValidationForm<Assessment> implements Ha
|
|||||||
questions.setReadOnly(false);
|
questions.setReadOnly(false);
|
||||||
questions.setAvailableOptions(questionService.getQuestions());
|
questions.setAvailableOptions(questionService.getQuestions());
|
||||||
|
|
||||||
setSavedHandler((SavedHandler<Assessment>) assessment -> {
|
setSavedHandler((SavedHandler<Exam>) exam -> {
|
||||||
final var saved = this.assessmentService.saveAssessment(assessment);
|
final var saved = this.examService.saveExam(exam);
|
||||||
setEntityWithEnabledSave(saved);
|
setEntityWithEnabledSave(saved);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -61,11 +61,11 @@ public class AssessmentView extends BeanValidationForm<Assessment> implements Ha
|
|||||||
@Override
|
@Override
|
||||||
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||||
if (StringUtils.isNotBlank(s) && !"new".equals(s)) {
|
if (StringUtils.isNotBlank(s) && !"new".equals(s)) {
|
||||||
final var assessment = assessmentService.getAssessment(UUID.fromString(s));
|
final var exam = examService.getExam(UUID.fromString(s));
|
||||||
|
|
||||||
setEntityWithEnabledSave(assessment);
|
setEntityWithEnabledSave(exam);
|
||||||
} else {
|
} else {
|
||||||
setEntityWithEnabledSave(new Assessment());
|
setEntityWithEnabledSave(new Exam());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
package com.primefactorsolutions.views.assessment;
|
package com.primefactorsolutions.views.assessment;
|
||||||
|
|
||||||
import com.primefactorsolutions.model.Assessment;
|
import com.primefactorsolutions.model.Exam;
|
||||||
import com.primefactorsolutions.service.AssessmentService;
|
import com.primefactorsolutions.service.ExamService;
|
||||||
import com.primefactorsolutions.views.BaseView;
|
import com.primefactorsolutions.views.BaseView;
|
||||||
import com.primefactorsolutions.views.MainLayout;
|
import com.primefactorsolutions.views.MainLayout;
|
||||||
import com.primefactorsolutions.views.SubmissionView;
|
import com.primefactorsolutions.views.SubmissionView;
|
||||||
@ -25,48 +25,48 @@ import org.vaadin.firitin.components.grid.VGrid;
|
|||||||
|
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
@PageTitle("Assessments")
|
@PageTitle("Exams")
|
||||||
@Route(value = "/assessments", layout = MainLayout.class)
|
@Route(value = "/exams", layout = MainLayout.class)
|
||||||
@PermitAll
|
@PermitAll
|
||||||
public class AssessmentsListView extends BaseView {
|
public class ExamsListView extends BaseView {
|
||||||
|
|
||||||
public AssessmentsListView(final AuthenticationContext authenticationContext,
|
public ExamsListView(final AuthenticationContext authenticationContext,
|
||||||
final AssessmentService assessmentService) {
|
final ExamService examService) {
|
||||||
super(authenticationContext);
|
super(authenticationContext);
|
||||||
final HorizontalLayout hl = new HorizontalLayout();
|
final HorizontalLayout hl = new HorizontalLayout();
|
||||||
final Button addAssessment = new Button("Add Assessment");
|
final Button addExam = new Button("Add Exam");
|
||||||
addAssessment.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
addExam.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
addAssessment.addClickListener(buttonClickEvent ->
|
addExam.addClickListener(buttonClickEvent ->
|
||||||
getUI().flatMap(ui -> ui.navigate(AssessmentView.class, "new")));
|
getUI().flatMap(ui -> ui.navigate(ExamView.class, "new")));
|
||||||
hl.add(addAssessment);
|
hl.add(addExam);
|
||||||
|
|
||||||
final VGrid<Assessment> grid = new VGrid<>(Assessment.class);
|
final VGrid<Exam> grid = new VGrid<>(Exam.class);
|
||||||
grid.setColumns("id", "candidate.email");
|
grid.setColumns("id", "candidate.email");
|
||||||
final Grid.Column<Assessment> statusColumn = grid.addColumn(assessment ->
|
final Grid.Column<Exam> statusColumn = grid.addColumn(exam ->
|
||||||
assessment.getAssessmentEvents().isEmpty()
|
exam.getExamEvents().isEmpty()
|
||||||
? "N/A"
|
? "N/A"
|
||||||
: assessment.getAssessmentEvents().getLast().getStatus().name());
|
: exam.getExamEvents().getLast().getStatus().name());
|
||||||
statusColumn.setHeader("Status");
|
statusColumn.setHeader("Status");
|
||||||
|
|
||||||
grid.addComponentColumn(assessment -> MenuBarUtils.menuBar(
|
grid.addComponentColumn(exam -> MenuBarUtils.menuBar(
|
||||||
Pair.of("View", __ ->
|
Pair.of("View", __ ->
|
||||||
getUI().flatMap(ui -> ui.navigate(SubmissionView.class, assessment.getId().toString()))),
|
getUI().flatMap(ui -> ui.navigate(SubmissionView.class, exam.getId().toString()))),
|
||||||
Pair.of("Copy", __ ->
|
Pair.of("Copy", __ ->
|
||||||
ClientsideClipboard.writeToClipboard(
|
ClientsideClipboard.writeToClipboard(
|
||||||
String.format("email: %s link: https://careers.primefactorsolutions.com/evaluation/%s",
|
String.format("email: %s link: https://intra.primefactorsolutions.com/evaluation/%s",
|
||||||
assessment.getCandidate().getEmail(),
|
exam.getCandidate().getEmail(),
|
||||||
assessment.getId()))),
|
exam.getId()))),
|
||||||
Pair.of("Email", __ -> {
|
Pair.of("Email", __ -> {
|
||||||
ConfirmDialog dialog = new ConfirmDialog();
|
ConfirmDialog dialog = new ConfirmDialog();
|
||||||
dialog.setHeader("Send Link Email");
|
dialog.setHeader("Send Link Email");
|
||||||
dialog.setText(String.format("Enviar link por email al candidato %s?",
|
dialog.setText(String.format("Enviar link por email al candidato %s?",
|
||||||
assessment.getCandidate().getEmail()));
|
exam.getCandidate().getEmail()));
|
||||||
dialog.setCancelable(true);
|
dialog.setCancelable(true);
|
||||||
dialog.setConfirmText("Enviar");
|
dialog.setConfirmText("Enviar");
|
||||||
dialog.setConfirmButtonTheme("primary");
|
dialog.setConfirmButtonTheme("primary");
|
||||||
dialog.addConfirmListener(confirmEvent -> {
|
dialog.addConfirmListener(confirmEvent -> {
|
||||||
try {
|
try {
|
||||||
assessmentService.sendEmail(assessment);
|
examService.sendEmail(exam);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Notification.show("Error sending email: " + e.getMessage(), 10_000,
|
Notification.show("Error sending email: " + e.getMessage(), 10_000,
|
||||||
Notification.Position.TOP_CENTER);
|
Notification.Position.TOP_CENTER);
|
||||||
@ -76,7 +76,7 @@ public class AssessmentsListView extends BaseView {
|
|||||||
})
|
})
|
||||||
));
|
));
|
||||||
|
|
||||||
grid.setDataProvider(new ListDataProvider<>(assessmentService.getAssessments()));
|
grid.setDataProvider(new ListDataProvider<>(examService.getExams()));
|
||||||
grid.setAllRowsVisible(true);
|
grid.setAllRowsVisible(true);
|
||||||
|
|
||||||
getCurrentPageLayout().add(hl, grid);
|
getCurrentPageLayout().add(hl, grid);
|
@ -20,7 +20,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
@PageTitle("Assessments")
|
@PageTitle("Questions")
|
||||||
@Route(value = "/questions", layout = MainLayout.class)
|
@Route(value = "/questions", layout = MainLayout.class)
|
||||||
@PermitAll
|
@PermitAll
|
||||||
public class QuestionView extends BaseEntityForm<Question> implements HasUrlParameter<String> {
|
public class QuestionView extends BaseEntityForm<Question> implements HasUrlParameter<String> {
|
||||||
|
@ -3,10 +3,10 @@ insert into candidate (id, version, email) values ('23471ab3-f639-4d2b-9541-7227
|
|||||||
insert into question (id, version, content, title, description) values ('a7e00ff8-da41-4624-b31c-1b13c3f2e3ae', 1, 'foo bar', 'q1', 'lorem ipsum');
|
insert into question (id, version, content, title, description) values ('a7e00ff8-da41-4624-b31c-1b13c3f2e3ae', 1, 'foo bar', 'q1', 'lorem ipsum');
|
||||||
insert into question (id, version, content, title, description) values ('8a4b213c-ca81-4c38-b56d-d7028c2dde88', 1, 'foo buzz', 'q2', 'lorem ipsum');
|
insert into question (id, version, content, title, description) values ('8a4b213c-ca81-4c38-b56d-d7028c2dde88', 1, 'foo buzz', 'q2', 'lorem ipsum');
|
||||||
|
|
||||||
insert into assessment (id, version, candidate_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 1, '23471ab3-f639-4d2b-9541-7227f4ea7ee6');
|
insert into exam (id, version, candidate_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 1, '23471ab3-f639-4d2b-9541-7227f4ea7ee6');
|
||||||
|
|
||||||
insert into assessment_questions (assessment_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 'a7e00ff8-da41-4624-b31c-1b13c3f2e3ae');
|
insert into exam_questions (exam_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', 'a7e00ff8-da41-4624-b31c-1b13c3f2e3ae');
|
||||||
insert into assessment_questions (assessment_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', '8a4b213c-ca81-4c38-b56d-d7028c2dde88');
|
insert into exam_questions (exam_id, question_id) values ('46b153f4-23fd-462f-8430-fbe67b83caab', '8a4b213c-ca81-4c38-b56d-d7028c2dde88');
|
||||||
|
|
||||||
insert into team (id, version, name) values ('b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 1, 'ABC');
|
insert into team (id, version, name) values ('b0e8f394-78c1-4d8a-9c57-dc6e8b36a5fa', 1, 'ABC');
|
||||||
insert into team (id, version, name) values ('6d63bc15-3f8b-46f7-9cf1-7e9b0b9a2b28', 1, 'XYZ');
|
insert into team (id, version, name) values ('6d63bc15-3f8b-46f7-9cf1-7e9b0b9a2b28', 1, 'XYZ');
|
||||||
|
@ -2,7 +2,7 @@ package com.primefactorsolutions;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.*;
|
||||||
|
|
||||||
public class TestClass {
|
public class TestClass {
|
||||||
|
|
||||||
@ -12,9 +12,9 @@ public class TestClass {
|
|||||||
return "TODO";
|
return "TODO";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------- NO MODIFICAR DESDE ESTA LINEA --------------------
|
// ------------- NO MODIFICAR DESDE ESTA LINEA --------------------
|
||||||
|
|
||||||
|
// PRUEBAS UNITARIAS
|
||||||
public static class Tests {
|
public static class Tests {
|
||||||
public static Map.Entry<String, Boolean> testNInvalido() {
|
public static Map.Entry<String, Boolean> testNInvalido() {
|
||||||
boolean result = getFooBar(-1).equals("");
|
boolean result = getFooBar(-1).equals("");
|
||||||
|
@ -2,48 +2,48 @@ package com.primefactorsolutions;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.*;
|
||||||
|
|
||||||
public class TestClass {
|
public class TestClass {
|
||||||
|
|
||||||
// ------------ IMPLEMENTAR AQUI --------------------------------
|
// ------------ IMPLEMENTAR AQUI --------------------------------
|
||||||
|
|
||||||
public static String getPalindroma(String s) {
|
public static String getPalindromo(String s) {
|
||||||
return "TODO";
|
return "TODO";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------- NO MODIFICAR DESDE ESTA LINEA --------------------
|
// ------------- NO MODIFICAR DESDE ESTA LINEA --------------------
|
||||||
|
|
||||||
|
// PRUEBAS UNITARIAS
|
||||||
public static class Tests {
|
public static class Tests {
|
||||||
public static Map.Entry<String, Boolean> testPalindromaValido() {
|
public static Map.Entry<String, Boolean> testPalindromoValido() {
|
||||||
boolean result = getPalindroma("Ab").equals("ABBA");
|
boolean result = getPalindromo("Ab").equals("ABBA");
|
||||||
|
|
||||||
return Map.entry("palindrome es valido", result);
|
return Map.entry("palindromo es valido", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map.Entry<String, Boolean> testPalindromaVacio() {
|
public static Map.Entry<String, Boolean> testPalindromoVacio() {
|
||||||
boolean result = getPalindroma("").equals("");
|
boolean result = getPalindromo("").equals("");
|
||||||
|
|
||||||
return Map.entry("palindrome vacio es valido", result);
|
return Map.entry("palindromo vacio es valido", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map.Entry<String, Boolean> testPalindromaUnico() {
|
public static Map.Entry<String, Boolean> testPalindromoUnico() {
|
||||||
boolean result = getPalindroma("z").equals("Z");
|
boolean result = getPalindromo("z").equals("Z");
|
||||||
|
|
||||||
return Map.entry("palindrome un solo caracter es valido", result);
|
return Map.entry("palindromo un solo caracter es valido", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map.Entry<String, Boolean> testPalindromaUnico() {
|
public static Map.Entry<String, Boolean> testPalindromoEntrada() {
|
||||||
boolean result = getPalindroma("abba").equals("ABBA");
|
boolean result = getPalindromo("abba").equals("ABBA");
|
||||||
|
|
||||||
return Map.entry("palindrome un solo caracter es valido", result);
|
return Map.entry("palindromo en entrada es valido", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map.Entry<String, Boolean> testPalindromaNull() {
|
public static Map.Entry<String, Boolean> testPalindromoNull() {
|
||||||
boolean result = getPalindroma(null) == null;
|
boolean result = getPalindromo(null) == null;
|
||||||
|
|
||||||
return Map.entry("palindrome null es valido", result);
|
return Map.entry("palindromo null es valido", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
package com.primefactorsolutions.service;
|
|
||||||
|
|
||||||
import com.primefactorsolutions.model.Assessment;
|
|
||||||
import com.primefactorsolutions.model.AssessmentEvent;
|
|
||||||
import com.primefactorsolutions.model.AssessmentStatus;
|
|
||||||
import com.primefactorsolutions.repositories.AssessmentRepository;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import org.assertj.core.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.mockito.InjectMocks;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
|
||||||
public class AssessmentServiceTests {
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private AssessmentRepository assessmentRepository;
|
|
||||||
@Mock
|
|
||||||
private EntityManager entityManager;
|
|
||||||
@Mock
|
|
||||||
private JavaMailSender emailSender;
|
|
||||||
@InjectMocks
|
|
||||||
private AssessmentService assessmentService;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAlreadyStartedAssessment() {
|
|
||||||
final var aid = UUID.randomUUID();
|
|
||||||
final var assessment = new Assessment();
|
|
||||||
assessment.setId(aid);
|
|
||||||
assessment.setAssessmentEvents(List.of(new AssessmentEvent(Instant.now(), AssessmentStatus.STARTED)));
|
|
||||||
|
|
||||||
when(assessmentRepository.findById(eq(aid)))
|
|
||||||
.thenReturn(Optional.of(assessment));
|
|
||||||
|
|
||||||
final var started = assessmentService.startAssessment(aid);
|
|
||||||
|
|
||||||
Assertions.assertThat(assessment).isEqualTo(started);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.primefactorsolutions.service;
|
||||||
|
|
||||||
|
import com.primefactorsolutions.model.Exam;
|
||||||
|
import com.primefactorsolutions.model.ExamEvent;
|
||||||
|
import com.primefactorsolutions.model.ExamStatus;
|
||||||
|
import com.primefactorsolutions.repositories.ExamRepository;
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import org.assertj.core.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
public class ExamServiceTests {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ExamRepository examRepository;
|
||||||
|
@Mock
|
||||||
|
private EntityManager entityManager;
|
||||||
|
@Mock
|
||||||
|
private JavaMailSender emailSender;
|
||||||
|
@InjectMocks
|
||||||
|
private ExamService examService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAlreadyStartedExam() {
|
||||||
|
final var aid = UUID.randomUUID();
|
||||||
|
final var exam = new Exam();
|
||||||
|
exam.setId(aid);
|
||||||
|
exam.setExamEvents(List.of(new ExamEvent(Instant.now(), ExamStatus.STARTED)));
|
||||||
|
|
||||||
|
when(examRepository.findById(eq(aid)))
|
||||||
|
.thenReturn(Optional.of(exam));
|
||||||
|
|
||||||
|
final var started = examService.startExam(aid);
|
||||||
|
|
||||||
|
Assertions.assertThat(exam).isEqualTo(started);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user