Compare commits
8 Commits
main
...
Rama-Ricar
Author | SHA1 | Date | |
---|---|---|---|
49dc6421f5 | |||
dd95b70c66 | |||
7d6955a5c3 | |||
4eebdf6f01 | |||
59c7b2af85 | |||
a393c82649 | |||
aa041b3358 | |||
93e42baa52 |
@ -1,14 +0,0 @@
|
||||
name: PR Builder
|
||||
run-name: ${{ gitea.actor }} building PR
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
Build-PR:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event on branch ${{ gitea.head_ref }} and ref is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
||||
- name: Build PR
|
||||
if: gitea.base_ref == 'main'
|
||||
run: |
|
||||
git clone --single-branch --branch "${{ gitea.head_ref }}" https://git.primefactorsolutions.com/PFS/pfs-intra.git && cd pfs-intra && ./mvnw clean package -Pproduction
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
@ -1,16 +0,0 @@
|
||||
name: Builder
|
||||
run-name: ${{ gitea.actor }} building
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
Build-Project:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event on branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
||||
- name: Build package
|
||||
run: |
|
||||
git clone --single-branch --branch main https://git.primefactorsolutions.com/PFS/pfs-intra.git && cd pfs-intra && ./mvnw clean package -Pproduction && unlink /home/ubuntu/pfs-intra/app.jar && cp target/*.jar /home/ubuntu/pfs-intra/app.jar && sudo systemctl restart pfs-intra
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,4 +19,3 @@ drivers/
|
||||
# Error screenshots generated by TestBench for failed integration tests
|
||||
error-screenshots/
|
||||
webpack.generated.js
|
||||
*.env
|
||||
|
Binary file not shown.
2492
package-lock.json
generated
2492
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
50
package.json
50
package.json
@ -5,23 +5,21 @@
|
||||
"dependencies": {
|
||||
"@f0rce/ace-widget": "1.0.2",
|
||||
"@polymer/polymer": "3.5.1",
|
||||
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
||||
"@vaadin/bundles": "24.5.1",
|
||||
"@vaadin/bundles": "24.4.2",
|
||||
"@vaadin/common-frontend": "0.0.19",
|
||||
"@vaadin/polymer-legacy-adapter": "24.5.1",
|
||||
"@vaadin/react-components": "24.5.1",
|
||||
"@vaadin/react-components-pro": "24.5.1",
|
||||
"@vaadin/router": "2.0.0",
|
||||
"@vaadin/polymer-legacy-adapter": "24.4.2",
|
||||
"@vaadin/react-components": "24.4.2",
|
||||
"@vaadin/react-components-pro": "24.4.2",
|
||||
"@vaadin/router": "1.7.5",
|
||||
"@vaadin/vaadin-development-mode-detector": "2.0.7",
|
||||
"@vaadin/vaadin-lumo-styles": "24.5.1",
|
||||
"@vaadin/vaadin-material-styles": "24.5.1",
|
||||
"@vaadin/vaadin-themable-mixin": "24.5.1",
|
||||
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
||||
"@vaadin/vaadin-lumo-styles": "24.4.2",
|
||||
"@vaadin/vaadin-material-styles": "24.4.2",
|
||||
"@vaadin/vaadin-themable-mixin": "24.4.2",
|
||||
"@vaadin/vaadin-usage-statistics": "2.1.2",
|
||||
"construct-style-sheets-polyfill": "3.1.0",
|
||||
"date-fns": "2.29.3",
|
||||
"lit": "3.1.4",
|
||||
"print-js": "1.6.0",
|
||||
"proj4": "2.12.1",
|
||||
"proj4": "2.11.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-router-dom": "6.23.1"
|
||||
@ -50,23 +48,21 @@
|
||||
"dependencies": {
|
||||
"@f0rce/ace-widget": "1.0.2",
|
||||
"@polymer/polymer": "3.5.1",
|
||||
"@vaadin-component-factory/vcf-pdf-viewer": "2.0.1",
|
||||
"@vaadin/bundles": "24.5.1",
|
||||
"@vaadin/bundles": "24.4.2",
|
||||
"@vaadin/common-frontend": "0.0.19",
|
||||
"@vaadin/polymer-legacy-adapter": "24.5.1",
|
||||
"@vaadin/react-components": "24.5.1",
|
||||
"@vaadin/react-components-pro": "24.5.1",
|
||||
"@vaadin/router": "2.0.0",
|
||||
"@vaadin/polymer-legacy-adapter": "24.4.2",
|
||||
"@vaadin/react-components": "24.4.2",
|
||||
"@vaadin/react-components-pro": "24.4.2",
|
||||
"@vaadin/router": "1.7.5",
|
||||
"@vaadin/vaadin-development-mode-detector": "2.0.7",
|
||||
"@vaadin/vaadin-lumo-styles": "24.5.1",
|
||||
"@vaadin/vaadin-material-styles": "24.5.1",
|
||||
"@vaadin/vaadin-themable-mixin": "24.5.1",
|
||||
"@vaadin/vaadin-usage-statistics": "2.1.3",
|
||||
"@vaadin/vaadin-lumo-styles": "24.4.2",
|
||||
"@vaadin/vaadin-material-styles": "24.4.2",
|
||||
"@vaadin/vaadin-themable-mixin": "24.4.2",
|
||||
"@vaadin/vaadin-usage-statistics": "2.1.2",
|
||||
"construct-style-sheets-polyfill": "3.1.0",
|
||||
"date-fns": "2.29.3",
|
||||
"lit": "3.1.4",
|
||||
"print-js": "1.6.0",
|
||||
"proj4": "2.12.1",
|
||||
"proj4": "2.11.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-router-dom": "6.23.1"
|
||||
@ -91,7 +87,7 @@
|
||||
"workbox-core": "7.1.0",
|
||||
"workbox-precaching": "7.1.0"
|
||||
},
|
||||
"hash": "1a0f17d48b329307b5862bc57499307d1b89f7d89260121c2b7189f76957c436"
|
||||
"hash": "ff8035f5a0dd319a5c705d9cea5b3e1d6c1a0bb871c35af8dd8e4ede5c65fe76"
|
||||
},
|
||||
"overrides": {
|
||||
"@vaadin/bundles": "$@vaadin/bundles",
|
||||
@ -113,8 +109,6 @@
|
||||
"@vaadin/vaadin-themable-mixin": "$@vaadin/vaadin-themable-mixin",
|
||||
"@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles",
|
||||
"@vaadin/vaadin-material-styles": "$@vaadin/vaadin-material-styles",
|
||||
"@f0rce/ace-widget": "$@f0rce/ace-widget",
|
||||
"print-js": "$print-js",
|
||||
"@vaadin-component-factory/vcf-pdf-viewer": "$@vaadin-component-factory/vcf-pdf-viewer"
|
||||
"@f0rce/ace-widget": "$@f0rce/ace-widget"
|
||||
}
|
||||
}
|
||||
|
83
pom.xml
83
pom.xml
@ -11,8 +11,7 @@
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<vaadin.version>24.5.1</vaadin.version>
|
||||
<vaadin-maven-plugin.version>24.4.6</vaadin-maven-plugin.version>
|
||||
<vaadin.version>24.4.6</vaadin.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
@ -101,10 +100,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-ldap</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
@ -120,15 +115,6 @@
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.17.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
@ -191,21 +177,6 @@
|
||||
<artifactId>viritin</artifactId>
|
||||
<version>2.8.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.overcoded</groupId>
|
||||
<artifactId>panel-for-vaadin</artifactId>
|
||||
<version>24.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml-schemas</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.flowingcode.addons</groupId>
|
||||
<artifactId>simple-timer</artifactId>
|
||||
@ -250,64 +221,16 @@
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.14.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.vaadin.addons.componentfactory</groupId>
|
||||
<artifactId>vcf-pdf-viewer</artifactId>
|
||||
<version>2.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.openhtmltopdf</groupId>
|
||||
<artifactId>openhtmltopdf-pdfbox</artifactId>
|
||||
<version>1.0.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.32</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>4.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.git-commit-id</groupId>
|
||||
<artifactId>git-commit-id-maven-plugin</artifactId>
|
||||
<version>9.0.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>spring-boot:run</defaultGoal>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.github.git-commit-id</groupId>
|
||||
<artifactId>git-commit-id-maven-plugin</artifactId>
|
||||
<version>9.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>get-the-git-infos</id>
|
||||
<goals>
|
||||
<goal>revision</goal>
|
||||
</goals>
|
||||
<phase>initialize</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<generateGitPropertiesFile>true</generateGitPropertiesFile>
|
||||
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
|
||||
<includeOnlyProperties>
|
||||
<includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
|
||||
<includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
|
||||
</includeOnlyProperties>
|
||||
<commitIdGenerationMode>full</commitIdGenerationMode>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
@ -337,7 +260,7 @@
|
||||
<plugin>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-maven-plugin</artifactId>
|
||||
<version>${vaadin-maven-plugin.version}</version>
|
||||
<version>${vaadin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
@ -398,7 +321,7 @@
|
||||
<plugin>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-maven-plugin</artifactId>
|
||||
<version>${vaadin-maven-plugin.version}</version>
|
||||
<version>${vaadin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
Binary file not shown.
Binary file not shown.
@ -4,6 +4,7 @@ import com.vaadin.flow.component.page.AppShellConfigurator;
|
||||
import com.vaadin.flow.theme.Theme;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* The entry point of the Spring Boot application.
|
||||
*
|
||||
|
@ -1,19 +0,0 @@
|
||||
package com.primefactorsolutions.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
@Configuration
|
||||
public class PropertiesConfig {
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
|
||||
final PropertySourcesPlaceholderConfigurer propsConfig = new PropertySourcesPlaceholderConfigurer();
|
||||
propsConfig.setLocation(new ClassPathResource("git.properties"));
|
||||
propsConfig.setIgnoreResourceNotFound(true);
|
||||
propsConfig.setIgnoreUnresolvablePlaceholders(true);
|
||||
|
||||
return propsConfig;
|
||||
}
|
||||
}
|
@ -1,32 +1,20 @@
|
||||
package com.primefactorsolutions.config;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.primefactorsolutions.views.LoginView;
|
||||
import com.vaadin.flow.spring.security.VaadinWebSecurity;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.ldap.LdapBindAuthenticationManagerFactory;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
|
||||
import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
|
||||
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
public class SecurityConfig extends VaadinWebSecurity {
|
||||
@Value("${spring.ldap.url}")
|
||||
private String ldapUrl;
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
@ -49,28 +37,13 @@ public class SecurityConfig extends VaadinWebSecurity {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(final UserDetailsContextMapper userDetailsContextMapper) {
|
||||
final DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
|
||||
String.format("%s/dc=primefactorsolutions,dc=com", ldapUrl));
|
||||
public AuthenticationManager authenticationManager() {
|
||||
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
|
||||
"ldap://localhost:8389/dc=primefactorsolutions,dc=com");
|
||||
contextSource.setCacheEnvironmentProperties(false);
|
||||
final LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=users");
|
||||
factory.setUserDetailsContextMapper(userDetailsContextMapper);
|
||||
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UserDetailsContextMapper userDetailsContextMapper(final EmployeeService employeeService) {
|
||||
return new LdapUserDetailsMapper() {
|
||||
@Override
|
||||
public UserDetails mapUserFromContext(final DirContextOperations ctx, final String username,
|
||||
final Collection<? extends GrantedAuthority> authorities) {
|
||||
final UserDetails details = super.mapUserFromContext(ctx, username, authorities);
|
||||
final Employee employee = employeeService.getDetachedEmployeeByUsername(details.getUsername());
|
||||
|
||||
return employee == null ? details : employee;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -15,33 +15,30 @@ import java.util.Optional;
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Exam extends BaseEntity {
|
||||
public class Assessment extends BaseEntity {
|
||||
@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
|
||||
@JoinTable(name = "EXAM_QUESTIONS", joinColumns = @JoinColumn(name = "exam_id"),
|
||||
@JoinTable(name = "ASSESSMENT_QUESTIONS", joinColumns = @JoinColumn(name = "assessment_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "question_id"))
|
||||
private List<Question> questions = new ArrayList<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "exam", cascade = {CascadeType.ALL})
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "assessment", cascade = {CascadeType.ALL})
|
||||
private List<Submission> submissions = new ArrayList<>();
|
||||
|
||||
@ManyToOne
|
||||
private Candidate candidate;
|
||||
|
||||
@ManyToOne
|
||||
private Evaluation evaluation;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
|
||||
@JoinColumn(name = "EXAM_ID")
|
||||
private List<ExamEvent> examEvents = new ArrayList<>();
|
||||
@JoinColumn(name = "ASSESSMENT_ID")
|
||||
private List<AssessmentEvent> assessmentEvents = new ArrayList<>();
|
||||
|
||||
public Submission getCurrentSubmission() {
|
||||
return submissions.getLast();
|
||||
}
|
||||
|
||||
public Long getRemainingTimeSeconds() {
|
||||
final Optional<Instant> started = examEvents.stream()
|
||||
.filter(e -> e.getStatus() == ExamStatus.STARTED)
|
||||
.map(ExamEvent::getTimestamp)
|
||||
final Optional<Instant> started = assessmentEvents.stream()
|
||||
.filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
||||
.map(AssessmentEvent::getTimestamp)
|
||||
.findFirst();
|
||||
|
||||
final Integer totalTimeMinutes = questions.stream()
|
||||
@ -55,24 +52,24 @@ public class Exam extends BaseEntity {
|
||||
}
|
||||
|
||||
public Instant getStartingTime() {
|
||||
final Optional<Instant> started = examEvents.stream()
|
||||
.filter(e -> e.getStatus() == ExamStatus.STARTED)
|
||||
.map(ExamEvent::getTimestamp)
|
||||
final Optional<Instant> started = assessmentEvents.stream()
|
||||
.filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
||||
.map(AssessmentEvent::getTimestamp)
|
||||
.findFirst();
|
||||
|
||||
return started.orElse(null);
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return examEvents.stream().filter(e -> e.getStatus() == ExamStatus.COMPLETED)
|
||||
.map(ExamEvent::getTimestamp)
|
||||
return assessmentEvents.stream().filter(e -> e.getStatus() == AssessmentStatus.COMPLETED)
|
||||
.map(AssessmentEvent::getTimestamp)
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return examEvents.stream().filter(e -> e.getStatus() == ExamStatus.STARTED)
|
||||
.map(ExamEvent::getTimestamp)
|
||||
return assessmentEvents.stream().filter(e -> e.getStatus() == AssessmentStatus.STARTED)
|
||||
.map(AssessmentEvent::getTimestamp)
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
}
|
@ -13,7 +13,7 @@ import java.time.Instant;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ExamEvent extends BaseEntity {
|
||||
public class AssessmentEvent extends BaseEntity {
|
||||
private Instant timestamp;
|
||||
private ExamStatus status;
|
||||
private AssessmentStatus status;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public enum ExamStatus {
|
||||
public enum AssessmentStatus {
|
||||
CREATED,
|
||||
STARTED,
|
||||
COMPLETED
|
@ -1,11 +1,11 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import jakarta.persistence.Version;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
@MappedSuperclass
|
||||
@ -13,18 +13,22 @@ public abstract class BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@Getter
|
||||
@Setter
|
||||
private UUID id;
|
||||
|
||||
@Version
|
||||
@Getter
|
||||
private int version;
|
||||
@Getter
|
||||
@ColumnDefault("NOW()")
|
||||
private Instant created;
|
||||
@ColumnDefault("NOW()")
|
||||
@Getter
|
||||
private Instant updated;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
@ -44,14 +48,4 @@ public abstract class BaseEntity {
|
||||
}
|
||||
return super.equals(that);
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
public void updateCreated() {
|
||||
this.created = Instant.now();
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
public void updateUpdated() {
|
||||
this.updated = Instant.now();
|
||||
}
|
||||
}
|
||||
|
@ -6,17 +6,17 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Candidate extends BaseEntity implements HasLabel {
|
||||
public class Candidate extends BaseEntity {
|
||||
@Column(unique = true)
|
||||
private String email;
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return email;
|
||||
}
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "candidate")
|
||||
private List<Assessment> assessments;
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public record Certification(String title, Integer year) {
|
||||
}
|
@ -1,23 +1,23 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Document extends BaseEntity {
|
||||
private String fileName;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Nullable
|
||||
private String description;
|
||||
private String location;
|
||||
private DocumentType documentType;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "employee_id", nullable = false)
|
||||
private Employee employee;
|
||||
@Lob
|
||||
@Column(columnDefinition = "BLOB")
|
||||
private byte[] fileData;
|
||||
private String creator;
|
||||
}
|
||||
|
@ -1,34 +1,7 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public enum DocumentType {
|
||||
CARNET_DE_IDENTIDAD,
|
||||
RECIBOS_DE_PAGO,
|
||||
CONTRATO_DE_TRABAJO,
|
||||
CERTIFICADO_DE_TRABAJO,
|
||||
NDA,
|
||||
MEMORÁNDUMS,
|
||||
APROBACIÓN_DE_CONTRATO_MTEPS,
|
||||
CERTIFICADO_DE_ANTECEDENTES,
|
||||
EVALUACIÓN_PRE_EMPLEO,
|
||||
FORMULARIO_DE_INSCRIPCIÓN_AL_SEGURO,
|
||||
FORMULARIO_DE_CANCELACIÓN_DE_SEGURO,
|
||||
TÍTULO_PROFESIONAL_1,
|
||||
CERTIFICACIÓN_PROFESIONAL_1,
|
||||
TÍTULO_PROFESIONAL_2,
|
||||
CERTIFICACIÓN_PROFECIONAL_2,
|
||||
TÍTULO_PROFESIONAL_3,
|
||||
CERTIFICACIÓN_PROFECIONAL_3,
|
||||
NORMATIVA_LABORAL_GENERAL,
|
||||
NORMAS_DE_TRABAJO_REMOTO,
|
||||
NORMAS_DE_SEGURIDAD,
|
||||
INSTRUCTIVOS_DE_RECURSOS_HUMANOS,
|
||||
MANUAL_DE_FUNCIONES_DE_ADMINISTRACIÓN,
|
||||
MANUAL_DE_FUNCIONES_DE_INGENIERÍA,
|
||||
LEY_GENERAL_DEL_TRABAJO,
|
||||
DECRETOS_SUPREMOS,
|
||||
RESOLUCIONES_O_DISPOSICIONES_REGLAMENTARIAS,
|
||||
NORMATIVA_COMPLEMENTARIA,
|
||||
LEY_GRAL_DE_HIGIENE_SALUD_SEGURIDAD_OCUPACIONAL_Y_BIENESTAR,
|
||||
NORMATIVA_REGLAMENTARIA_PARA_DESARROLLO_DE_PASANTÍAS,
|
||||
OTROS
|
||||
ID_CARD,
|
||||
PAY_STUB,
|
||||
OTHER
|
||||
}
|
||||
|
@ -1,193 +1,47 @@
|
||||
package com.primefactorsolutions.model;
|
||||
package com.primefactorsolutions.model;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.hypersistence.utils.hibernate.type.json.JsonType;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Employee extends BaseEntity implements UserDetails, HasLabel {
|
||||
|
||||
private String username;
|
||||
@NotNull(message = "El nombre no puede estar vacío")
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre solo debe contener letras")
|
||||
private String firstName;
|
||||
@NotNull(message = "El apellido no puede estar vacío")
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El apellido solo debe contener letras")
|
||||
private String lastName;
|
||||
@MinAge(18)
|
||||
private LocalDate birthday;
|
||||
@Pattern(regexp = "^[a-zA-Z ,]+$", message = "La ciudad de nacimiento solo debe contener letras, espacios o comas")
|
||||
private String birthCity;
|
||||
private String age;
|
||||
@Size(max = 50, message = "La dirección de residencia no debe exceder 50 caracteres")
|
||||
private String residenceAddress;
|
||||
@Size(max = 30, message = "La dirección local no debe exceder 100 caracteres")
|
||||
@Pattern(regexp = "^[a-zA-Z -]+$", message = "La dirección local solo debe contener letras y guion")
|
||||
private String localAddress;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "El número de teléfono debe contener solo números")
|
||||
private String phoneNumber;
|
||||
@Email(message = "El correo personal no tiene un formato válido")
|
||||
private String personalEmail;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "El número de teléfono debe contener solo números")
|
||||
private String phoneNumberProfessional;
|
||||
@Email(message = "El correo profesional no tiene un formato válido")
|
||||
private String professionalEmail;
|
||||
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El cargo solo debe contener letras")
|
||||
private String position;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "team_id", nullable = false)
|
||||
private Team team;
|
||||
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre y apellido de contacto"
|
||||
+ " de emergencia solo debe contener letras")
|
||||
private String emergencyCName;
|
||||
private String emergencyCAddress;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "El teléfono de contacto de emergencia "
|
||||
+ " debe contener solo números")
|
||||
private String emergencyCPhone;
|
||||
@Email(message = "El correo de contacto de emergencia no tiene un formato válido")
|
||||
private String emergencyCEmail;
|
||||
private String numberOfChildren;
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]+$", message = "El CI debe contener solo letras y números")
|
||||
private String ci;
|
||||
private String issuedIn;
|
||||
|
||||
@Type(JsonType.class)
|
||||
@Column(columnDefinition = "json")
|
||||
@ColumnDefault("JSON_ARRAY()")
|
||||
private List<Certification> educationTitles = Lists.newArrayList();
|
||||
@Type(JsonType.class)
|
||||
@Column(columnDefinition = "json")
|
||||
@ColumnDefault("JSON_ARRAY()")
|
||||
private List<Certification> certifications = Lists.newArrayList();
|
||||
private String recognition;
|
||||
private String achievements;
|
||||
@Type(JsonType.class)
|
||||
@Column(columnDefinition = "json")
|
||||
@ColumnDefault("JSON_ARRAY()")
|
||||
private List<Language> languages = Lists.newArrayList();
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "El código debe contener solo letras y números")
|
||||
private String cod;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El lead manager solo debe contener letras")
|
||||
private String leadManager;
|
||||
|
||||
private LocalDate dateOfEntry;
|
||||
private LocalDate dateOfExit;
|
||||
|
||||
private String seniority;
|
||||
private BigDecimal salaryTotal = BigDecimal.ZERO;
|
||||
private BigDecimal salaryBasic = BigDecimal.ZERO;
|
||||
private BigDecimal professionalBonus = BigDecimal.ZERO;
|
||||
private BigDecimal tenureBonus = BigDecimal.ZERO;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "El nombre del banco solo debe contener letras")
|
||||
private String bankName;
|
||||
@Pattern(regexp = "^[0-9]+$", message = "El número de cuenta debe contener solo números")
|
||||
private String accountNumber;
|
||||
@Setter
|
||||
private String customContractType;
|
||||
private String gpss;
|
||||
private String sss;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "Los derechohabientes solo deben contener letras")
|
||||
private String beneficiarie1;
|
||||
@Pattern(regexp = "^[a-zA-Z ]+$", message = "Los derechohabientes solo deben contener letras")
|
||||
private String beneficiarie2;
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String profileImage;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Status status;
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return Lists.newArrayList(new SimpleGrantedAuthority("ROLE_" + this.role.name()));
|
||||
@Data
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Employee extends BaseEntity {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private LocalDate birthday;
|
||||
private String birthCity;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private MaritalStatus maritalStatus;
|
||||
private String residenceAddress;
|
||||
private String phoneNumber;
|
||||
private String personalEmail;
|
||||
private String emergencyCName;
|
||||
private String emergencyCAddress;
|
||||
private String emergencyCPhone;
|
||||
private String emergencyCEmail;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Status status;
|
||||
public enum Status {
|
||||
ACTIVE,
|
||||
INACTIVE
|
||||
}
|
||||
public enum MaritalStatus {
|
||||
SINGLE,
|
||||
MARRIED,
|
||||
WIDOWED,
|
||||
DIVORCED
|
||||
}
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
public void setStatus(final Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private MaritalStatus maritalStatus;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Gender gender;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private ContractType contractType;
|
||||
@Size(max = 255, message = "El detalle del contrato no debe exceder 255 caracteres")
|
||||
private String otherContractDetail;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Role role = Role.USER;
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return String.format("%s %s", firstName, lastName);
|
||||
}
|
||||
|
||||
public enum Status {
|
||||
ACTIVE,
|
||||
INACTIVE
|
||||
}
|
||||
|
||||
public enum Gender {
|
||||
MALE,
|
||||
FEMALE
|
||||
}
|
||||
|
||||
public enum MaritalStatus {
|
||||
SINGLE,
|
||||
MARRIED,
|
||||
WIDOWED,
|
||||
DIVORCED
|
||||
}
|
||||
|
||||
public enum ContractType {
|
||||
CONTRATO_LABORAL,
|
||||
CONTRATO_CIVIL_O_SERVICIOS,
|
||||
CONTRATO_PLAZO_FIJO,
|
||||
CONSULTORIA_INTERNA,
|
||||
CONSULTORIA_EXTERNA,
|
||||
CONTRATO_MIXTO,
|
||||
OTROS
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public enum EmployeePosition {
|
||||
JUNIOR_DEV,
|
||||
JUNIOR_QA,
|
||||
SENIOR_DEV,
|
||||
SENIOR_QA
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
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 Integer points;
|
||||
private EmployeePosition candidatePosition;
|
||||
private Employee interviewer;
|
||||
@Type(JsonType.class)
|
||||
@Column(columnDefinition = "json")
|
||||
@ColumnDefault("JSON_ARRAY()")
|
||||
private List<SkillEvaluation> skillEvaluations = Lists.newArrayList();
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "evaluation")
|
||||
private List<Exam> exams;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public interface HasLabel {
|
||||
String getLabel();
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public record Language(String name, Proficiency proficiency) {
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Constraint(validatedBy = MinAgeValidator.class)
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MinAge {
|
||||
String message() default "El empleado debe ser mayor de {value} años";
|
||||
Class<?>[] groups() default {};
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
int value();
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
public class MinAgeValidator implements ConstraintValidator<MinAge, LocalDate> {
|
||||
private int minAge;
|
||||
|
||||
@Override
|
||||
public void initialize(final MinAge constraintAnnotation) {
|
||||
this.minAge = constraintAnnotation.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(final LocalDate birthday, final ConstraintValidatorContext context) {
|
||||
if (birthday == null) {
|
||||
return true;
|
||||
}
|
||||
return ChronoUnit.YEARS.between(birthday, LocalDate.now()) >= minAge;
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public enum Proficiency {
|
||||
BASIC,
|
||||
ADVANCED,
|
||||
FLUENT
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public record SkillEvaluation(SkillType skillType, SkillLevel level, String comments) {
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public enum SkillLevel {
|
||||
NEEDS_IMPROVEMENT,
|
||||
FAIR,
|
||||
VERY_GOOD,
|
||||
EXCELLENT
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public enum SkillType {
|
||||
TECHNICAL_KNOWLEDGE,
|
||||
ASSERTIVENESS,
|
||||
COMPLETENESS_AND_CONCISENESS,
|
||||
COMMUNICATION
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import io.hypersistence.utils.hibernate.type.json.JsonType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
@ -7,6 +9,9 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@ -18,12 +23,14 @@ public class Submission extends BaseEntity {
|
||||
private Question question;
|
||||
|
||||
@Lob
|
||||
private String text;
|
||||
private String response;
|
||||
|
||||
private String output;
|
||||
@Type(JsonType.class)
|
||||
@Column(columnDefinition = "json")
|
||||
private Map<String, Object> results;
|
||||
|
||||
private SubmissionStatus submissionStatus;
|
||||
|
||||
@ManyToOne
|
||||
private Exam exam;
|
||||
private Assessment assessment;
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Team extends BaseEntity {
|
||||
private String name;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TimeOff extends BaseEntity {
|
||||
@Enumerated(EnumType.STRING)
|
||||
private TimeOffRequestType category;
|
||||
private LocalDate date;
|
||||
private Double duration;
|
||||
private Double expiration;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Type type;
|
||||
|
||||
public enum Type {
|
||||
FIXED,
|
||||
MOVABLE,
|
||||
OTHER
|
||||
}
|
||||
}
|
@ -1,30 +1,21 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TimeOffRequest extends BaseEntity {
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "employee_id", nullable = false)
|
||||
private Employee employee;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private TimeOffRequestType category;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private TimeOffRequestStatus state;
|
||||
private Double availableDays;
|
||||
private LocalDate expiration;
|
||||
private LocalDate startDate;
|
||||
private LocalDate endDate;
|
||||
private Double daysToBeTake;
|
||||
private Double daysBalance;
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "request", cascade = {CascadeType.ALL})
|
||||
private List<TimeOffRequestEntry> entries;
|
||||
private TimeOffRequestType type;
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public enum TimeOffRequestStatus {
|
||||
TODOS,
|
||||
TOMADO,
|
||||
APROBADO,
|
||||
EN_USO,
|
||||
PENDIENTE,
|
||||
RECHAZADO,
|
||||
VENCIDO,
|
||||
|
||||
SOLICITADO,
|
||||
}
|
@ -1,29 +1,7 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
public enum TimeOffRequestType {
|
||||
AÑO_NUEVO,
|
||||
LUNES_CARNAVAL,
|
||||
MARTES_CARNAVAL,
|
||||
VIERNES_SANTO,
|
||||
DIA_DEL_TRABAJADOR,
|
||||
DIA_DE_LA_INDEPENDENCIA,
|
||||
NAVIDAD,
|
||||
DIA_DEL_ESTADO_PLURINACIONAL,
|
||||
CORPUS_CHRISTI,
|
||||
AÑO_NUEVO_ANDINO,
|
||||
ANIVERSARIO_DEPARTAMENTAL,
|
||||
DIA_DE_TODOS_LOS_DIFUNTOS,
|
||||
CUMPLEAÑOS,
|
||||
MATERNIDAD,
|
||||
PATERNIDAD,
|
||||
MATRIMONIO,
|
||||
DUELO_1ER_GRADO,
|
||||
DUELO_2ER_GRADO,
|
||||
DIA_DEL_PADRE,
|
||||
DIA_DE_LA_MADRE,
|
||||
DIA_DE_LA_MUJER_INTERNACIONAL,
|
||||
DIA_DE_LA_MUJER_NACIONAL,
|
||||
PERMISOS_DE_SALUD,
|
||||
VACACION_GESTION_ACTUAL,
|
||||
VACACION_GESTION_ANTERIOR,
|
||||
VACATION,
|
||||
MATERNITY,
|
||||
OTHER
|
||||
}
|
||||
|
21
src/main/java/com/primefactorsolutions/model/Timesheet.java
Normal file
21
src/main/java/com/primefactorsolutions/model/Timesheet.java
Normal file
@ -0,0 +1,21 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import io.hypersistence.utils.hibernate.type.json.JsonType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Timesheet extends BaseEntity {
|
||||
@Type(JsonType.class)
|
||||
@Column(columnDefinition = "json")
|
||||
private List<TimesheetEntry> entries;
|
||||
}
|
@ -1,30 +1,13 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.IsoFields;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TimesheetEntry extends BaseEntity {
|
||||
|
||||
private String task;
|
||||
private String details;
|
||||
private LocalDate date;
|
||||
private double hours;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "employee_id")
|
||||
private Employee employee;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "team_id")
|
||||
private Team team;
|
||||
|
||||
public int getWeekNumber() {
|
||||
return date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
|
||||
}
|
||||
public class TimesheetEntry {
|
||||
private TaskType taskType;
|
||||
private int hours;
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
package com.primefactorsolutions.model;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.IsoFields;
|
||||
import java.time.temporal.WeekFields;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public record Week(LocalDate from, LocalDate to) {
|
||||
@Override
|
||||
public String toString() {
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE;
|
||||
return String.format("from %s to %s", formatter.format(from), formatter.format(to));
|
||||
}
|
||||
|
||||
public static Week getCurrent() {
|
||||
final int weekNumber = LocalDate.now().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
|
||||
final LocalDate from = getFirstDayOfWeek(weekNumber);
|
||||
|
||||
return new Week(from, from.plusDays(6));
|
||||
}
|
||||
|
||||
public static List<Week> getLastWeeks(final int numberOfWeeks) {
|
||||
final int weekNumber = LocalDate.now().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
|
||||
LocalDate from = getFirstDayOfWeek(weekNumber);
|
||||
final ArrayList<Week> result = Lists.newArrayList();
|
||||
|
||||
for (int i = 0; i < numberOfWeeks; i++) {
|
||||
result.add(new Week(from, from.plusDays(6)));
|
||||
from = from.minusDays(7);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static LocalDate getFirstDayOfWeek(final int weekNumber) {
|
||||
return LocalDate
|
||||
.now()
|
||||
.with(WeekFields.of(Locale.US).getFirstDayOfWeek())
|
||||
.with(WeekFields.of(Locale.US).weekOfWeekBasedYear(), weekNumber);
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package com.primefactorsolutions.repositories;
|
||||
|
||||
import com.primefactorsolutions.model.Exam;
|
||||
import com.primefactorsolutions.model.Assessment;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ExamRepository extends JpaRepository<Exam, UUID> {
|
||||
public interface AssessmentRepository extends JpaRepository<Assessment, UUID> {
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.primefactorsolutions.repositories;
|
||||
|
||||
import com.primefactorsolutions.model.Document;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface DocumentRepository extends JpaRepository<Document, UUID> {
|
||||
}
|
@ -3,14 +3,7 @@ package com.primefactorsolutions.repositories;
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface EmployeeRepository extends JpaRepository<Employee, UUID> {
|
||||
Optional<Employee> findByUsername(String username);
|
||||
Optional<Employee> findByPersonalEmail(String personalEmail);
|
||||
List<Employee> findAllByTeamId(UUID teamId);
|
||||
//Optional<Employee> findByTeamIdAndLeadManagerTrue(UUID teamId);
|
||||
List<Employee> findByTeamName(String teamName);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
package com.primefactorsolutions.repositories;
|
||||
|
||||
import com.primefactorsolutions.model.Evaluation;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface EvaluationRepository extends JpaRepository<Evaluation, UUID> {
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.primefactorsolutions.repositories;
|
||||
|
||||
import com.primefactorsolutions.model.Team;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface TeamRepository extends JpaRepository<Team, UUID> {
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package com.primefactorsolutions.repositories;
|
||||
|
||||
import com.primefactorsolutions.model.TimeOff;
|
||||
import com.primefactorsolutions.model.TimeOffRequestType;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface TimeOffRepository extends JpaRepository<TimeOff, UUID> {
|
||||
TimeOff findByCategory(TimeOffRequestType category);
|
||||
List<TimeOff> findByDateBetween(LocalDate from, LocalDate to);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package com.primefactorsolutions.repositories;
|
||||
|
||||
import com.primefactorsolutions.model.TimeOffRequest;
|
||||
import com.primefactorsolutions.model.TimeOffRequestStatus;
|
||||
import com.primefactorsolutions.model.TimeOffRequestType;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface TimeOffRequestRepository extends JpaRepository<TimeOffRequest, UUID> {
|
||||
List<TimeOffRequest> findByOrderByUpdatedDesc();
|
||||
List<TimeOffRequest> findByEmployeeId(UUID idEmployee);
|
||||
Optional<TimeOffRequest> findByEmployeeIdAndState(UUID employeeId, TimeOffRequestStatus state);
|
||||
List<TimeOffRequest> findByEmployeeIdAndCategory(UUID employeeId, TimeOffRequestType category);
|
||||
List<TimeOffRequest> findByState(TimeOffRequestStatus state);
|
||||
void deleteByEmployeeIdAndCategory(UUID employeeId, TimeOffRequestType category);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.primefactorsolutions.repositories;
|
||||
|
||||
import com.primefactorsolutions.model.TimesheetEntry;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface TimesheetEntryRepository extends JpaRepository<TimesheetEntry, UUID> {
|
||||
List<TimesheetEntry> findByDateBetween(LocalDate from, LocalDate to);
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTCreationException;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AccountService {
|
||||
private final EmailService emailService;
|
||||
private final EmployeeService employeeService;
|
||||
private final String secret;
|
||||
|
||||
public AccountService(final EmailService emailService, final EmployeeService employeeService,
|
||||
@Value("${application.jwtSecret}") final String secret) {
|
||||
this.emailService = emailService;
|
||||
this.employeeService = employeeService;
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public void sendResetPasswordEmail(final String personalEmail) {
|
||||
final Employee employee = employeeService.getEmployeeByPersonalEmail(personalEmail);
|
||||
|
||||
if (employee == null) {
|
||||
log.warn("Could not find employee for email {}", personalEmail);
|
||||
return;
|
||||
}
|
||||
|
||||
final String link = createResetPasswordLink(employee.getUsername());
|
||||
final String content = "Visit this link to reset your password: " + link;
|
||||
emailService.sendEmail(personalEmail, "PFS - Reset Password", content);
|
||||
}
|
||||
|
||||
public void resetPassword(final String username, final String newPassword, final String token) {
|
||||
DecodedJWT decodedJWT;
|
||||
|
||||
try {
|
||||
Algorithm algorithm = Algorithm.HMAC512(secret);
|
||||
JWTVerifier verifier = JWT.require(algorithm)
|
||||
.withIssuer("pfs")
|
||||
.build();
|
||||
|
||||
decodedJWT = verifier.verify(token);
|
||||
final Instant expiry = decodedJWT.getExpiresAtAsInstant();
|
||||
final String claim = decodedJWT.getClaim("username").asString();
|
||||
|
||||
if (expiry.isBefore(Instant.now())
|
||||
|| !username.equals(claim)) {
|
||||
log.warn("token invalid {} {} {}", username, claim, expiry);
|
||||
return;
|
||||
}
|
||||
} catch (JWTVerificationException e) {
|
||||
log.warn("error updating password", e);
|
||||
return;
|
||||
}
|
||||
|
||||
final Employee employee = employeeService.getDetachedEmployeeByUsername(username);
|
||||
|
||||
if (employee == null) {
|
||||
log.warn("Could not find employee for username {}", username);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(newPassword) || newPassword.length() < 8) {
|
||||
throw new IllegalArgumentException("New password should be at least 8 chars long");
|
||||
}
|
||||
|
||||
employeeService.updatePassword(employee, newPassword);
|
||||
|
||||
log.info("updated password for {}", username);
|
||||
}
|
||||
|
||||
private String createResetPasswordLink(final String username) {
|
||||
String token = "";
|
||||
|
||||
try {
|
||||
Algorithm algorithm = Algorithm.HMAC512(secret);
|
||||
token = JWT.create()
|
||||
.withIssuer("pfs")
|
||||
.withClaim("username", username)
|
||||
.withExpiresAt(Instant.now().plus(1, ChronoUnit.HOURS))
|
||||
.sign(algorithm);
|
||||
} catch (JWTCreationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return String.format("https://intra.primefactorsolutions.com/reset-password?username=%s&token=%s", username,
|
||||
token);
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.*;
|
||||
import com.primefactorsolutions.repositories.AssessmentRepository;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.transaction.Transactional;
|
||||
import lombok.Data;
|
||||
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
|
||||
@Data
|
||||
@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);
|
||||
}
|
||||
}
|
@ -2,19 +2,19 @@ package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.Candidate;
|
||||
import com.primefactorsolutions.repositories.CandidateRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class CandidateService {
|
||||
private final CandidateRepository candidateRepository;
|
||||
|
||||
public Candidate createOrUpdate(final Candidate candidate) {
|
||||
final Candidate saved = candidateRepository.save(candidate);
|
||||
public Candidate createOrUpdate(final Candidate assessment) {
|
||||
final Candidate saved = candidateRepository.save(assessment);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.Document;
|
||||
import com.primefactorsolutions.model.DocumentType;
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.repositories.DocumentRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.beanutils.BeanComparator;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class DocumentService {
|
||||
private final DocumentRepository documentRepository;
|
||||
|
||||
public void saveDocument(final Document newDocument) {
|
||||
documentRepository.save(newDocument);
|
||||
}
|
||||
|
||||
public void deleteDocument(final UUID id) {
|
||||
documentRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public List<Document> getAllDocuments() {
|
||||
return documentRepository.findAll();
|
||||
}
|
||||
|
||||
public Document getDocument(final UUID id) {
|
||||
Optional<Document> employee = documentRepository.findById(id);
|
||||
return employee.orElse(null);
|
||||
}
|
||||
|
||||
public List<Document> findDocuments(
|
||||
final int start, final int pageSize, final String sortProperty, final boolean asc) {
|
||||
List<Document> documents = documentRepository.findAll();
|
||||
|
||||
int end = Math.min(start + pageSize, documents.size());
|
||||
documents.sort(new BeanComparator<>(sortProperty));
|
||||
|
||||
if (!asc) {
|
||||
Collections.reverse(documents);
|
||||
}
|
||||
|
||||
return documents.subList(start, end);
|
||||
}
|
||||
|
||||
public List<Document> findDocuments(final int start, final int pageSize) {
|
||||
List<Document> employees = documentRepository.findAll();
|
||||
|
||||
int end = Math.min(start + pageSize, employees.size());
|
||||
return employees.subList(start, end);
|
||||
}
|
||||
|
||||
public List<Document> findDocumentBy(final DocumentType documentType,
|
||||
final Employee employee,
|
||||
final int start,
|
||||
final int pageSize) {
|
||||
List<Document> documents = documentRepository.findAll();
|
||||
if (documentType != null) {
|
||||
documents = documents.stream()
|
||||
.filter(doc -> doc.getDocumentType().equals(documentType))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
if (employee != null) {
|
||||
documents = documents.stream()
|
||||
.filter(doc -> doc.getEmployee().equals(employee))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
int end = Math.min(start + pageSize, documents.size());
|
||||
return documents.subList(start, end);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.mail.SimpleMailMessage;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class EmailService {
|
||||
public static final String NO_REPLY_PRIMEFACTORSOLUTIONS_COM = "no-reply@primefactorsolutions.com";
|
||||
private final JavaMailSender emailSender;
|
||||
|
||||
public void sendEmail(final String email, final String title, final String messageContent) {
|
||||
try {
|
||||
final SimpleMailMessage message = new SimpleMailMessage();
|
||||
message.setFrom(NO_REPLY_PRIMEFACTORSOLUTIONS_COM);
|
||||
message.setBcc(NO_REPLY_PRIMEFACTORSOLUTIONS_COM);
|
||||
message.setTo(email);
|
||||
message.setSubject(title);
|
||||
message.setText(messageContent);
|
||||
|
||||
emailSender.send(message);
|
||||
log.info("Sent email to {}", email);
|
||||
} catch (Exception e) {
|
||||
log.error("Error sending email to {}", email, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,72 +1,28 @@
|
||||
package com.primefactorsolutions.service;
|
||||
import com.google.common.base.Strings;
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.beanutils.BeanComparator;
|
||||
import com.primefactorsolutions.repositories.EmployeeRepository;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.support.LdapNameBuilder;
|
||||
import lombok.Data;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.naming.Name;
|
||||
import javax.naming.directory.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.Optional;
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class EmployeeService {
|
||||
private static final String USERPASSWORD = "userPassword";
|
||||
private static final String OBJECTCLASS = "objectclass";
|
||||
private static final String ORGANIZATIONAL_PERSON = "organizationalPerson";
|
||||
private static final String INET_ORG_PERSON = "inetOrgPerson";
|
||||
private static final String TOP = "top";
|
||||
private static final String PERSON = "person";
|
||||
public static final String BASE_DN = "dc=primefactorsolutions,dc=com";
|
||||
|
||||
private final EmployeeRepository employeeRepository;
|
||||
private final LdapTemplate ldapTemplate;
|
||||
private final EntityManager entityManager;
|
||||
|
||||
protected Name buildDn(final Employee employee) {
|
||||
return LdapNameBuilder.newInstance(BASE_DN)
|
||||
.add("ou", "users")
|
||||
.add("uid", employee.getUsername())
|
||||
.build();
|
||||
}
|
||||
|
||||
public List<Employee> getEmployees() {
|
||||
return employeeRepository.findAll();
|
||||
}
|
||||
|
||||
public Employee getDetachedEmployeeByUsername(final String username) {
|
||||
final Employee employee = employeeRepository.findByUsername(username).orElse(null);
|
||||
|
||||
if (employee != null) {
|
||||
entityManager.detach(employee);
|
||||
return employee;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getTeamLeadName(final UUID teamId) {
|
||||
// Encuentra al empleado con el rol de lead_manager en el equipo especificado
|
||||
List<Employee> teamMembers = employeeRepository.findAllByTeamId(teamId);
|
||||
Optional<Employee> leadManager = teamMembers.stream()
|
||||
.filter(e -> Strings.isNullOrEmpty(e.getLeadManager()))
|
||||
.findFirst();
|
||||
return leadManager.map(employee -> employee.getFirstName() + " " + employee.getLastName())
|
||||
.orElse("No asignado");
|
||||
public EmployeeService(final EmployeeRepository employeeRepository) {
|
||||
this.employeeRepository = employeeRepository;
|
||||
}
|
||||
|
||||
public List<Employee> findEmployees(
|
||||
final int start, final int pageSize, final String sortProperty, final boolean asc) {
|
||||
List<Employee> employees = employeeRepository.findAll();
|
||||
Collections.reverse(employees);
|
||||
|
||||
int end = Math.min(start + pageSize, employees.size());
|
||||
employees.sort(new BeanComparator<>(sortProperty));
|
||||
@ -80,62 +36,17 @@ public class EmployeeService {
|
||||
|
||||
public List<Employee> findEmployees(final int start, final int pageSize) {
|
||||
List<Employee> employees = employeeRepository.findAll();
|
||||
Collections.reverse(employees);
|
||||
|
||||
int end = Math.min(start + pageSize, employees.size());
|
||||
return employees.subList(start, end);
|
||||
}
|
||||
|
||||
public Employee getEmployeeByPersonalEmail(final String email) {
|
||||
return employeeRepository.findByPersonalEmail(email).orElse(null);
|
||||
}
|
||||
|
||||
public Employee createOrUpdate(final Employee employee) {
|
||||
if (employee.getId() == null) {
|
||||
final Name dn = buildDn(employee);
|
||||
// ldapClient.bind(dn).attributes(buildAttributes(employee)).execute();
|
||||
ldapTemplate.bind(dn, null, buildAttributes(employee));
|
||||
}
|
||||
|
||||
return employeeRepository.save(employee);
|
||||
}
|
||||
|
||||
public Employee getEmployee(final UUID id) {
|
||||
final Optional<Employee> employee = employeeRepository.findById(id);
|
||||
|
||||
Optional<Employee> employee = employeeRepository.findById(id);
|
||||
return employee.orElse(null);
|
||||
}
|
||||
|
||||
private Attributes buildAttributes(final Employee employee) {
|
||||
final Attributes attrs = new BasicAttributes();
|
||||
final BasicAttribute ocattr = new BasicAttribute(OBJECTCLASS);
|
||||
ocattr.add(TOP);
|
||||
ocattr.add(PERSON);
|
||||
ocattr.add(ORGANIZATIONAL_PERSON);
|
||||
ocattr.add(INET_ORG_PERSON);
|
||||
attrs.put(ocattr);
|
||||
attrs.put("cn", String.format("%s %s", employee.getFirstName(), employee.getLastName()));
|
||||
attrs.put("sn", String.format("%s %s", employee.getFirstName(), employee.getLastName()));
|
||||
attrs.put("uid", employee.getUsername());
|
||||
attrs.put(USERPASSWORD, String.format("%s%s", employee.getUsername(), 123));
|
||||
|
||||
return attrs;
|
||||
}
|
||||
|
||||
public void updatePassword(final Employee employee, final String newPassword) {
|
||||
final Attribute attr = new BasicAttribute(USERPASSWORD, newPassword);
|
||||
final ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
|
||||
|
||||
ldapTemplate.modifyAttributes(buildDn(employee), new ModificationItem[] {item});
|
||||
}
|
||||
|
||||
public List<Employee> findAllEmployees() {
|
||||
List<Employee> employees = employeeRepository.findAll();
|
||||
Collections.reverse(employees);
|
||||
return employees;
|
||||
}
|
||||
|
||||
public List<Employee> findEmployeesByTeam(final String teamName) {
|
||||
return employeeRepository.findByTeamName(teamName);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.Evaluation;
|
||||
import com.primefactorsolutions.repositories.EvaluationRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class EvaluationService {
|
||||
private final EvaluationRepository evaluationRepository;
|
||||
|
||||
public Evaluation createOrUpdate(final Evaluation candidate) {
|
||||
return evaluationRepository.save(candidate);
|
||||
}
|
||||
|
||||
public List<Evaluation> getEvaluations() {
|
||||
return evaluationRepository.findAll();
|
||||
}
|
||||
|
||||
public Evaluation getEvaluation(final UUID id) {
|
||||
return evaluationRepository.findById(id).orElse(null);
|
||||
}
|
||||
}
|
@ -1,197 +0,0 @@
|
||||
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.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/candidate-exam/%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(), null,
|
||||
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(), null,
|
||||
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);
|
||||
}
|
||||
}
|
@ -2,14 +2,14 @@ package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.Question;
|
||||
import com.primefactorsolutions.repositories.QuestionRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class QuestionService {
|
||||
private final QuestionRepository questionRepository;
|
||||
|
||||
|
@ -1,250 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.openhtmltopdf.pdfboxout.PdfBoxRenderer;
|
||||
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapper;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateExceptionHandler;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.pdfbox.io.MemoryUsageSetting;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@Service
|
||||
public class ReportService {
|
||||
public ReportService() {
|
||||
}
|
||||
|
||||
public byte[] writeAsExcel(final String reportName, final List<String> headers,
|
||||
final List<Map<String, Object>> data, final String selectedTeam,
|
||||
final int weekNumber, final int currentYear)
|
||||
throws IOException {
|
||||
return createExcelFile(reportName, headers, data, selectedTeam, weekNumber, currentYear);
|
||||
}
|
||||
|
||||
private byte[] createExcelFile(final String reportName, final List<String> headers,
|
||||
final List<Map<String, Object>> data, final String selectedTeam,
|
||||
final int weekNumber, final int currentYear)
|
||||
throws IOException {
|
||||
try (Workbook workbook = new XSSFWorkbook();
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
||||
Sheet sheet = workbook.createSheet(reportName);
|
||||
|
||||
// Crear encabezados
|
||||
// Crear una fila para el rótulo "Reporte por equipo"
|
||||
Row titleRow = sheet.createRow(0); // Fila 0 para el rótulo
|
||||
Cell titleCell = titleRow.createCell(0);
|
||||
|
||||
// Concatenar el nombre del equipo al rótulo
|
||||
String titleText = "Informe: " + weekNumber + "/" + currentYear;
|
||||
titleCell.setCellValue(titleText);
|
||||
|
||||
// Estilo del rótulo
|
||||
CellStyle titleStyle = workbook.createCellStyle();
|
||||
Font titleFont = workbook.createFont();
|
||||
titleFont.setBold(true);
|
||||
titleFont.setFontHeightInPoints((short) 14); // Tamaño de la fuente
|
||||
titleStyle.setFont(titleFont);
|
||||
titleCell.setCellStyle(titleStyle);
|
||||
|
||||
// Fusionar celdas para el rótulo
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, headers.size() - 1)); // Ajusta el rango de celdas
|
||||
|
||||
// Crear filas adicionales con la información solicitada
|
||||
Row asuntoRow = sheet.createRow(1); // Fila 1: Asunto
|
||||
asuntoRow.createCell(0).setCellValue("Asunto: Informe semanal de horas trabajadas");
|
||||
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, headers.size() - 1));
|
||||
|
||||
Row semanaRow = sheet.createRow(2); // Fila 2: Semana
|
||||
semanaRow.createCell(0).setCellValue("Semana: " + weekNumber); // Puedes insertar una fecha real aquí
|
||||
sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, headers.size() - 1));
|
||||
|
||||
Row horasCumplirRow = sheet.createRow(3); // Fila 3: Horas a cumplir
|
||||
horasCumplirRow.createCell(0).setCellValue("Horas a cumplir: 40 horas"); // Puedes agregar las horas reales
|
||||
sheet.addMergedRegion(new CellRangeAddress(3, 3, 0, headers.size() - 1));
|
||||
|
||||
Row teamLeadRow = sheet.createRow(4); // Fila 4: Team Lead
|
||||
teamLeadRow.createCell(0).setCellValue("Team Lead: "); // Solo texto
|
||||
sheet.addMergedRegion(new CellRangeAddress(4, 4, 0, headers.size() - 1));
|
||||
|
||||
// Crear encabezados (fila 5)
|
||||
Row headerRow = sheet.createRow(5); // Los encabezados empiezan en la fila 5
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerStyle.setFont(headerFont);
|
||||
|
||||
for (int i = 0; i < headers.size(); i++) {
|
||||
Cell cell = headerRow.createCell(i);
|
||||
cell.setCellValue(headers.get(i));
|
||||
cell.setCellStyle(headerStyle);
|
||||
}
|
||||
|
||||
// Crear filas de datos (a partir de la fila 6)
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
Row dataRow = sheet.createRow(i + 6); // Los datos empiezan después de la fila de encabezados
|
||||
Map<String, Object> rowData = data.get(i);
|
||||
int cellIndex = 0;
|
||||
for (String key : headers) {
|
||||
Cell cell = dataRow.createCell(cellIndex++);
|
||||
Object value = rowData.get(key);
|
||||
if (value != null) {
|
||||
if (value instanceof String) {
|
||||
cell.setCellValue((String) value);
|
||||
} else if (value instanceof Number) {
|
||||
cell.setCellValue(((Number) value).doubleValue());
|
||||
}
|
||||
} else {
|
||||
cell.setCellValue(""); // Manejo de valores nulos
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
workbook.write(os);
|
||||
return os.toByteArray();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error al generar el archivo Excel: " + e.getMessage());
|
||||
throw e; // Propagar la excepción después de registrarla
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public byte[] writeAsPdf(final String reportName, final Object model) {
|
||||
try (var os = new ByteArrayOutputStream()) {
|
||||
writeAsPdf(reportName, model, os);
|
||||
|
||||
return os.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public void writeAsPdf(final String reportName, final Object model, final OutputStream out) {
|
||||
var in = getTemplate(reportName);
|
||||
final Configuration cfg = getConfiguration();
|
||||
final Reader reader = new InputStreamReader(in);
|
||||
final Template temp = new Template(reportName, reader, cfg);
|
||||
|
||||
var wrapper = new DefaultObjectWrapper(Configuration.VERSION_2_3_32);
|
||||
ByteArrayOutputStream oo = new ByteArrayOutputStream();
|
||||
Writer outTemplate = new OutputStreamWriter(oo);
|
||||
|
||||
temp.process(wrapper.wrap(model), outTemplate);
|
||||
|
||||
var builder = new PdfRendererBuilder();
|
||||
builder.usePDDocument(new PDDocument(MemoryUsageSetting.setupMixed(1000000)));
|
||||
builder.withHtmlContent(oo.toString(StandardCharsets.UTF_8), "/test");
|
||||
builder.toStream(out);
|
||||
|
||||
try (PdfBoxRenderer pdfBoxRenderer = builder.buildPdfRenderer()) {
|
||||
pdfBoxRenderer.layout();
|
||||
pdfBoxRenderer.createPDF();
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream getTemplate(final String reportName) {
|
||||
return ReportService.class.getResourceAsStream(String.format("/reports/%s.html", reportName));
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private static Configuration getConfiguration() {
|
||||
final Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
|
||||
cfg.setDefaultEncoding("UTF-8");
|
||||
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||
cfg.setLogTemplateExceptions(false);
|
||||
cfg.setWrapUncheckedExceptions(true);
|
||||
cfg.setFallbackOnNullLoopVariable(false);
|
||||
cfg.setSQLDateAndTimeTimeZone(TimeZone.getDefault());
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
public byte[] generateExcelReport(final Employee employee) {
|
||||
try (Workbook workbook = new XSSFWorkbook()) {
|
||||
Sheet sheet = workbook.createSheet("Empleado");
|
||||
Row titleRow = sheet.createRow(0);
|
||||
Cell titleCell = titleRow.createCell(0);
|
||||
titleCell.setCellValue("Información General del Empleado");
|
||||
CellStyle titleStyle = workbook.createCellStyle();
|
||||
Font titleFont = workbook.createFont();
|
||||
titleFont.setBold(true);
|
||||
titleFont.setFontHeightInPoints((short) 16);
|
||||
titleStyle.setFont(titleFont);
|
||||
titleStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
titleCell.setCellStyle(titleStyle);
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 40));
|
||||
Row header = sheet.createRow(2);
|
||||
String[] headers = {
|
||||
"Username", "Nombres", "Apellidos", "Estado", "Género", "Fecha de Nacimiento", "Edad",
|
||||
"Ciudad y País de Nacimiento", "Dirección de Residencia", "Departamento y Provincia de Residencia",
|
||||
"Estado Civil", "Número de Hijos", "CI", "Expedido en", "Teléfono", "E-mail Personal",
|
||||
"Teléfono Laboral",
|
||||
"E-mail Laboral", "Nombres y Apellidos de Contacto", "Dirección de Contacto",
|
||||
"Teléfono de Contacto",
|
||||
"Email de Contacto", "Código de Empleado", "Cargo", "Equipo", "Lead/Manager", "Fecha de Ingreso",
|
||||
"Fecha de Retiro", "Tipo de Contrato", "Tipo de Contrato Personalizado", "Antigüedad",
|
||||
"Salario Total",
|
||||
"Salario Básico", "Bono de Antigüedad", "Bono Profesional", "Banco", "Número de Cuenta",
|
||||
"Código Único de Asegurado (GPSS)", "Matrícula de Asegurado (SSS)", "Derechohabiente 1",
|
||||
"Derechohabiente 2"
|
||||
};
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerStyle.setFont(headerFont);
|
||||
headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = header.createCell(i);
|
||||
cell.setCellValue(headers[i]);
|
||||
cell.setCellStyle(headerStyle);
|
||||
}
|
||||
Row dataRow = sheet.createRow(3); // Fila 3
|
||||
String[] employeeData = {
|
||||
employee.getUsername(), employee.getFirstName(), employee.getLastName(),
|
||||
employee.getStatus().toString(),
|
||||
employee.getGender().toString(), employee.getBirthday().toString(),
|
||||
String.valueOf(employee.getAge()),
|
||||
employee.getBirthCity(), employee.getResidenceAddress(), employee.getLocalAddress(),
|
||||
employee.getMaritalStatus().toString(), String.valueOf(employee.getNumberOfChildren()),
|
||||
employee.getCi(),
|
||||
employee.getIssuedIn(), employee.getPhoneNumber(), employee.getPersonalEmail(),
|
||||
employee.getPhoneNumberProfessional(), employee.getProfessionalEmail(),
|
||||
employee.getEmergencyCName(),
|
||||
employee.getEmergencyCAddress(), employee.getEmergencyCPhone(), employee.getEmergencyCEmail(),
|
||||
employee.getCod(), employee.getPosition(), employee.getTeam().getName(), employee.getLeadManager(),
|
||||
employee.getDateOfEntry().toString(), employee.getDateOfExit() != null ? employee.getDateOfExit()
|
||||
.toString() : "",
|
||||
employee.getContractType().toString(), employee.getCustomContractType(),
|
||||
employee.getSeniority(), employee.getSalaryTotal().toString(), employee.getSalaryBasic().toString(),
|
||||
employee.getTenureBonus().toString(), employee.getProfessionalBonus().toString(),
|
||||
employee.getBankName(), employee.getAccountNumber(), employee.getGpss(), employee.getSss(),
|
||||
employee.getBeneficiarie1(), employee.getBeneficiarie2()
|
||||
};
|
||||
for (int i = 0; i < employeeData.length; i++) {
|
||||
dataRow.createCell(i).setCellValue(employeeData[i] != null ? employeeData[i] : "");
|
||||
}
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
sheet.autoSizeColumn(i);
|
||||
}
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
workbook.write(outputStream);
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error al generar el reporte Excel", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.Team;
|
||||
import com.primefactorsolutions.repositories.TeamRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class TeamService {
|
||||
private final TeamRepository teamRepository;
|
||||
|
||||
public void saveTeam(final Team newTeam) {
|
||||
teamRepository.save(newTeam);
|
||||
}
|
||||
|
||||
public void deleteTeam(final UUID id) {
|
||||
teamRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public List<Team> findAllTeams() {
|
||||
return teamRepository.findAll();
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.*;
|
||||
import com.primefactorsolutions.repositories.TimeOffRequestRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class TimeOffRequestService {
|
||||
private final TimeOffRequestRepository timeOffRequestRepository;
|
||||
|
||||
public void saveTimeOffRequest(final TimeOffRequest newTimeOffRequest) {
|
||||
timeOffRequestRepository.save(newTimeOffRequest);
|
||||
}
|
||||
|
||||
public void deleteTimeOffRequestByEmployeeAndCategory(final UUID employeeId, final TimeOffRequestType category) {
|
||||
timeOffRequestRepository.deleteByEmployeeIdAndCategory(employeeId, category);
|
||||
}
|
||||
|
||||
public void saveAll(final List<TimeOffRequest> requests) {
|
||||
timeOffRequestRepository.saveAll(requests);
|
||||
}
|
||||
|
||||
public void deleteTimeOffRequest(final UUID id) {
|
||||
timeOffRequestRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public List<TimeOffRequest> findAllTimeOffRequests() {
|
||||
return timeOffRequestRepository.findByOrderByUpdatedDesc();
|
||||
}
|
||||
|
||||
public TimeOffRequest findTimeOffRequest(final UUID id) {
|
||||
Optional<TimeOffRequest> timeOffRequest = timeOffRequestRepository.findById(id);
|
||||
return timeOffRequest.orElse(null);
|
||||
}
|
||||
|
||||
public List<TimeOffRequest> findRequestsByState(final TimeOffRequestStatus state) {
|
||||
return timeOffRequestRepository.findByState(state);
|
||||
}
|
||||
|
||||
public List<TimeOffRequest> findRequestsByEmployeeId(final UUID idEmployee) {
|
||||
return timeOffRequestRepository.findByEmployeeId(idEmployee);
|
||||
}
|
||||
|
||||
public Optional<TimeOffRequest> findByEmployeeAndState(final UUID employeeId, final TimeOffRequestStatus state) {
|
||||
return timeOffRequestRepository.findByEmployeeIdAndState(employeeId, state);
|
||||
}
|
||||
|
||||
public List<TimeOffRequest> findByEmployeeAndCategory(final UUID employeeId, final TimeOffRequestType category) {
|
||||
return timeOffRequestRepository.findByEmployeeIdAndCategory(employeeId, category);
|
||||
}
|
||||
|
||||
public void updateRequestStatuses() {
|
||||
List<TimeOffRequest> requests = findAllTimeOffRequests();
|
||||
LocalDate now = LocalDate.now();
|
||||
LocalDate startOfYear = LocalDate.of(now.getYear(), 1, 1);
|
||||
|
||||
for (TimeOffRequest request : requests) {
|
||||
if (request.getCategory() == TimeOffRequestType.VACACION_GESTION_ACTUAL && now.isEqual(startOfYear)) {
|
||||
deleteTimeOffRequestByEmployeeAndCategory(
|
||||
request.getEmployee().getId(),
|
||||
TimeOffRequestType.VACACION_GESTION_ANTERIOR
|
||||
);
|
||||
request.setCategory(TimeOffRequestType.VACACION_GESTION_ANTERIOR);
|
||||
}
|
||||
|
||||
if (request.getState() == TimeOffRequestStatus.APROBADO
|
||||
|| request.getState() == TimeOffRequestStatus.EN_USO) {
|
||||
LocalDate startDate = request.getStartDate();
|
||||
LocalDate endDate = request.getEndDate();
|
||||
|
||||
if (now.isAfter(endDate)) {
|
||||
request.setState(TimeOffRequestStatus.TOMADO);
|
||||
} else if (now.isEqual(startDate) || (now.isAfter(startDate) && now.isBefore(endDate))) {
|
||||
request.setState(TimeOffRequestStatus.EN_USO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saveAll(requests);
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.TimeOffRequestType;
|
||||
import com.primefactorsolutions.model.TimeOff;
|
||||
import com.primefactorsolutions.repositories.TimeOffRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class TimeOffService {
|
||||
private final TimeOffRepository timeOffRepository;
|
||||
|
||||
public TimeOff getTimeOff(final UUID id) {
|
||||
return timeOffRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
public void saveTimeOff(final TimeOff timeOff) {
|
||||
timeOffRepository.save(timeOff);
|
||||
}
|
||||
|
||||
public TimeOff findVacationByCategory(final TimeOffRequestType category) {
|
||||
return timeOffRepository.findByCategory(category);
|
||||
}
|
||||
|
||||
public List<TimeOff> findVacations() {
|
||||
return timeOffRepository.findAll();
|
||||
}
|
||||
|
||||
public List<TimeOff> findTimeOffs(final Integer year) {
|
||||
final LocalDate from = LocalDate.of(year, 1, 1);
|
||||
final LocalDate to = LocalDate.of(year, 12, 31);
|
||||
return timeOffRepository.findByDateBetween(from, to);
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package com.primefactorsolutions.service;
|
||||
|
||||
import com.primefactorsolutions.model.TimesheetEntry;
|
||||
import com.primefactorsolutions.repositories.TimesheetEntryRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class TimesheetService {
|
||||
private final TimesheetEntryRepository timesheetEntryRepository;
|
||||
|
||||
@Autowired
|
||||
public TimesheetService(final TimesheetEntryRepository timesheetEntryRepository) {
|
||||
this.timesheetEntryRepository = timesheetEntryRepository;
|
||||
}
|
||||
|
||||
public List<TimesheetEntry> findAll() {
|
||||
return timesheetEntryRepository.findAll();
|
||||
}
|
||||
|
||||
public TimesheetEntry save(final TimesheetEntry timesheetEntry) {
|
||||
return timesheetEntryRepository.save(timesheetEntry);
|
||||
}
|
||||
|
||||
public TimesheetEntry getTimesheetEntry(final UUID id) {
|
||||
final Optional<TimesheetEntry> hoursWorked = timesheetEntryRepository.findById(id);
|
||||
return hoursWorked.orElse(null);
|
||||
}
|
||||
|
||||
public List<TimesheetEntry> findListHoursWorkedEmployee(final LocalDate from,
|
||||
final LocalDate to) {
|
||||
return timesheetEntryRepository.findByDateBetween(from, to);
|
||||
}
|
||||
}
|
@ -1,13 +1,11 @@
|
||||
package com.primefactorsolutions.views.assessment;
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Candidate;
|
||||
import com.primefactorsolutions.model.Exam;
|
||||
import com.primefactorsolutions.model.Assessment;
|
||||
import com.primefactorsolutions.model.Question;
|
||||
import com.primefactorsolutions.service.ExamService;
|
||||
import com.primefactorsolutions.service.AssessmentService;
|
||||
import com.primefactorsolutions.service.QuestionService;
|
||||
import com.primefactorsolutions.service.CandidateService;
|
||||
import com.primefactorsolutions.views.BaseEntityForm;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.ItemLabelGenerator;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
@ -17,34 +15,32 @@ import com.vaadin.flow.router.HasUrlParameter;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.fields.SubListSelector;
|
||||
import org.vaadin.firitin.form.BeanValidationForm;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@SpringComponent
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Exams")
|
||||
@Route(value = "/exams", layout = MainLayout.class)
|
||||
@PageTitle("Assessments")
|
||||
@Route(value = "/assessments", layout = MainLayout.class)
|
||||
@Uses(ComboBox.class)
|
||||
public class ExamView extends BaseEntityForm<Exam> implements HasUrlParameter<String> {
|
||||
private final ExamService examService;
|
||||
public class AssessmentView extends BeanValidationForm<Assessment> implements HasUrlParameter<String> {
|
||||
private final AssessmentService assessmentService;
|
||||
|
||||
private final ComboBox<Candidate> candidate;
|
||||
private final SubListSelector<Question> questions;
|
||||
private ComboBox<Candidate> candidate = null;
|
||||
private SubListSelector<Question> questions = null;
|
||||
|
||||
public ExamView(final AuthenticationContext authorizationContext,
|
||||
final ExamService examService,
|
||||
final QuestionService questionService,
|
||||
final CandidateService candidateService) {
|
||||
super(authorizationContext, Exam.class);
|
||||
public AssessmentView(final AssessmentService assessmentService, final QuestionService questionService,
|
||||
final CandidateService candidateService) {
|
||||
super(Assessment.class);
|
||||
|
||||
this.examService = examService;
|
||||
this.assessmentService = assessmentService;
|
||||
|
||||
candidate = new ComboBox<>("Candidate", candidateService.getCandidates());
|
||||
candidate.setItemLabelGenerator((ItemLabelGenerator<Candidate>) Candidate::getEmail);
|
||||
@ -55,20 +51,20 @@ public class ExamView extends BaseEntityForm<Exam> implements HasUrlParameter<St
|
||||
questions.setReadOnly(false);
|
||||
questions.setAvailableOptions(questionService.getQuestions());
|
||||
|
||||
setSavedHandler((SavedHandler<Exam>) exam -> {
|
||||
this.examService.saveExam(exam);
|
||||
goTo(ExamsListView.class);
|
||||
setSavedHandler((SavedHandler<Assessment>) assessment -> {
|
||||
final var saved = this.assessmentService.saveAssessment(assessment);
|
||||
setEntityWithEnabledSave(saved);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||
if (StringUtils.isNotBlank(s) && !"new".equals(s)) {
|
||||
final var exam = examService.getExam(UUID.fromString(s));
|
||||
final var assessment = assessmentService.getAssessment(UUID.fromString(s));
|
||||
|
||||
setEntityWithEnabledSave(exam);
|
||||
setEntityWithEnabledSave(assessment);
|
||||
} else {
|
||||
setEntityWithEnabledSave(new Exam());
|
||||
setEntityWithEnabledSave(new Assessment());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,127 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Assessment;
|
||||
import com.primefactorsolutions.service.AssessmentService;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.DataProvider;
|
||||
import com.vaadin.flow.data.provider.DataProviderListener;
|
||||
import com.vaadin.flow.data.provider.Query;
|
||||
import com.vaadin.flow.function.ValueProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.shared.Registration;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.addon.stefan.clipboard.ClientsideClipboard;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Assessments")
|
||||
@Route(value = "/assessments", layout = MainLayout.class)
|
||||
@PermitAll
|
||||
public class AssessmentsListView extends Main {
|
||||
|
||||
public AssessmentsListView(final AssessmentService assessmentService) {
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
final Button addAssessment = new Button("Add Assessment");
|
||||
addAssessment.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
this.getUI().get().navigate(AssessmentView.class, "new");
|
||||
});
|
||||
hl.add(addAssessment);
|
||||
|
||||
final VGrid<Assessment> grid = new VGrid<>(Assessment.class);
|
||||
grid.setColumns("id", "candidate.email");
|
||||
final Grid.Column<Assessment> statusColumn = grid.addColumn((ValueProvider<Assessment, Object>) assessment ->
|
||||
assessment.getAssessmentEvents().isEmpty()
|
||||
? "N/A"
|
||||
: assessment.getAssessmentEvents().getLast().getStatus().name());
|
||||
statusColumn.setHeader("Status");
|
||||
|
||||
grid.addComponentColumn((ValueProvider<Assessment, Component>) assessment -> {
|
||||
var result = new Button("Result", event ->
|
||||
this.getUI().get().navigate(SubmissionView.class, assessment.getId().toString())
|
||||
);
|
||||
result.setEnabled(assessment.isCompleted());
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
grid.addComponentColumn((ValueProvider<Assessment, Component>) assessment -> new Button("Copy Link", event ->
|
||||
ClientsideClipboard.writeToClipboard(
|
||||
String.format("email: %s link: https://careers.primefactorsolutions.com/evaluation/%s",
|
||||
assessment.getCandidate().getEmail(),
|
||||
assessment.getId()))
|
||||
));
|
||||
grid.addComponentColumn((ValueProvider<Assessment, Component>) assessment ->
|
||||
new Button("Send Email", event -> {
|
||||
ConfirmDialog dialog = new ConfirmDialog();
|
||||
dialog.setHeader("Send Link Email");
|
||||
dialog.setText(String.format("Enviar link por email al candidato %s?",
|
||||
assessment.getCandidate().getEmail()));
|
||||
dialog.setCancelable(true);
|
||||
dialog.setConfirmText("Enviar");
|
||||
dialog.setConfirmButtonTheme("primary");
|
||||
dialog.addConfirmListener((ComponentEventListener<ConfirmDialog.ConfirmEvent>) confirmEvent -> {
|
||||
try {
|
||||
assessmentService.sendEmail(assessment);
|
||||
} catch (Exception e) {
|
||||
Notification.show("Error sending email: " + e.getMessage(), 10_000,
|
||||
Notification.Position.TOP_CENTER);
|
||||
}
|
||||
});
|
||||
dialog.open();
|
||||
}));
|
||||
|
||||
grid.setDataProvider(new DataProvider<>() {
|
||||
@Override
|
||||
public boolean isInMemory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size(final Query<Assessment, Object> query) {
|
||||
return assessmentService.getAssessments().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Assessment> fetch(final Query<Assessment, Object> query) {
|
||||
int limit = query.getLimit();
|
||||
int pagerSize = query.getPageSize();
|
||||
int page = query.getPage();
|
||||
|
||||
return assessmentService.getAssessments().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshItem(final Assessment assessment) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshAll() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registration addDataProviderListener(final DataProviderListener<Assessment> dataProviderListener) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
grid.setAllRowsVisible(true);
|
||||
|
||||
add(hl, grid);
|
||||
}
|
||||
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.views.util.AuthUtils;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.UI;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import org.vaadin.firitin.form.BeanValidationForm;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class BaseEntityForm<T> extends BeanValidationForm<T> {
|
||||
private final AuthenticationContext authenticationContext;
|
||||
private Button editButton;
|
||||
private EditHandler<T> editHandler;
|
||||
|
||||
public BaseEntityForm(final AuthenticationContext authenticationContext, final Class<T> entityType) {
|
||||
super(entityType);
|
||||
this.authenticationContext = authenticationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HorizontalLayout getToolbar() {
|
||||
return new HorizontalLayout(getCancelButton(), getEditButton(), getSaveButton());
|
||||
}
|
||||
|
||||
public Button getEditButton() {
|
||||
if (editButton == null) {
|
||||
editButton = new Button("Edit");
|
||||
editButton.setEnabled(false);
|
||||
editButton.addClickListener(__ -> {
|
||||
if (editHandler != null) {
|
||||
editHandler.onEdit(getEntity());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return editButton;
|
||||
}
|
||||
|
||||
public void setEditHandler(final EditHandler<T> editHandler) {
|
||||
this.editHandler = editHandler;
|
||||
getEditButton().setEnabled(editHandler != null);
|
||||
}
|
||||
|
||||
protected <V extends Component> void goTo(final Class<V> view) {
|
||||
getUI().ifPresent(ui -> ui.navigate(view));
|
||||
}
|
||||
|
||||
protected Button getCancelButton() {
|
||||
final Button cancelButton = new Button("Cancel");
|
||||
cancelButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
|
||||
UI.getCurrent().getPage().getHistory().back());
|
||||
|
||||
return cancelButton;
|
||||
}
|
||||
|
||||
protected boolean isRoleAdmin() {
|
||||
return AuthUtils.isAdmin(this.authenticationContext);
|
||||
}
|
||||
|
||||
protected Optional<UUID> getEmployeeId() {
|
||||
return AuthUtils.getEmployeeId(this.authenticationContext);
|
||||
}
|
||||
|
||||
public interface EditHandler<T> extends Serializable {
|
||||
|
||||
void onEdit(T entity);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.views.util.AuthUtils;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
public abstract class BaseView extends Main {
|
||||
|
||||
private final VerticalLayout currentPageLayout;
|
||||
private final AuthenticationContext authenticationContext;
|
||||
|
||||
public BaseView(final AuthenticationContext authenticationContext) {
|
||||
this.authenticationContext = authenticationContext;
|
||||
currentPageLayout = new VerticalLayout();
|
||||
add(currentPageLayout);
|
||||
}
|
||||
|
||||
protected boolean isRoleAdmin() {
|
||||
return AuthUtils.isAdmin(this.authenticationContext);
|
||||
}
|
||||
|
||||
protected Optional<UUID> getEmployeeId() {
|
||||
return AuthUtils.getEmployeeId(this.authenticationContext);
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
public class CalendarView {
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
package com.primefactorsolutions.views.assessment;
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Candidate;
|
||||
import com.primefactorsolutions.service.CandidateService;
|
||||
import com.primefactorsolutions.views.BaseEntityForm;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.textfield.EmailField;
|
||||
import com.vaadin.flow.router.BeforeEvent;
|
||||
@ -11,35 +9,34 @@ import com.vaadin.flow.router.HasUrlParameter;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.form.BeanValidationForm;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Candidates")
|
||||
@PageTitle("Assessments")
|
||||
@Route(value = "/candidates", layout = MainLayout.class)
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
public class CandidateView extends BaseEntityForm<Candidate> implements HasUrlParameter<String> {
|
||||
@PermitAll
|
||||
public class CandidateView extends BeanValidationForm<Candidate> implements HasUrlParameter<String> {
|
||||
private final CandidateService candidateService;
|
||||
|
||||
private EmailField email = null;
|
||||
|
||||
public CandidateView(final AuthenticationContext authenticationContext,
|
||||
final CandidateService candidateService) {
|
||||
super(authenticationContext, Candidate.class);
|
||||
public CandidateView(final CandidateService candidateService) {
|
||||
super(Candidate.class);
|
||||
this.candidateService = candidateService;
|
||||
email = new EmailField();
|
||||
email.setWidthFull();
|
||||
email.setLabel("Email");
|
||||
|
||||
setSavedHandler((SavedHandler<Candidate>) candidate -> {
|
||||
candidateService.createOrUpdate(candidate);
|
||||
goTo(CandidatesListView.class);
|
||||
final Candidate saved = candidateService.createOrUpdate(candidate);
|
||||
setEntityWithEnabledSave(saved);
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Candidate;
|
||||
import com.primefactorsolutions.service.CandidateService;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.DataProvider;
|
||||
import com.vaadin.flow.data.provider.DataProviderListener;
|
||||
import com.vaadin.flow.data.provider.Query;
|
||||
import com.vaadin.flow.function.ValueProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.shared.Registration;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Candidates")
|
||||
@Route(value = "/candidates", layout = MainLayout.class)
|
||||
@PermitAll
|
||||
public class CandidatesListView extends Main {
|
||||
private final CandidateService candidateService;
|
||||
|
||||
public CandidatesListView(final CandidateService candidateService) {
|
||||
this.candidateService = candidateService;
|
||||
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
final Button addCandidate = new Button("Add Candidate");
|
||||
addCandidate.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
this.getUI().get().navigate(CandidateView.class, "new");
|
||||
});
|
||||
hl.add(addCandidate);
|
||||
|
||||
final VGrid<Candidate> grid = new VGrid<>(Candidate.class);
|
||||
grid.setColumns("id", "email");
|
||||
grid.setAllRowsVisible(true);
|
||||
grid.addComponentColumn((ValueProvider<Candidate, Component>) candidate -> {
|
||||
final Button edit = new Button("Edit");
|
||||
edit.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
|
||||
this.getUI().get().navigate(CandidateView.class, candidate.getId().toString()));
|
||||
return edit;
|
||||
});
|
||||
|
||||
grid.setDataProvider(new DataProvider<>() {
|
||||
@Override
|
||||
public boolean isInMemory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size(final Query<Candidate, Object> query) {
|
||||
return candidateService.getCandidates().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Candidate> fetch(final Query<Candidate, Object> query) {
|
||||
int limit = query.getLimit();
|
||||
int pagerSize = query.getPageSize();
|
||||
int page = query.getPage();
|
||||
return candidateService.getCandidates().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshItem(final Candidate candidate) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshAll() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registration addDataProviderListener(final DataProviderListener<Candidate> dataProviderListener) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
add(hl, grid);
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
public class Constants {
|
||||
public static final int PAGE_SIZE = 10;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Documents")
|
||||
@Route(value = "/documents/me", layout = MainLayout.class)
|
||||
public class DocumentsView extends Main {
|
||||
}
|
||||
|
214
src/main/java/com/primefactorsolutions/views/EmployeeView.java
Normal file
214
src/main/java/com/primefactorsolutions/views/EmployeeView.java
Normal file
@ -0,0 +1,214 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.html.H3;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.EmailField;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||
import com.vaadin.flow.router.BeforeEvent;
|
||||
import com.vaadin.flow.router.HasUrlParameter;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.datepicker.VDatePicker;
|
||||
import org.vaadin.firitin.form.BeanValidationForm;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Employee")
|
||||
@Route(value = "/employees", layout = MainLayout.class)
|
||||
public class EmployeeView extends BeanValidationForm<Employee> implements HasUrlParameter<String> {
|
||||
|
||||
private final EmployeeService employeeService;
|
||||
|
||||
private final TextField firstName;
|
||||
private final TextField lastName;
|
||||
private final ComboBox<String> status;
|
||||
private final VDatePicker birthday;
|
||||
private final TextField birthCity;
|
||||
private final ComboBox<String> maritalStatus;
|
||||
private final TextField residenceAddress;
|
||||
private final TextField phoneNumber;
|
||||
private final EmailField personalEmail;
|
||||
|
||||
private final TextField emergencyCName;
|
||||
private final TextField emergencyCAddress;
|
||||
private final TextField emergencyCPhone;
|
||||
private final EmailField emergencyCEmail;
|
||||
|
||||
private final H2 mt;
|
||||
private final H3 fs;
|
||||
private final H3 ss;
|
||||
|
||||
public EmployeeView(final EmployeeService employeeService) {
|
||||
super(Employee.class);
|
||||
this.employeeService = employeeService;
|
||||
|
||||
mt = new H2("Información General del Empleado");
|
||||
fs = new H3("Información Personal");
|
||||
ss = new H3("Datos de Contacto de Emergencia");
|
||||
|
||||
final HorizontalLayout mainLayout = new HorizontalLayout();
|
||||
final VerticalLayout sidebar = createSidebar();
|
||||
final VerticalLayout contentLayout = createContentLayout();
|
||||
final VerticalLayout contentLayout2 = createContentLayout();
|
||||
|
||||
firstName = new TextField("Nombres: ");
|
||||
firstName.setWidthFull();
|
||||
firstName.setMaxLength(30);
|
||||
firstName.setRequired(true);
|
||||
|
||||
lastName = new TextField("Apellidos");
|
||||
lastName.setWidthFull();
|
||||
lastName.setMaxLength(30);
|
||||
lastName.setRequired(true);
|
||||
|
||||
status = new ComboBox<>("Estado");
|
||||
status.setItems(List.of("ACTIVE", "INACTIVE"));
|
||||
lastName.setWidthFull();
|
||||
lastName.setMaxLength(30);
|
||||
status.setRequired(true);
|
||||
|
||||
birthday = new VDatePicker("Fecha de Nacimiento");
|
||||
birthday.setWidthFull();
|
||||
|
||||
birthCity = new TextField("Ciudad y País de Nacimiento");
|
||||
birthCity.setWidthFull();
|
||||
birthCity.setMaxLength(20);
|
||||
|
||||
maritalStatus = new ComboBox<>("Estado Civil");
|
||||
maritalStatus.setItems(List.of("Soltero", "Casado", "Viudo", "Divorciado"));
|
||||
maritalStatus.setWidthFull();
|
||||
|
||||
residenceAddress = new TextField("Dirección de Residencia");
|
||||
residenceAddress.setWidthFull();
|
||||
residenceAddress.setMaxLength(50);
|
||||
|
||||
phoneNumber = new TextField("Teléfono");
|
||||
phoneNumber.setWidthFull();
|
||||
phoneNumber.setMaxLength(8);
|
||||
phoneNumber.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
phoneNumber.addValueChangeListener(e -> {
|
||||
if (!e.getValue().matches("\\d*")) {
|
||||
phoneNumber.setErrorMessage("El teléfono debe contener solo números.");
|
||||
}
|
||||
});
|
||||
|
||||
personalEmail = new EmailField("E-mail");
|
||||
personalEmail.setWidthFull();
|
||||
personalEmail.setMaxLength(30);
|
||||
|
||||
emergencyCName = new TextField("Nombres y Apellidos de Contacto");
|
||||
emergencyCName.setWidthFull();
|
||||
emergencyCName.setMaxLength(50);
|
||||
|
||||
emergencyCAddress = new TextField("Dirección de Contacto");
|
||||
emergencyCAddress.setWidthFull();
|
||||
emergencyCAddress.setMaxLength(50);
|
||||
|
||||
emergencyCPhone = new TextField("Teléfono de Contacto");
|
||||
emergencyCPhone.setWidthFull();
|
||||
emergencyCPhone.setMaxLength(8);
|
||||
emergencyCPhone.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
emergencyCPhone.addValueChangeListener(e -> {
|
||||
if (!e.getValue().matches("\\d*")) {
|
||||
emergencyCPhone.setErrorMessage("El teléfono debe contener solo números.");
|
||||
}
|
||||
});
|
||||
|
||||
emergencyCEmail = new EmailField("Email de Contacto");
|
||||
emergencyCEmail.setWidthFull();
|
||||
emergencyCEmail.setMaxLength(30);
|
||||
|
||||
contentLayout.add(
|
||||
mt, fs, firstName, lastName, status, birthday, birthCity, maritalStatus,
|
||||
residenceAddress, phoneNumber, personalEmail);
|
||||
|
||||
contentLayout2.add(
|
||||
ss, emergencyCName, emergencyCAddress, emergencyCPhone, emergencyCEmail);
|
||||
|
||||
setSavedHandler((SavedHandler<Employee>) employee -> {
|
||||
if (validateForm()) {
|
||||
final Employee saved = employeeService.createOrUpdate(employee);
|
||||
Notification.show("Employee saved successfully.");
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class));
|
||||
setEntityWithEnabledSave(saved);
|
||||
} else {
|
||||
Notification.show("Please complete the required fields correctly.", 3000, Notification.Position.MIDDLE);
|
||||
}
|
||||
});
|
||||
|
||||
mainLayout.add(sidebar, contentLayout, contentLayout2);
|
||||
addClassName("main-layout");
|
||||
}
|
||||
|
||||
private boolean validateForm() {
|
||||
return !firstName.isEmpty() && !lastName.isEmpty() && status.getValue() != null;
|
||||
}
|
||||
|
||||
private VerticalLayout createSidebar() {
|
||||
VerticalLayout sidebar = new VerticalLayout();
|
||||
sidebar.setWidth("250px");
|
||||
sidebar.add(new Button("Información General", e -> navigateToSection("Información General")));
|
||||
sidebar.add(new Button("Detalles Profesionales", e -> navigateToSection("Detalles Profesionales")));
|
||||
return sidebar;
|
||||
}
|
||||
|
||||
private void navigateToSection(final String section) {
|
||||
Notification.show("Navigating to " + section);
|
||||
}
|
||||
|
||||
private VerticalLayout createContentLayout() {
|
||||
VerticalLayout contentLayout = new VerticalLayout();
|
||||
contentLayout.setWidth("100%");
|
||||
return contentLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||
if (StringUtils.isNotBlank(s) && !"new".equals(s)) {
|
||||
var employee = employeeService.getEmployee(UUID.fromString(s));
|
||||
setEntityWithEnabledSave(employee);
|
||||
} else {
|
||||
setEntityWithEnabledSave(new Employee());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Component> getFormComponents() {
|
||||
return List.of(
|
||||
mt,
|
||||
fs,
|
||||
firstName,
|
||||
lastName,
|
||||
status,
|
||||
birthday,
|
||||
birthCity,
|
||||
maritalStatus,
|
||||
residenceAddress,
|
||||
phoneNumber,
|
||||
personalEmail,
|
||||
ss,
|
||||
emergencyCName,
|
||||
emergencyCAddress,
|
||||
emergencyCPhone,
|
||||
emergencyCEmail
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,109 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import org.vaadin.firitin.components.grid.PagingGrid;
|
||||
import com.vaadin.flow.component.grid.GridSortOrder;
|
||||
import com.vaadin.flow.data.provider.SortDirection;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Employees")
|
||||
@Route(value = "/employees", layout = MainLayout.class)
|
||||
@PermitAll
|
||||
public class EmployeesListView extends Main {
|
||||
|
||||
private final EmployeeService employeeService;
|
||||
private final PagingGrid<Employee> table = new PagingGrid<>(Employee.class);
|
||||
|
||||
public EmployeesListView(final EmployeeService employeeService) {
|
||||
this.employeeService = employeeService;
|
||||
setupView();
|
||||
refreshGrid();
|
||||
}
|
||||
|
||||
private void setupView() {
|
||||
add(new H2("Employee List"));
|
||||
configureTable();
|
||||
add(createAddEmployeeButton());
|
||||
add(table);
|
||||
}
|
||||
|
||||
private void configureTable() {
|
||||
table.setColumns("firstName", "lastName", "status");
|
||||
addEditButtonColumn("Edit", this::navigateToEditView);
|
||||
setupPagingGrid();
|
||||
}
|
||||
|
||||
private void updateEmployeeStatus(final Employee employee, final boolean isActive) {
|
||||
employee.setStatus(isActive ? Employee.Status.ACTIVE : Employee.Status.INACTIVE);
|
||||
employeeService.createOrUpdate(employee);
|
||||
refreshGrid();
|
||||
}
|
||||
|
||||
private void addEditButtonColumn(final String label, final ButtonClickHandler handler) {
|
||||
table.addComponentColumn(employee -> createButton(label, () -> handler.handle(employee)));
|
||||
}
|
||||
|
||||
private Button createButton(final String label, final Runnable onClickAction) {
|
||||
Button button = new Button(label);
|
||||
button.addClickListener(event -> onClickAction.run());
|
||||
return button;
|
||||
}
|
||||
|
||||
private Button createAddEmployeeButton() {
|
||||
return createButton("Add Employee", this::navigateToAddEmployeeView);
|
||||
}
|
||||
|
||||
private void navigateToEditView(final Employee employee) {
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, employee.getId().toString()));
|
||||
}
|
||||
|
||||
private void navigateToAddEmployeeView() {
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, "new"));
|
||||
}
|
||||
|
||||
private void setupPagingGrid() {
|
||||
table.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
||||
table.setPageSize(5);
|
||||
}
|
||||
|
||||
private void refreshGrid() {
|
||||
table.setPagingDataProvider((page, pageSize) -> fetchEmployees((int) page, pageSize));
|
||||
}
|
||||
|
||||
private List<Employee> fetchEmployees(final int page, final int pageSize) {
|
||||
int start = page * pageSize;
|
||||
if (hasSortOrder()) {
|
||||
return fetchSortedEmployees(start, pageSize);
|
||||
}
|
||||
return employeeService.findEmployees(start, pageSize);
|
||||
}
|
||||
|
||||
private boolean hasSortOrder() {
|
||||
return !table.getSortOrder().isEmpty();
|
||||
}
|
||||
|
||||
private List<Employee> fetchSortedEmployees(final int start, final int pageSize) {
|
||||
GridSortOrder<Employee> sortOrder = table.getSortOrder().getFirst();
|
||||
return employeeService.findEmployees(start, pageSize,
|
||||
sortOrder.getSorted().getKey(),
|
||||
sortOrder.getDirection() == SortDirection.ASCENDING);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface ButtonClickHandler {
|
||||
void handle(Employee employee);
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import com.hilerio.ace.AceEditor;
|
||||
import com.hilerio.ace.AceMode;
|
||||
import com.hilerio.ace.AceTheme;
|
||||
import com.primefactorsolutions.model.*;
|
||||
import com.primefactorsolutions.service.ExamService;
|
||||
import com.primefactorsolutions.service.AssessmentService;
|
||||
import com.primefactorsolutions.service.CompilerService;
|
||||
import com.vaadin.flow.component.*;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
@ -27,15 +27,19 @@ import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Background;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BoxSizing;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Display;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Flex;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FlexDirection;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontSize;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontWeight;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Height;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Overflow;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Padding;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
|
||||
import io.overcoded.vaadin.panel.Panel;
|
||||
import io.overcoded.vaadin.panel.PanelConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
@ -45,23 +49,24 @@ import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@PageTitle("Evaluacion")
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@Route(value = "/candidate-exam", layout = MainLayout.class)
|
||||
@Route(value = "/evaluation", layout = MainLayout.class)
|
||||
@AnonymousAllowed
|
||||
@Slf4j
|
||||
public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
public class EvaluationView extends Main implements HasUrlParameter<String> {
|
||||
|
||||
private final CompilerService compilerService;
|
||||
private final ExamService examService;
|
||||
private final AssessmentService assessmentService;
|
||||
|
||||
private AceEditor questionEditor = null;
|
||||
private Dialog dialog = null;
|
||||
private Dialog completeDialog = null;
|
||||
private AceEditor result = null;
|
||||
private Exam exam = null;
|
||||
private Assessment assessment = null;
|
||||
private Submission currSubmission = null;
|
||||
private Boolean isCompleted = false;
|
||||
|
||||
@ -69,48 +74,33 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
private MenuItem prev = null;
|
||||
private MenuItem next = null;
|
||||
private MenuItem reset = null;
|
||||
private MenuItem finish = null;
|
||||
private Panel candidatePanel = null;
|
||||
private Section sidebar = null;
|
||||
private SimpleTimer timer = null;
|
||||
private DescriptionList dl = null;
|
||||
private Section editorSection = null;
|
||||
private Section startSection = null;
|
||||
private Section completedSection = null;
|
||||
private H3 questionTitle = null;
|
||||
private Text questionDescription = null;
|
||||
|
||||
public CandidateExamView(final CompilerService compilerService, final ExamService examService) {
|
||||
public EvaluationView(final CompilerService compilerService, final AssessmentService assessmentService) {
|
||||
this.compilerService = compilerService;
|
||||
this.examService = examService;
|
||||
this.assessmentService = assessmentService;
|
||||
|
||||
addClassNames(Display.FLEX, Flex.GROW, Height.FULL);
|
||||
|
||||
initStartSection();
|
||||
initCompletedSection();
|
||||
initEditorSection();
|
||||
initResultDialog();
|
||||
initCompleteDialog();
|
||||
initTimer(examService);
|
||||
initCandidatePanel();
|
||||
initSidebar();
|
||||
|
||||
VerticalLayout vl = new VerticalLayout();
|
||||
vl.add(completedSection, candidatePanel, startSection, editorSection, dialog);
|
||||
add(vl);
|
||||
add(completedSection, startSection, editorSection, sidebar, dialog);
|
||||
|
||||
updateUI();
|
||||
}
|
||||
|
||||
private void initTimer(final ExamService examService) {
|
||||
timer = new SimpleTimer(0);
|
||||
timer.setMinutes(true);
|
||||
timer.addTimerEndEvent((ComponentEventListener<SimpleTimer.TimerEndedEvent>) timerEndedEvent -> {
|
||||
Notification.show("Tiempo completado.", 5_000, Notification.Position.TOP_CENTER);
|
||||
this.currSubmission.setText(this.questionEditor.getValue());
|
||||
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||
this.exam = examService.completeExam(exam.getId());
|
||||
goToCompleted();
|
||||
updateUI();
|
||||
});
|
||||
timer.setFractions(false);
|
||||
}
|
||||
|
||||
private void initResultDialog() {
|
||||
dialog = new Dialog();
|
||||
dialog.setHeaderTitle("Resultados");
|
||||
@ -138,8 +128,8 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
dialog.add(dialogLayout);
|
||||
|
||||
final Button saveButton = new Button("Guardar y Siguiente", e -> {
|
||||
this.currSubmission.setText(this.questionEditor.getValue());
|
||||
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
||||
dialog.close();
|
||||
goToNext();
|
||||
});
|
||||
@ -166,9 +156,9 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
|
||||
final Button completeButton = new Button("Terminar", e -> {
|
||||
completeDialog.close();
|
||||
this.currSubmission.setText(this.questionEditor.getValue());
|
||||
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||
this.exam = examService.completeExam(exam.getId());
|
||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
||||
this.assessment = assessmentService.completeAssessment(assessment.getId());
|
||||
goToCompleted();
|
||||
updateUI();
|
||||
});
|
||||
@ -205,26 +195,24 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
|
||||
final MenuBar navMenuBar = new MenuBar();
|
||||
prev = navMenuBar.addItem("Anterior pregunta",
|
||||
menuItemClickEvent -> {
|
||||
this.currSubmission.setText(this.questionEditor.getValue());
|
||||
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||
this.currSubmission = this.examService.getPrevSubmission(exam.getId(), this.currSubmission);
|
||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||
log.info(">>> prev");
|
||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
||||
this.currSubmission = this.assessmentService.getPrevSubmission(assessment.getId(), this.currSubmission);
|
||||
updateUI();
|
||||
});
|
||||
next = navMenuBar.addItem("Siguiente pregunta",
|
||||
menuItemClickEvent -> {
|
||||
this.currSubmission.setText(this.questionEditor.getValue());
|
||||
this.examService.saveSubmission(exam.getId(), this.currSubmission);
|
||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
||||
goToNext();
|
||||
});
|
||||
reset = navMenuBar.addItem("Reiniciar pregunta (deshacer todos los cambios)",
|
||||
menuItemClickEvent -> {
|
||||
this.currSubmission.setText(this.currSubmission.getQuestion().getContent());
|
||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||
this.currSubmission.setResponse(this.currSubmission.getQuestion().getContent());
|
||||
this.questionEditor.setValue(this.currSubmission.getQuestion().getContent());
|
||||
});
|
||||
finish = navMenuBar.addItem("Terminar evaluacion", menuItemClickEvent -> {
|
||||
this.completeDialog.open();
|
||||
});
|
||||
|
||||
final Div menuBar = new Div();
|
||||
menuBar.add(runMenuBar, navMenuBar);
|
||||
@ -265,9 +253,10 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
start = new Button("Empezar");
|
||||
start.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||
start.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
this.exam = this.examService.startExam(this.exam.getId());
|
||||
log.info(">>> start");
|
||||
this.assessment = this.assessmentService.startAssessment(this.assessment.getId());
|
||||
|
||||
if (tf.getValue().trim().equalsIgnoreCase(this.exam.getCandidate().getEmail())) {
|
||||
if (tf.getValue().trim().equalsIgnoreCase(this.assessment.getCandidate().getEmail())) {
|
||||
this.getUI().get().getPage().reload();
|
||||
} else {
|
||||
Notification notification = new Notification();
|
||||
@ -329,7 +318,8 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
}
|
||||
|
||||
private void goToNext() {
|
||||
Submission found = this.examService.getNextSubmission(exam.getId(),
|
||||
log.info(">>> next");
|
||||
Submission found = this.assessmentService.getNextSubmission(assessment.getId(),
|
||||
this.currSubmission.getId());
|
||||
|
||||
if (found == null) {
|
||||
@ -340,44 +330,78 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
}
|
||||
}
|
||||
|
||||
private void initCandidatePanel() {
|
||||
final PanelConfig config = PanelConfig.builder()
|
||||
.closeable(false)
|
||||
.collapsable(false)
|
||||
.build();
|
||||
private void initSidebar() {
|
||||
sidebar = new Section();
|
||||
sidebar.addClassNames(Background.CONTRAST_5, BoxSizing.BORDER, Display.FLEX, FlexDirection.COLUMN,
|
||||
Flex.SHRINK_NONE, Overflow.AUTO, Padding.LARGE);
|
||||
sidebar.setWidth("256px");
|
||||
|
||||
candidatePanel = new Panel(config, "", new HorizontalLayout());
|
||||
candidatePanel.setVisible(false);
|
||||
dl = new DescriptionList();
|
||||
dl.addClassNames(Display.FLEX, FlexDirection.COLUMN, Gap.LARGE, Margin.Bottom.SMALL, Margin.Top.NONE,
|
||||
FontSize.SMALL);
|
||||
|
||||
final Text text = new Text("Tiempo restante:");
|
||||
|
||||
timer = new SimpleTimer(0);
|
||||
timer.setMinutes(true);
|
||||
timer.addTimerEndEvent((ComponentEventListener<SimpleTimer.TimerEndedEvent>) timerEndedEvent -> {
|
||||
Notification.show("Tiempo completado.", 5_000, Notification.Position.TOP_CENTER);
|
||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||
this.assessmentService.saveSubmission(assessment.getId(), this.currSubmission);
|
||||
this.assessment = assessmentService.completeAssessment(assessment.getId());
|
||||
goToCompleted();
|
||||
updateUI();
|
||||
});
|
||||
timer.setFractions(false);
|
||||
|
||||
final Button completeButton = new Button("Terminar evaluacion");
|
||||
completeButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||
completeButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
this.completeDialog.open();
|
||||
});
|
||||
|
||||
// Add it all together
|
||||
sidebar.add(dl, text, timer, completeButton);
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
if (exam == null || !exam.isStarted()) {
|
||||
if (assessment == null || !assessment.isStarted()) {
|
||||
editorSection.setVisible(false);
|
||||
startSection.setVisible(true);
|
||||
sidebar.setVisible(false);
|
||||
} else {
|
||||
if (currSubmission != null) {
|
||||
questionEditor.setValue(this.currSubmission.getText());
|
||||
questionEditor.setValue(this.currSubmission.getResponse());
|
||||
questionTitle.setText(this.currSubmission.getQuestion().getTitle());
|
||||
questionDescription.setText(this.currSubmission.getQuestion().getDescription());
|
||||
}
|
||||
|
||||
editorSection.setVisible(true);
|
||||
startSection.setVisible(false);
|
||||
sidebar.setVisible(true);
|
||||
|
||||
updateCandidatePanel();
|
||||
prev.setEnabled(currSubmission != null && !assessment.isFirst(currSubmission));
|
||||
next.setEnabled(currSubmission == null || !assessment.isLast(currSubmission));
|
||||
|
||||
prev.setEnabled(currSubmission != null && !exam.isFirst(currSubmission));
|
||||
next.setEnabled(currSubmission == null || !exam.isLast(currSubmission));
|
||||
|
||||
if (this.exam.isCompleted()) {
|
||||
if (this.assessment.isCompleted()) {
|
||||
goToCompleted();
|
||||
this.editorSection.setVisible(false);
|
||||
this.candidatePanel.setVisible(false);
|
||||
this.sidebar.setVisible(false);
|
||||
this.startSection.setVisible(false);
|
||||
this.completedSection.setVisible(true);
|
||||
}
|
||||
|
||||
final Long remainingTime = this.exam.getRemainingTimeSeconds();
|
||||
if (dl.getChildren().collect(Collectors.toList()).isEmpty()) {
|
||||
dl.add(
|
||||
createItem("Candidato:", assessment.getCandidate().getEmail()),
|
||||
createItem("Hora de inicio:", Optional.ofNullable(assessment.getStartingTime())
|
||||
.map(t -> ZonedDateTime.ofInstant(t,
|
||||
ZoneId.of("GMT-4")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
|
||||
.orElse("N/A"))
|
||||
);
|
||||
}
|
||||
|
||||
final Long remainingTime = this.assessment.getRemainingTimeSeconds();
|
||||
timer.pause();
|
||||
timer.setStartTime(remainingTime > 0 ? remainingTime : 3);
|
||||
timer.setMinutes(true);
|
||||
@ -386,19 +410,6 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCandidatePanel() {
|
||||
final Text candidateName = new Text("Candidato: " + exam.getCandidate().getEmail() + ", ");
|
||||
final Text startTime = new Text("Hora de inicio: " + Optional.ofNullable(exam.getStartingTime())
|
||||
.map(t -> ZonedDateTime.ofInstant(t,
|
||||
ZoneId.of("GMT-4")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
|
||||
.orElse("N/A") + ", ");
|
||||
final Text text = new Text("Tiempo restante:");
|
||||
final HorizontalLayout layout = new HorizontalLayout(candidateName, startTime, text, timer);
|
||||
layout.setWidthFull();
|
||||
candidatePanel.setContent(layout);
|
||||
candidatePanel.setVisible(true);
|
||||
}
|
||||
|
||||
private Div createItem(final String label, final String value) {
|
||||
return new Div(createTerm(label), createDescription(value));
|
||||
}
|
||||
@ -426,18 +437,18 @@ public class CandidateExamView extends Main implements HasUrlParameter<String> {
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||
this.exam = this.examService.getExam(UUID.fromString(s));
|
||||
this.assessment = this.assessmentService.getAssessment(UUID.fromString(s));
|
||||
|
||||
if (this.exam == null) {
|
||||
if (this.assessment == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (this.exam.isCompleted()) {
|
||||
if (this.assessment.isCompleted()) {
|
||||
goToCompleted();
|
||||
}
|
||||
|
||||
this.currSubmission = this.exam.isStarted()
|
||||
? this.examService.getNextSubmission(exam.getId(), null)
|
||||
this.currSubmission = this.assessment.isStarted()
|
||||
? this.assessmentService.getNextSubmission(assessment.getId(), null)
|
||||
: null;
|
||||
|
||||
updateUI();
|
@ -1,54 +0,0 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.formlayout.FormLayout;
|
||||
import com.vaadin.flow.component.html.H3;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.PasswordField;
|
||||
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Route("init-account")
|
||||
@PageTitle("PFS Intra")
|
||||
@AnonymousAllowed
|
||||
public class InitAccountView extends VerticalLayout implements BeforeEnterObserver {
|
||||
|
||||
public InitAccountView() {
|
||||
setSizeFull();
|
||||
setAlignItems(Alignment.CENTER);
|
||||
setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
|
||||
final VerticalLayout vl = new VerticalLayout();
|
||||
vl.setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
vl.setWidth("400px");
|
||||
|
||||
final PasswordField password = new PasswordField("Password");
|
||||
final PasswordField confirmPassword = new PasswordField("Confirm Password");
|
||||
|
||||
final FormLayout formLayout = new FormLayout(password, confirmPassword);
|
||||
formLayout.setColspan(password, 3);
|
||||
formLayout.setColspan(confirmPassword, 3);
|
||||
|
||||
final Button primaryButton = new Button("Submit");
|
||||
primaryButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
|
||||
final Button secondaryButton = new Button("Cancel");
|
||||
HorizontalLayout hl = new HorizontalLayout(secondaryButton, primaryButton);
|
||||
|
||||
vl.add(new H3("Set Account Password"));
|
||||
vl.add(formLayout);
|
||||
vl.add(hl);
|
||||
|
||||
add(vl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEnter(final BeforeEnterEvent beforeEnterEvent) {
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.html.Anchor;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.login.LoginForm;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||
@ -10,9 +8,6 @@ import com.vaadin.flow.router.BeforeEnterObserver;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
@Route("login")
|
||||
@PageTitle("PFS Intra")
|
||||
@ -21,22 +16,16 @@ public class LoginView extends VerticalLayout implements BeforeEnterObserver {
|
||||
|
||||
private final LoginForm login = new LoginForm();
|
||||
|
||||
public LoginView(@Autowired @Value("${git.commit.id.abbrev}") final String commitId) {
|
||||
public LoginView() {
|
||||
addClassName("login-view");
|
||||
setSizeFull();
|
||||
setAlignItems(Alignment.CENTER);
|
||||
setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
|
||||
login.setAction("login");
|
||||
login.setForgotPasswordButtonVisible(false);
|
||||
|
||||
add(new H1("PFS Intra"));
|
||||
add(login);
|
||||
add(new Anchor("/password-recovery", "Reset password?"));
|
||||
|
||||
final Span version = new Span(String.format("v.%s", commitId));
|
||||
version.addClassName(LumoUtility.FontSize.XSMALL);
|
||||
add(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,46 +1,20 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.views.assessment.EvaluationsListView;
|
||||
import com.primefactorsolutions.views.employee.DocumentsListView;
|
||||
import com.primefactorsolutions.views.employee.EmployeesListView;
|
||||
import com.primefactorsolutions.views.admin.TimeOffListView;
|
||||
import com.primefactorsolutions.views.assessment.ExamsListView;
|
||||
import com.primefactorsolutions.views.assessment.CandidatesListView;
|
||||
import com.primefactorsolutions.views.assessment.QuestionsListView;
|
||||
import com.primefactorsolutions.views.timeoff.TimeOffRequestsListView;
|
||||
import com.primefactorsolutions.views.timeoff.TimeOffSummaryListView;
|
||||
import com.primefactorsolutions.views.timesheet.TimesheetListView;
|
||||
import com.primefactorsolutions.views.timesheet.TimesheetReportView;
|
||||
import com.primefactorsolutions.views.util.AuthUtils;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.Text;
|
||||
import com.vaadin.flow.component.applayout.AppLayout;
|
||||
import com.vaadin.flow.component.applayout.DrawerToggle;
|
||||
import com.vaadin.flow.component.avatar.Avatar;
|
||||
import com.vaadin.flow.component.contextmenu.HasMenuItems;
|
||||
import com.vaadin.flow.component.contextmenu.MenuItem;
|
||||
import com.vaadin.flow.component.contextmenu.SubMenu;
|
||||
import com.vaadin.flow.component.html.*;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.menubar.MenuBar;
|
||||
import com.vaadin.flow.component.menubar.MenuBarVariant;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.html.Footer;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Header;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.orderedlayout.Scroller;
|
||||
import com.vaadin.flow.component.sidenav.SideNav;
|
||||
import com.vaadin.flow.component.sidenav.SideNavItem;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.vaadin.lineawesome.LineAwesomeIcon;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* The main view is a top-level placeholder for other views.
|
||||
*/
|
||||
@ -49,158 +23,79 @@ public class MainLayout extends AppLayout {
|
||||
|
||||
private H1 viewTitle;
|
||||
|
||||
public MainLayout(final AuthenticationContext authContext,
|
||||
@Autowired @Value("${git.commit.id.abbrev}") final String commitId) {
|
||||
public MainLayout(final AuthenticationContext authContext) {
|
||||
this.authContext = authContext;
|
||||
setPrimarySection(Section.DRAWER);
|
||||
addDrawerContent(commitId);
|
||||
addDrawerContent();
|
||||
addHeaderContent();
|
||||
}
|
||||
|
||||
private void addHeaderContent() {
|
||||
final DrawerToggle toggle = new DrawerToggle();
|
||||
DrawerToggle toggle = new DrawerToggle();
|
||||
toggle.setAriaLabel("Menu toggle");
|
||||
|
||||
viewTitle = new H1();
|
||||
viewTitle.addClassNames(LumoUtility.FontSize.LARGE, LumoUtility.Margin.NONE);
|
||||
|
||||
final HorizontalLayout header = authContext.getAuthenticatedUser(UserDetails.class)
|
||||
.map(user -> {
|
||||
String employeeId = "N/A";
|
||||
|
||||
if (user instanceof Employee) {
|
||||
final UUID uuid = ((Employee) user).getId();
|
||||
|
||||
if (uuid != null) {
|
||||
employeeId = uuid.toString();
|
||||
}
|
||||
}
|
||||
|
||||
final Avatar loggedUser = new Avatar(user.getUsername());
|
||||
loggedUser.getStyle().set("display", "block");
|
||||
loggedUser.getElement().setAttribute("tabindex", "-1");
|
||||
|
||||
final MenuBar menuBar = new MenuBar();
|
||||
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
|
||||
final MenuItem actions = createIconItem(menuBar, loggedUser, null, employeeId);
|
||||
final SubMenu actionsSubMenu = actions.getSubMenu();
|
||||
final MenuItem signOutMenuItem = createIconItem(actionsSubMenu,
|
||||
createIcon(VaadinIcon.EXIT, true), "Sign-out", null);
|
||||
signOutMenuItem.addClickListener(c -> this.authContext.logout());
|
||||
|
||||
final HorizontalLayout hl = new HorizontalLayout(menuBar);
|
||||
hl.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
|
||||
|
||||
return hl;
|
||||
}).orElseGet(HorizontalLayout::new);
|
||||
header.setAlignItems(FlexComponent.Alignment.STRETCH);
|
||||
header.setWidthFull();
|
||||
|
||||
addToNavbar(true, toggle, viewTitle, header);
|
||||
addToNavbar(true, toggle, viewTitle);
|
||||
}
|
||||
|
||||
private MenuItem createIconItem(final HasMenuItems menu, final Component component,
|
||||
final String label, final String ariaLabel) {
|
||||
final MenuItem item = menu.addItem(component, e -> {
|
||||
});
|
||||
|
||||
if (ariaLabel != null) {
|
||||
item.setAriaLabel(ariaLabel);
|
||||
}
|
||||
|
||||
if (label != null) {
|
||||
item.add(new Text(label));
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private Icon createIcon(final VaadinIcon iconName, final boolean isChild) {
|
||||
final Icon icon = new Icon(iconName);
|
||||
|
||||
if (isChild) {
|
||||
icon.getStyle().set("width", "var(--lumo-icon-size-s)");
|
||||
icon.getStyle().set("height", "var(--lumo-icon-size-s)");
|
||||
icon.getStyle().set("marginRight", "var(--lumo-space-s)");
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private void addDrawerContent(final String commitId) {
|
||||
final Span appName = new Span("pfs-intra");
|
||||
private void addDrawerContent() {
|
||||
Span appName = new Span("pfs-intra");
|
||||
appName.addClassNames(LumoUtility.FontWeight.SEMIBOLD, LumoUtility.FontSize.LARGE);
|
||||
final Header header = new Header(appName);
|
||||
final Scroller scroller = new Scroller(createNavigation());
|
||||
addToDrawer(header, scroller, createFooter(commitId));
|
||||
Header header = new Header(appName);
|
||||
|
||||
Scroller scroller = new Scroller(createNavigation());
|
||||
|
||||
addToDrawer(header, scroller, createFooter());
|
||||
}
|
||||
|
||||
private SideNav createNavigation() {
|
||||
final SideNav nav = new SideNav();
|
||||
SideNav nav = new SideNav();
|
||||
|
||||
if (AuthUtils.isUser(authContext)) {
|
||||
nav.addItem(new SideNavItem("Home", MainView.class, LineAwesomeIcon.HOME_SOLID.create()));
|
||||
authContext.getAuthenticatedUser(UserDetails.class).ifPresent(u -> {
|
||||
SideNavItem recruiting = new SideNavItem("Recruiting", MainView.class,
|
||||
LineAwesomeIcon.BUSINESS_TIME_SOLID.create());
|
||||
recruiting.addItem(new SideNavItem("Assessments", AssessmentsListView.class,
|
||||
LineAwesomeIcon.RIBBON_SOLID.create()));
|
||||
recruiting.addItem(new SideNavItem("Candidates", CandidatesListView.class,
|
||||
LineAwesomeIcon.USER.create()));
|
||||
recruiting.addItem(new SideNavItem("Questions", QuestionsListView.class,
|
||||
LineAwesomeIcon.QUESTION_SOLID.create()));
|
||||
|
||||
if (AuthUtils.isAdmin(authContext)) {
|
||||
SideNavItem admin = new SideNavItem("Admin");
|
||||
admin.setPrefixComponent(LineAwesomeIcon.BUILDING.create());
|
||||
admin.addItem(new SideNavItem("Calendario", TimeOffListView.class,
|
||||
LineAwesomeIcon.CALENDAR.create()));
|
||||
nav.addItem(admin);
|
||||
|
||||
SideNavItem recruiting = new SideNavItem("Recruiting");
|
||||
recruiting.setPrefixComponent(LineAwesomeIcon.BUSINESS_TIME_SOLID.create());
|
||||
recruiting.addItem(new SideNavItem("Candidates", CandidatesListView.class,
|
||||
LineAwesomeIcon.USER.create()));
|
||||
recruiting.addItem(new SideNavItem("Evaluations", EvaluationsListView.class,
|
||||
LineAwesomeIcon.BOOK_READER_SOLID.create()));
|
||||
recruiting.addItem(new SideNavItem("Exams", ExamsListView.class,
|
||||
LineAwesomeIcon.PEN_NIB_SOLID.create()));
|
||||
recruiting.addItem(new SideNavItem("Questions", QuestionsListView.class,
|
||||
LineAwesomeIcon.QUESTION_SOLID.create()));
|
||||
nav.addItem(recruiting);
|
||||
}
|
||||
|
||||
final SideNavItem timeOff = new SideNavItem("Time-off");
|
||||
timeOff.setPrefixComponent(LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create());
|
||||
timeOff.addItem(new SideNavItem("Vacations", TimeOffSummaryListView.class,
|
||||
LineAwesomeIcon.UMBRELLA_BEACH_SOLID.create()));
|
||||
timeOff.addItem(new SideNavItem("Requests", TimeOffRequestsListView.class,
|
||||
LineAwesomeIcon.LIST_ALT.create()));
|
||||
|
||||
final SideNavItem timesheet = new SideNavItem("Timesheet");
|
||||
timesheet.setPrefixComponent(LineAwesomeIcon.HOURGLASS_START_SOLID.create());
|
||||
timesheet.addItem(new SideNavItem("Registro de Horas Trabajadas", TimesheetListView.class,
|
||||
LineAwesomeIcon.ID_CARD_SOLID.create()));
|
||||
|
||||
if (AuthUtils.isAdmin(authContext)) {
|
||||
timesheet.addItem(new SideNavItem("Reporte Horas Trabajadas", TimesheetReportView.class,
|
||||
LineAwesomeIcon.ID_CARD_SOLID.create()));
|
||||
}
|
||||
|
||||
final SideNavItem profile = new SideNavItem("Employee");
|
||||
profile.setPrefixComponent(LineAwesomeIcon.USER_TIE_SOLID.create());
|
||||
|
||||
if (AuthUtils.isAdmin(authContext)) {
|
||||
profile.addItem(new SideNavItem("Profiles", EmployeesListView.class,
|
||||
LineAwesomeIcon.USER_FRIENDS_SOLID.create()));
|
||||
}
|
||||
|
||||
profile.addItem(new SideNavItem("My Profile", "/employees/me",
|
||||
SideNavItem admin = new SideNavItem("Admin", MainView.class,
|
||||
LineAwesomeIcon.SUPERSCRIPT_SOLID.create());
|
||||
admin.addItem(new SideNavItem("Requests", RequestsListView.class,
|
||||
LineAwesomeIcon.TASKS_SOLID.create()));
|
||||
admin.addItem(new SideNavItem("Timesheets", TimesheestReportView.class,
|
||||
LineAwesomeIcon.HOURGLASS_END_SOLID.create()));
|
||||
admin.addItem(new SideNavItem("Employees", EmployeesListView.class,
|
||||
LineAwesomeIcon.USER_EDIT_SOLID.create()));
|
||||
profile.addItem(new SideNavItem("Documents", DocumentsListView.class,
|
||||
LineAwesomeIcon.FILE_ALT_SOLID.create()));
|
||||
|
||||
SideNavItem timeOff = new SideNavItem("My Time-off", TimeoffView.class,
|
||||
LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create());
|
||||
SideNavItem timesheet = new SideNavItem("My Timesheet", TimesheetView.class,
|
||||
LineAwesomeIcon.HOURGLASS_START_SOLID.create());
|
||||
SideNavItem profile = new SideNavItem("My Profile", ProfileView.class,
|
||||
LineAwesomeIcon.USER_EDIT_SOLID.create());
|
||||
SideNavItem documents = new SideNavItem("My Documents", DocumentsView.class,
|
||||
LineAwesomeIcon.SUITCASE_SOLID.create());
|
||||
|
||||
nav.addItem(new SideNavItem("Home", MainView.class, LineAwesomeIcon.HOME_SOLID.create()));
|
||||
nav.addItem(admin);
|
||||
nav.addItem(recruiting);
|
||||
nav.addItem(profile);
|
||||
nav.addItem(timesheet);
|
||||
nav.addItem(timeOff);
|
||||
}
|
||||
});
|
||||
|
||||
return nav;
|
||||
}
|
||||
|
||||
private Footer createFooter(final String commitId) {
|
||||
return new Footer(new Text(String.format("v.%s", commitId)));
|
||||
private Footer createFooter() {
|
||||
Footer layout = new Footer();
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,7 +2,6 @@ package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.Text;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
@ -11,8 +10,7 @@ import jakarta.annotation.security.PermitAll;
|
||||
@Route(value = "", layout = MainLayout.class)
|
||||
@PermitAll
|
||||
public class MainView extends Main {
|
||||
|
||||
public MainView() {
|
||||
add(new VerticalLayout(new Text("Welcome to PFS!")));
|
||||
add(new Text("welcome"));
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.service.AccountService;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.formlayout.FormLayout;
|
||||
import com.vaadin.flow.component.html.H3;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.EmailField;
|
||||
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
|
||||
@Route("password-recovery")
|
||||
@PageTitle("PFS Intra")
|
||||
@AnonymousAllowed
|
||||
public class PasswordRecoveryView extends VerticalLayout implements BeforeEnterObserver {
|
||||
|
||||
public PasswordRecoveryView(final AccountService accountService) {
|
||||
setSizeFull();
|
||||
setAlignItems(Alignment.CENTER);
|
||||
setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
|
||||
final VerticalLayout vl = new VerticalLayout();
|
||||
vl.setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
vl.setWidth("400px");
|
||||
|
||||
final EmailField personalEmail = new EmailField("Personal Email");
|
||||
personalEmail.setRequired(true);
|
||||
|
||||
final EmailField confirmPersonalEmail = new EmailField("Confirm Personal Email");
|
||||
confirmPersonalEmail.setRequired(true);
|
||||
|
||||
final FormLayout formLayout = new FormLayout(personalEmail, confirmPersonalEmail);
|
||||
formLayout.setColspan(personalEmail, 3);
|
||||
formLayout.setColspan(confirmPersonalEmail, 3);
|
||||
|
||||
final Button primaryButton = new Button("Submit");
|
||||
primaryButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
primaryButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
if (personalEmail.getValue().equals(confirmPersonalEmail.getValue())) {
|
||||
accountService.sendResetPasswordEmail(personalEmail.getValue());
|
||||
getUI().ifPresent(ui -> ui.navigate(MainView.class));
|
||||
}
|
||||
});
|
||||
|
||||
final Button secondaryButton = new Button("Cancel");
|
||||
final HorizontalLayout hl = new HorizontalLayout(secondaryButton, primaryButton);
|
||||
secondaryButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
|
||||
getUI().ifPresent(ui -> ui.navigate(MainView.class)));
|
||||
|
||||
vl.add(new H3("PFS - Password Recovery"));
|
||||
vl.add(formLayout);
|
||||
vl.add(hl);
|
||||
|
||||
add(vl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEnter(final BeforeEnterEvent beforeEnterEvent) {
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Profile")
|
||||
@Route(value = "/profiles", layout = MainLayout.class)
|
||||
public class ProfileView extends Main {
|
||||
}
|
||||
|
@ -1,29 +1,27 @@
|
||||
package com.primefactorsolutions.views.assessment;
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Question;
|
||||
import com.primefactorsolutions.service.QuestionService;
|
||||
import com.primefactorsolutions.views.BaseEntityForm;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.textfield.IntegerField;
|
||||
import com.vaadin.flow.component.textfield.TextArea;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.form.BeanValidationForm;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Questions")
|
||||
@PageTitle("Assessments")
|
||||
@Route(value = "/questions", layout = MainLayout.class)
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
public class QuestionView extends BaseEntityForm<Question> implements HasUrlParameter<String> {
|
||||
@PermitAll
|
||||
public class QuestionView extends BeanValidationForm<Question> implements HasUrlParameter<String> {
|
||||
private final QuestionService questionService;
|
||||
|
||||
private TextField title = null;
|
||||
@ -31,9 +29,8 @@ public class QuestionView extends BaseEntityForm<Question> implements HasUrlPara
|
||||
private TextArea content = null;
|
||||
private IntegerField timeMinutes = null;
|
||||
|
||||
public QuestionView(final AuthenticationContext authenticationContext,
|
||||
final QuestionService questionService) {
|
||||
super(authenticationContext, Question.class);
|
||||
public QuestionView(final QuestionService questionService) {
|
||||
super(Question.class);
|
||||
this.questionService = questionService;
|
||||
title = new TextField();
|
||||
title.setWidthFull();
|
||||
@ -51,8 +48,8 @@ public class QuestionView extends BaseEntityForm<Question> implements HasUrlPara
|
||||
content.setLabel("Content");
|
||||
|
||||
setSavedHandler((SavedHandler<Question>) question -> {
|
||||
questionService.createOrUpdate(question);
|
||||
goTo(QuestionsListView.class);
|
||||
final Question saved = questionService.createOrUpdate(question);
|
||||
setEntityWithEnabledSave(saved);
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.model.Question;
|
||||
import com.primefactorsolutions.service.QuestionService;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.DataProvider;
|
||||
import com.vaadin.flow.data.provider.DataProviderListener;
|
||||
import com.vaadin.flow.data.provider.Query;
|
||||
import com.vaadin.flow.function.ValueProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.shared.Registration;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Questions")
|
||||
@Route(value = "/questions", layout = MainLayout.class)
|
||||
@PermitAll
|
||||
public class QuestionsListView extends Main {
|
||||
private final QuestionService questionService;
|
||||
|
||||
public QuestionsListView(final QuestionService questionService) {
|
||||
this.questionService = questionService;
|
||||
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
final Button addQuestion = new Button("Add Question");
|
||||
addQuestion.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
this.getUI().get().navigate(QuestionView.class, "new");
|
||||
});
|
||||
hl.add(addQuestion);
|
||||
|
||||
final VGrid<Question> grid = new VGrid<>(Question.class);
|
||||
grid.setColumns("id", "title");
|
||||
grid.addComponentColumn((ValueProvider<Question, Component>) question -> {
|
||||
final Button edit = new Button("Edit");
|
||||
edit.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
|
||||
this.getUI().get().navigate(QuestionView.class, question.getId().toString()));
|
||||
return edit;
|
||||
});
|
||||
grid.setDataProvider(new DataProvider<>() {
|
||||
@Override
|
||||
public boolean isInMemory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size(final Query<Question, Object> query) {
|
||||
return questionService.getQuestions().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Question> fetch(final Query<Question, Object> query) {
|
||||
int limit = query.getLimit();
|
||||
int pagerSize = query.getPageSize();
|
||||
int page = query.getPage();
|
||||
return questionService.getQuestions().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshItem(final Question question) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshAll() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registration addDataProviderListener(final DataProviderListener<Question> dataProviderListener) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
grid.setAllRowsVisible(true);
|
||||
|
||||
add(hl, grid);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Requests")
|
||||
@Route(value = "/requests", layout = MainLayout.class)
|
||||
@PermitAll
|
||||
public class RequestsListView extends Main {
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.primefactorsolutions.service.AccountService;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.formlayout.FormLayout;
|
||||
import com.vaadin.flow.component.html.H3;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.PasswordField;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Route("reset-password")
|
||||
@PageTitle("PFS Intra")
|
||||
@AnonymousAllowed
|
||||
public class ResetPasswordView extends VerticalLayout implements BeforeEnterObserver {
|
||||
private String username;
|
||||
private String token;
|
||||
|
||||
public ResetPasswordView(final AccountService accountService) {
|
||||
setSizeFull();
|
||||
setAlignItems(Alignment.CENTER);
|
||||
setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
|
||||
final VerticalLayout vl = new VerticalLayout();
|
||||
vl.setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
vl.setWidth("400px");
|
||||
|
||||
final PasswordField password = new PasswordField("Password");
|
||||
final PasswordField confirmPassword = new PasswordField("Confirm Password");
|
||||
|
||||
final FormLayout formLayout = new FormLayout(password, confirmPassword);
|
||||
formLayout.setColspan(password, 3);
|
||||
formLayout.setColspan(confirmPassword, 3);
|
||||
|
||||
final Button primaryButton = new Button("Submit");
|
||||
primaryButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
primaryButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
accountService.resetPassword(username, password.getValue(), token);
|
||||
getUI().ifPresent(ui -> ui.navigate(MainView.class));
|
||||
});
|
||||
|
||||
final Button secondaryButton = new Button("Cancel");
|
||||
secondaryButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
|
||||
getUI().ifPresent(ui -> ui.navigate(MainView.class)));
|
||||
|
||||
HorizontalLayout hl = new HorizontalLayout(secondaryButton, primaryButton);
|
||||
|
||||
vl.add(new H3("PFS - Reset Password"));
|
||||
vl.add(formLayout);
|
||||
vl.add(hl);
|
||||
|
||||
add(vl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEnter(final BeforeEnterEvent beforeEnterEvent) {
|
||||
final Location location = beforeEnterEvent.getLocation();
|
||||
final QueryParameters queryParameters = location.getQueryParameters();
|
||||
|
||||
this.username = queryParameters.getParameters().getOrDefault("username", List.of()).stream()
|
||||
.findFirst().orElse(null);
|
||||
this.token = queryParameters.getParameters().getOrDefault("token", List.of()).stream()
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
}
|
@ -3,9 +3,9 @@ package com.primefactorsolutions.views;
|
||||
import com.hilerio.ace.AceEditor;
|
||||
import com.hilerio.ace.AceMode;
|
||||
import com.hilerio.ace.AceTheme;
|
||||
import com.primefactorsolutions.model.Exam;
|
||||
import com.primefactorsolutions.model.Assessment;
|
||||
import com.primefactorsolutions.model.Submission;
|
||||
import com.primefactorsolutions.service.ExamService;
|
||||
import com.primefactorsolutions.service.AssessmentService;
|
||||
import com.primefactorsolutions.service.CompilerService;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
@ -20,9 +20,9 @@ import com.vaadin.flow.component.menubar.MenuBarVariant;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.*;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
@ -37,17 +37,18 @@ import java.util.stream.Collectors;
|
||||
@PageTitle("Evaluacion")
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
@Route(value = "/submissions", layout = MainLayout.class)
|
||||
@Route(value = "/submission", layout = MainLayout.class)
|
||||
@AnonymousAllowed
|
||||
@Slf4j
|
||||
public class SubmissionView extends Main implements HasUrlParameter<String> {
|
||||
|
||||
private final CompilerService compilerService;
|
||||
private final ExamService examService;
|
||||
private final AssessmentService assessmentService;
|
||||
|
||||
private AceEditor questionEditor = null;
|
||||
private AceEditor result = null;
|
||||
private Dialog dialog = null;
|
||||
private Exam exam = null;
|
||||
private Assessment assessment = null;
|
||||
private Submission currSubmission = null;
|
||||
private MenuItem prev = null;
|
||||
private MenuItem next = null;
|
||||
@ -56,9 +57,9 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
||||
private Section editorSection = null;
|
||||
private H3 questionTitle = null;
|
||||
|
||||
public SubmissionView(final CompilerService compilerService, final ExamService examService) {
|
||||
public SubmissionView(final CompilerService compilerService, final AssessmentService assessmentService) {
|
||||
this.compilerService = compilerService;
|
||||
this.examService = examService;
|
||||
this.assessmentService = assessmentService;
|
||||
|
||||
addClassNames(Display.FLEX, Flex.GROW, Height.FULL);
|
||||
|
||||
@ -130,13 +131,13 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
||||
prev = navMenuBar.addItem("Anterior pregunta",
|
||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||
log.info(">>> prev");
|
||||
this.currSubmission = this.examService.getPrevSubmission(exam.getId(),
|
||||
this.currSubmission = this.assessmentService.getPrevSubmission(assessment.getId(),
|
||||
this.currSubmission);
|
||||
updateUI();
|
||||
});
|
||||
next = navMenuBar.addItem("Siguiente pregunta",
|
||||
(ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||
this.currSubmission.setText(this.questionEditor.getValue());
|
||||
this.currSubmission.setResponse(this.questionEditor.getValue());
|
||||
goToNext();
|
||||
});
|
||||
|
||||
@ -185,7 +186,7 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
||||
|
||||
private void goToNext() {
|
||||
log.info(">>> next");
|
||||
Submission found = this.examService.getNextSubmission(exam.getId(),
|
||||
Submission found = this.assessmentService.getNextSubmission(assessment.getId(),
|
||||
this.currSubmission.getId(), false);
|
||||
|
||||
if (found != null) {
|
||||
@ -208,25 +209,25 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
if (exam == null || !exam.isStarted()) {
|
||||
if (assessment == null || !assessment.isStarted()) {
|
||||
editorSection.setVisible(false);
|
||||
sidebar.setVisible(false);
|
||||
} else {
|
||||
if (currSubmission != null) {
|
||||
questionEditor.setValue(this.currSubmission.getText());
|
||||
questionEditor.setValue(this.currSubmission.getResponse());
|
||||
questionTitle.setText(this.currSubmission.getQuestion().getTitle());
|
||||
}
|
||||
|
||||
editorSection.setVisible(true);
|
||||
sidebar.setVisible(true);
|
||||
|
||||
prev.setEnabled(currSubmission != null && !exam.isFirst(currSubmission));
|
||||
next.setEnabled(currSubmission == null || !exam.isLast(currSubmission));
|
||||
prev.setEnabled(currSubmission != null && !assessment.isFirst(currSubmission));
|
||||
next.setEnabled(currSubmission == null || !assessment.isLast(currSubmission));
|
||||
|
||||
if (dl.getChildren().collect(Collectors.toList()).isEmpty()) {
|
||||
dl.add(
|
||||
createItem("Candidato:", exam.getCandidate().getEmail()),
|
||||
createItem("Hora de inicio:", Optional.ofNullable(exam.getStartingTime())
|
||||
createItem("Candidato:", assessment.getCandidate().getEmail()),
|
||||
createItem("Hora de inicio:", Optional.ofNullable(assessment.getStartingTime())
|
||||
.map(t -> ZonedDateTime.ofInstant(t,
|
||||
ZoneId.of("GMT-4")).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
|
||||
.orElse("N/A"))
|
||||
@ -258,14 +259,14 @@ public class SubmissionView extends Main implements HasUrlParameter<String> {
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||
this.exam = this.examService.getExam(UUID.fromString(s));
|
||||
this.assessment = this.assessmentService.getAssessment(UUID.fromString(s));
|
||||
|
||||
if (this.exam == null) {
|
||||
if (this.assessment == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
this.currSubmission = this.exam.isStarted()
|
||||
? this.examService.getNextSubmission(exam.getId(), null, false)
|
||||
this.currSubmission = this.assessment.isStarted()
|
||||
? this.assessmentService.getNextSubmission(assessment.getId(), null, false)
|
||||
: null;
|
||||
|
||||
updateUI();
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Timeoff")
|
||||
@Route(value = "/timeoffs/me", layout = MainLayout.class)
|
||||
public class TimeoffView extends Main {
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Timesheets")
|
||||
@Route(value = "/timesheets", layout = MainLayout.class)
|
||||
@PermitAll
|
||||
public class TimesheestReportView extends Main {
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.primefactorsolutions.views;
|
||||
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Timesheet")
|
||||
@Route(value = "/timesheets/me", layout = MainLayout.class)
|
||||
public class TimesheetView extends Main {
|
||||
}
|
||||
|
@ -1,135 +0,0 @@
|
||||
package com.primefactorsolutions.views.admin;
|
||||
|
||||
import com.primefactorsolutions.model.*;
|
||||
import com.primefactorsolutions.service.TimeOffService;
|
||||
import com.primefactorsolutions.views.BaseView;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.primefactorsolutions.views.util.MenuBarUtils;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.contextmenu.MenuItem;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.menubar.MenuBar;
|
||||
import com.vaadin.flow.component.menubar.MenuBarVariant;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.ListDataProvider;
|
||||
import com.vaadin.flow.function.ValueProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Registro de Vacaciones")
|
||||
@Route(value = "/time-off/list", layout = MainLayout.class)
|
||||
public class TimeOffListView extends BaseView {
|
||||
|
||||
private final TimeOffService timeOffService;
|
||||
private final VGrid<TimeOff> timeOffGrid = new VGrid<>();
|
||||
private ComboBox<Integer> yearFilter;
|
||||
|
||||
public TimeOffListView(final AuthenticationContext authenticationContext,
|
||||
final TimeOffService timeOffService) {
|
||||
super(authenticationContext);
|
||||
this.timeOffService = timeOffService;
|
||||
|
||||
initializeView();
|
||||
}
|
||||
|
||||
private void refreshGridListHoursWorked(final Integer year) {
|
||||
final List<TimeOff> timeOffs = timeOffService.findTimeOffs(year);
|
||||
timeOffGrid.setDataProvider(new ListDataProvider<>(timeOffs));
|
||||
timeOffGrid.getDataProvider().refreshAll();
|
||||
}
|
||||
|
||||
private void initializeView() {
|
||||
getCurrentPageLayout().add(createAddTimeOff());
|
||||
setupFilters();
|
||||
setupListHoursWorkedGrid();
|
||||
getCurrentPageLayout().add(timeOffGrid);
|
||||
refreshGridListHoursWorked(yearFilter.getValue());
|
||||
}
|
||||
|
||||
private void setupFilters() {
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
hl.add(createYearFilter());
|
||||
getCurrentPageLayout().add(hl);
|
||||
}
|
||||
|
||||
private ComboBox<Integer> createYearFilter() {
|
||||
yearFilter = new ComboBox<>("Year");
|
||||
final int nowYear = LocalDate.now().getYear();
|
||||
final List<Integer> years = IntStream.range(0, 2).mapToObj(y -> nowYear - y).toList();
|
||||
|
||||
yearFilter.setItems(years);
|
||||
yearFilter.setValue(years.getFirst());
|
||||
yearFilter.addValueChangeListener(event ->
|
||||
refreshGridListHoursWorked(event.getValue())
|
||||
);
|
||||
|
||||
return yearFilter;
|
||||
}
|
||||
|
||||
private void setupListHoursWorkedGrid() {
|
||||
timeOffGrid.addColumn(e -> e.getCategory().name())
|
||||
.setHeader("Categoria");
|
||||
timeOffGrid.addColumn(e -> e.getType().name())
|
||||
.setHeader("Tipo");
|
||||
timeOffGrid.addColumn(TimeOff::getDate)
|
||||
.setHeader("Fecha");
|
||||
timeOffGrid.addColumn(TimeOff::getDuration).setHeader("Duracion");
|
||||
timeOffGrid.addColumn(TimeOff::getExpiration).setHeader("Expiracion");
|
||||
timeOffGrid.addComponentColumn((ValueProvider<TimeOff, Component>) timeOff -> {
|
||||
final MenuBar menuBar = new MenuBar();
|
||||
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
|
||||
final MenuItem viewItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.EYE, "Ver");
|
||||
viewItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||
navigateToTimeOffView(timeOff.getId(), "view");
|
||||
});
|
||||
final MenuItem editItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.PENCIL, "Editar");
|
||||
editItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent -> {
|
||||
navigateToTimeOffView(timeOff.getId(), "edit");
|
||||
});
|
||||
return menuBar;
|
||||
});
|
||||
}
|
||||
|
||||
private void navigateToTimeOffView(final UUID idRecord, final String action) {
|
||||
getUI().ifPresent(ui -> ui.navigate(TimeOffView.class, idRecord.toString() + "/" + action));
|
||||
}
|
||||
|
||||
private Button createButton(final String label, final Runnable onClickAction, final boolean isPrimary) {
|
||||
final Button button = new Button(label);
|
||||
|
||||
if (isPrimary) {
|
||||
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
}
|
||||
|
||||
button.addClickListener(event -> onClickAction.run());
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private Button createAddTimeOff() {
|
||||
return createButton("Agregar Vacacion", this::navigateToTimeOff, true);
|
||||
}
|
||||
|
||||
private void navigateToTimeOff() {
|
||||
getUI().ifPresent(ui -> ui.navigate(TimeOffView.class, "new"));
|
||||
}
|
||||
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package com.primefactorsolutions.views.admin;
|
||||
|
||||
import com.primefactorsolutions.model.TimeOff;
|
||||
import com.primefactorsolutions.model.TimeOffRequestType;
|
||||
import com.primefactorsolutions.service.TimeOffService;
|
||||
import com.primefactorsolutions.views.BaseEntityForm;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.textfield.NumberField;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.datepicker.VDatePicker;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.YearMonth;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Vacaciones")
|
||||
@Route(value = "/time-off/:hours-workedId?/:action?", layout = MainLayout.class)
|
||||
public class TimeOffView extends BaseEntityForm<TimeOff> implements HasUrlParameter<String> {
|
||||
private final ComboBox<TimeOffRequestType> category = new ComboBox<>("Categoria");
|
||||
private final ComboBox<TimeOff.Type> type = new ComboBox<>("Tipo");
|
||||
private final VDatePicker date = new VDatePicker("Fecha");
|
||||
private final NumberField duration = new NumberField("Duracion");
|
||||
private final NumberField expiration = new NumberField("Expiracion");
|
||||
|
||||
private final TimeOffService timeOffService;
|
||||
|
||||
public TimeOffView(final AuthenticationContext authenticationContext,
|
||||
final TimeOffService timeOffService) {
|
||||
super(authenticationContext, TimeOff.class);
|
||||
this.timeOffService = timeOffService;
|
||||
|
||||
initializeDateField();
|
||||
category.setItems(TimeOffRequestType.values());
|
||||
type.setItems(TimeOff.Type.values());
|
||||
|
||||
this.setSavedHandler(this::saveTimeOff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String action) {
|
||||
final RouteParameters params = beforeEvent.getRouteParameters();
|
||||
final String s = params.get("hours-workedId").orElse(null);
|
||||
|
||||
if ("new".equals(action) || s == null) {
|
||||
setEntityWithEnabledSave(new TimeOff());
|
||||
} else {
|
||||
final UUID timeOffId = UUID.fromString(s);
|
||||
final TimeOff timeOff = timeOffService.getTimeOff(timeOffId);
|
||||
|
||||
if ("edit".equals(action) && !s.isEmpty()) {
|
||||
setEntityWithEnabledSave(timeOff);
|
||||
} else if ("view".equals(action) && !s.isEmpty()) {
|
||||
setEntity(timeOff);
|
||||
duration.setReadOnly(true);
|
||||
expiration.setReadOnly(true);
|
||||
category.setReadOnly(true);
|
||||
type.setReadOnly(true);
|
||||
date.setReadOnly(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Component> getFormComponents() {
|
||||
return List.of(
|
||||
category,
|
||||
type,
|
||||
date,
|
||||
duration,
|
||||
expiration
|
||||
);
|
||||
}
|
||||
|
||||
private void initializeDateField() {
|
||||
final LocalDate today = LocalDate.now();
|
||||
final YearMonth currentMonth = YearMonth.of(today.getYear(), today.getMonth());
|
||||
final LocalDate startOfMonth = currentMonth.atDay(1);
|
||||
|
||||
date.setWidthFull();
|
||||
date.setMin(startOfMonth);
|
||||
date.setMax(today);
|
||||
date.setValue(today);
|
||||
}
|
||||
|
||||
private void saveTimeOff(final TimeOff timeOff) {
|
||||
if (isFormValid()) {
|
||||
timeOffService.saveTimeOff(timeOff);
|
||||
closeForm();
|
||||
}
|
||||
}
|
||||
|
||||
private void closeForm() {
|
||||
getUI().ifPresent(ui -> ui.navigate(TimeOffListView.class));
|
||||
}
|
||||
|
||||
private boolean isFormValid() {
|
||||
return date.getValue() != null;
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
package com.primefactorsolutions.views.assessment;
|
||||
|
||||
import com.primefactorsolutions.model.Candidate;
|
||||
import com.primefactorsolutions.service.CandidateService;
|
||||
import com.primefactorsolutions.views.BaseView;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.primefactorsolutions.views.util.MenuBarUtils;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.ListDataProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Candidates")
|
||||
@Route(value = "/candidates", layout = MainLayout.class)
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
public class CandidatesListView extends BaseView {
|
||||
|
||||
public CandidatesListView(final AuthenticationContext authenticationContext,
|
||||
final CandidateService candidateService) {
|
||||
super(authenticationContext);
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
final Button addCandidate = new Button("Add Candidate");
|
||||
addCandidate.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
addCandidate.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
this.getUI().flatMap(ui -> ui.navigate(CandidateView.class, "new"));
|
||||
});
|
||||
hl.add(addCandidate);
|
||||
|
||||
final VGrid<Candidate> grid = new VGrid<>(Candidate.class);
|
||||
grid.setColumns("email");
|
||||
grid.setAllRowsVisible(true);
|
||||
grid.addComponentColumn(candidate ->
|
||||
MenuBarUtils.menuBar(Map.of(Pair.of("Edit", VaadinIcon.PENCIL), menuItemClickEvent ->
|
||||
getUI().flatMap(ui -> ui.navigate(CandidateView.class, candidate.getId().toString())))));
|
||||
grid.setDataProvider(new ListDataProvider<>(candidateService.getCandidates()));
|
||||
|
||||
getCurrentPageLayout().add(hl, grid);
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package com.primefactorsolutions.views.assessment;
|
||||
|
||||
import com.primefactorsolutions.model.*;
|
||||
import com.primefactorsolutions.service.CandidateService;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.primefactorsolutions.service.EvaluationService;
|
||||
import com.primefactorsolutions.views.BaseEntityForm;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.primefactorsolutions.views.util.EntityComboBox;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.Text;
|
||||
import com.vaadin.flow.component.textfield.IntegerField;
|
||||
import com.vaadin.flow.router.BeforeEvent;
|
||||
import com.vaadin.flow.router.HasUrlParameter;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.fields.ElementCollectionField;
|
||||
import org.vaadin.firitin.fields.EnumSelect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Evaluations")
|
||||
@Route(value = "/evaluations", layout = MainLayout.class)
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
public class EvaluationView extends BaseEntityForm<Evaluation> implements HasUrlParameter<String> {
|
||||
private final CandidateService candidateService;
|
||||
private final EvaluationService evaluationService;
|
||||
private final EmployeeService employeeService;
|
||||
|
||||
private final EntityComboBox<Candidate> candidate = new EntityComboBox<>("Candidate");
|
||||
private final EntityComboBox<Employee> interviewer = new EntityComboBox<>("Interviewer");
|
||||
private final EnumSelect<EmployeePosition> candidatePosition =
|
||||
new EnumSelect<>("Position", EmployeePosition.class);
|
||||
private final IntegerField points = new IntegerField("Points");
|
||||
private final Text skillLabel = new Text("Skills");
|
||||
private final ElementCollectionField<SkillEvaluation> skillEvaluations =
|
||||
new ElementCollectionField<>(SkillEvaluation.class);
|
||||
|
||||
public EvaluationView(final AuthenticationContext authenticationContext,
|
||||
final CandidateService candidateService,
|
||||
final EmployeeService employeeService,
|
||||
final EvaluationService evaluationService) {
|
||||
super(authenticationContext, Evaluation.class);
|
||||
this.employeeService = employeeService;
|
||||
this.evaluationService = evaluationService;
|
||||
this.candidateService = candidateService;
|
||||
|
||||
this.candidate.setWidthFull();
|
||||
this.interviewer.setWidthFull();
|
||||
this.points.setWidthFull();
|
||||
this.skillEvaluations.setWidthFull();
|
||||
this.candidatePosition.setWidthFull();
|
||||
this.candidate.setItems(this.candidateService.getCandidates());
|
||||
this.interviewer.setItems(this.employeeService.getEmployees());
|
||||
|
||||
setSavedHandler(evaluation -> goTo(EvaluationsListView.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String s) {
|
||||
if (StringUtils.isNotBlank(s) && !"new".equals(s)) {
|
||||
var evaluation = evaluationService.getEvaluation(UUID.fromString(s));
|
||||
setEntityWithEnabledSave(evaluation);
|
||||
} else {
|
||||
setEntityWithEnabledSave(new Evaluation());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Component> getFormComponents() {
|
||||
return List.of(
|
||||
candidate,
|
||||
points,
|
||||
candidatePosition,
|
||||
skillLabel,
|
||||
skillEvaluations,
|
||||
interviewer
|
||||
);
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package com.primefactorsolutions.views.assessment;
|
||||
|
||||
import com.primefactorsolutions.model.Evaluation;
|
||||
import com.primefactorsolutions.service.EvaluationService;
|
||||
import com.primefactorsolutions.views.BaseView;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.primefactorsolutions.views.util.MenuBarUtils;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.ListDataProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Evaluations")
|
||||
@Route(value = "/evaluations", layout = MainLayout.class)
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
public class EvaluationsListView extends BaseView {
|
||||
|
||||
public EvaluationsListView(final AuthenticationContext authenticationContext,
|
||||
final EvaluationService evaluationService) {
|
||||
super(authenticationContext);
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
final Button addEvaluation = new Button("Add Evaluation");
|
||||
addEvaluation.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
addEvaluation.addClickListener(buttonClickEvent -> {
|
||||
this.getUI().flatMap(ui -> ui.navigate(EvaluationView.class, "new"));
|
||||
});
|
||||
hl.add(addEvaluation);
|
||||
|
||||
final VGrid<Evaluation> grid = new VGrid<>(Evaluation.class);
|
||||
grid.setColumns("candidate.email");
|
||||
grid.setAllRowsVisible(true);
|
||||
grid.addComponentColumn(evaluation ->
|
||||
MenuBarUtils.menuBar(Map.of(Pair.of("Edit", VaadinIcon.PENCIL), menuItemClickEvent ->
|
||||
getUI().flatMap(ui -> ui.navigate(EvaluationView.class, evaluation.getId().toString())))));
|
||||
grid.setDataProvider(new ListDataProvider<>(evaluationService.getEvaluations()));
|
||||
|
||||
getCurrentPageLayout().add(hl, grid);
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package com.primefactorsolutions.views.assessment;
|
||||
|
||||
import com.primefactorsolutions.model.Exam;
|
||||
import com.primefactorsolutions.service.ExamService;
|
||||
import com.primefactorsolutions.views.BaseView;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.primefactorsolutions.views.SubmissionView;
|
||||
import com.primefactorsolutions.views.util.MenuBarUtils;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.ListDataProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.addon.stefan.clipboard.ClientsideClipboard;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Exams")
|
||||
@Route(value = "/exams", layout = MainLayout.class)
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
public class ExamsListView extends BaseView {
|
||||
|
||||
public ExamsListView(final AuthenticationContext authenticationContext,
|
||||
final ExamService examService) {
|
||||
super(authenticationContext);
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
final Button addExam = new Button("Add Exam");
|
||||
addExam.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
addExam.addClickListener(buttonClickEvent ->
|
||||
getUI().flatMap(ui -> ui.navigate(ExamView.class, "new")));
|
||||
hl.add(addExam);
|
||||
|
||||
final VGrid<Exam> grid = new VGrid<>(Exam.class);
|
||||
grid.setColumns("id", "candidate.email");
|
||||
final Grid.Column<Exam> statusColumn = grid.addColumn(exam ->
|
||||
exam.getExamEvents().isEmpty()
|
||||
? "N/A"
|
||||
: exam.getExamEvents().getLast().getStatus().name());
|
||||
statusColumn.setHeader("Status");
|
||||
|
||||
grid.addComponentColumn(exam -> MenuBarUtils.menuBar(
|
||||
Pair.of("View", __ ->
|
||||
getUI().flatMap(ui -> ui.navigate(SubmissionView.class, exam.getId().toString()))),
|
||||
Pair.of("Copy", __ ->
|
||||
ClientsideClipboard.writeToClipboard(
|
||||
String.format("email: %s link: "
|
||||
+ "https://intra.primefactorsolutions.com/candidate-exam/%s",
|
||||
exam.getCandidate().getEmail(),
|
||||
exam.getId()))),
|
||||
Pair.of("Email", __ -> {
|
||||
ConfirmDialog dialog = new ConfirmDialog();
|
||||
dialog.setHeader("Send Link Email");
|
||||
dialog.setText(String.format("Enviar link por email al candidato %s?",
|
||||
exam.getCandidate().getEmail()));
|
||||
dialog.setCancelable(true);
|
||||
dialog.setConfirmText("Enviar");
|
||||
dialog.setConfirmButtonTheme("primary");
|
||||
dialog.addConfirmListener(confirmEvent -> {
|
||||
try {
|
||||
examService.sendEmail(exam);
|
||||
} catch (Exception e) {
|
||||
Notification.show("Error sending email: " + e.getMessage(), 10_000,
|
||||
Notification.Position.TOP_CENTER);
|
||||
}
|
||||
});
|
||||
dialog.open();
|
||||
})
|
||||
));
|
||||
|
||||
grid.setDataProvider(new ListDataProvider<>(examService.getExams()));
|
||||
grid.setAllRowsVisible(true);
|
||||
|
||||
getCurrentPageLayout().add(hl, grid);
|
||||
}
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package com.primefactorsolutions.views.assessment;
|
||||
|
||||
import com.primefactorsolutions.model.Question;
|
||||
import com.primefactorsolutions.service.QuestionService;
|
||||
import com.primefactorsolutions.views.BaseView;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.primefactorsolutions.views.util.MenuBarUtils;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.ListDataProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.grid.VGrid;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Questions")
|
||||
@Route(value = "/questions", layout = MainLayout.class)
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
public class QuestionsListView extends BaseView {
|
||||
|
||||
public QuestionsListView(final AuthenticationContext authenticationContext, final QuestionService questionService) {
|
||||
super(authenticationContext);
|
||||
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
final Button addQuestion = new Button("Add Question");
|
||||
addQuestion.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
addQuestion.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent ->
|
||||
this.getUI().flatMap(ui -> ui.navigate(QuestionView.class, "new")));
|
||||
hl.add(addQuestion);
|
||||
|
||||
final VGrid<Question> grid = new VGrid<>(Question.class);
|
||||
grid.setColumns("title", "description", "timeMinutes");
|
||||
grid.addComponentColumn(question ->
|
||||
MenuBarUtils.menuBar(Pair.of("Edit", __ ->
|
||||
getUI().flatMap(ui -> ui.navigate(QuestionView.class, question.getId().toString())))));
|
||||
grid.setDataProvider(new ListDataProvider<>(questionService.getQuestions()));
|
||||
grid.setAllRowsVisible(true);
|
||||
|
||||
getCurrentPageLayout().add(hl, grid);
|
||||
}
|
||||
}
|
@ -1,229 +0,0 @@
|
||||
package com.primefactorsolutions.views.employee;
|
||||
|
||||
import com.primefactorsolutions.model.Document;
|
||||
import com.primefactorsolutions.model.DocumentType;
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.service.DocumentService;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.primefactorsolutions.views.BaseEntityForm;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.component.upload.Upload;
|
||||
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.server.StreamRegistration;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import elemental.json.Json;
|
||||
import elemental.json.JsonArray;
|
||||
import elemental.json.JsonObject;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.io.InputStream;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Document")
|
||||
@Route(value = "/documents/:documentId?/:action?", layout = MainLayout.class)
|
||||
public class DocumentView extends BaseEntityForm<Document> implements HasUrlParameter<String> {
|
||||
private final TextField fileName = new TextField("Nombre del documento");
|
||||
private final ComboBox<DocumentType> documentType = new ComboBox<>("Tipo de documento");
|
||||
private final ComboBox<Employee> employeeComboBox = new ComboBox<>("Empleado");
|
||||
private final Span pdfOnlyMessage = new Span("Únicamente se permite la carga de archivos en formato PDF.");
|
||||
private final MemoryBuffer buffer = new MemoryBuffer();
|
||||
private final Upload uploadButton = new Upload(buffer);
|
||||
private final DocumentService documentService;
|
||||
private final EmployeeService employeeService;
|
||||
private final AuthenticationContext authContext;
|
||||
private boolean fileUploaded = false;
|
||||
private Button viewDocumentButton;
|
||||
|
||||
public DocumentView(final AuthenticationContext authenticationContext,
|
||||
final DocumentService documentService,
|
||||
final EmployeeService employeeService,
|
||||
final AuthenticationContext authContext) {
|
||||
super(authenticationContext, Document.class);
|
||||
this.documentService = documentService;
|
||||
this.employeeService = employeeService;
|
||||
this.authContext = authContext;
|
||||
initializeView();
|
||||
this.setSavedHandler(this::saveDocument);
|
||||
}
|
||||
|
||||
private void initializeView() {
|
||||
configureComponents();
|
||||
configureUploadButton();
|
||||
}
|
||||
|
||||
protected Button createViewDocumentButton() {
|
||||
viewDocumentButton = new Button("Ver documento");
|
||||
viewDocumentButton.setEnabled(false);
|
||||
viewDocumentButton.addClickListener(event -> viewDocument());
|
||||
return viewDocumentButton;
|
||||
}
|
||||
|
||||
private void setFileNameProperties() {
|
||||
fileName.setWidthFull();
|
||||
}
|
||||
|
||||
private void setDocumentTypeProperties() {
|
||||
documentType.setItems(DocumentType.values());
|
||||
documentType.setWidthFull();
|
||||
}
|
||||
|
||||
private void setEmployeeComboBoxProperties() {
|
||||
List<Employee> employees = employeeService.findAllEmployees();
|
||||
employeeComboBox.setItems(employees);
|
||||
employeeComboBox.setItemLabelGenerator(employee -> employee.getFirstName() + " " + employee.getLastName());
|
||||
employeeComboBox.setWidthFull();
|
||||
}
|
||||
|
||||
private void setDocumentCreator(final Document document) {
|
||||
authContext.getAuthenticatedUser(UserDetails.class).ifPresent(user -> {
|
||||
document.setCreator(user.getUsername());
|
||||
});
|
||||
}
|
||||
|
||||
private void setFieldsReadOnly(final boolean option) {
|
||||
fileName.setReadOnly(option);
|
||||
documentType.setReadOnly(option);
|
||||
employeeComboBox.setReadOnly(option);
|
||||
}
|
||||
|
||||
private void viewDocument() {
|
||||
StreamResource resource;
|
||||
try {
|
||||
InputStream inputStream = buffer.getInputStream();
|
||||
if (inputStream != null && inputStream.available() > 0) {
|
||||
resource = new StreamResource(fileName.getValue(), () -> new ByteArrayInputStream(readFileData()));
|
||||
} else {
|
||||
byte[] fileData = getEntity().getFileData();
|
||||
resource = new StreamResource(fileName.getValue(), () -> new ByteArrayInputStream(fileData));
|
||||
}
|
||||
resource.setContentType("application/pdf");
|
||||
getUI().ifPresent(ui -> {
|
||||
StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource);
|
||||
ui.getPage().open(registration.getResourceUri().toString());
|
||||
});
|
||||
} catch (IOException e) {
|
||||
Notification.show("Error al leer el archivo.");
|
||||
}
|
||||
}
|
||||
|
||||
private void saveDocument(final Document document) {
|
||||
if (isFormValid()) {
|
||||
document.setFileName(fileName.getValue());
|
||||
document.setDocumentType(documentType.getValue());
|
||||
document.setEmployee(employeeComboBox.getValue());
|
||||
document.setFileData(readFileData());
|
||||
setDocumentCreator(document);
|
||||
|
||||
documentService.saveDocument(document);
|
||||
getUI().ifPresent(ui -> ui.navigate(DocumentsListView.class));
|
||||
} else {
|
||||
Notification.show("Error al guardar: Por favor, complete todos los campos y cargue un archivo.");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFormValid() {
|
||||
return !fileName.isEmpty()
|
||||
&& documentType.getValue() != null
|
||||
&& employeeComboBox.getValue() != null
|
||||
&& fileUploaded;
|
||||
}
|
||||
|
||||
private byte[] readFileData() {
|
||||
try {
|
||||
return buffer.getInputStream().readAllBytes();
|
||||
} catch (IOException e) {
|
||||
Notification.show("Error al leer los datos del archivo.");
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
private void preLoadFile(final Document document) {
|
||||
JsonArray jsonArray = Json.createArray();
|
||||
JsonObject jsonObject = Json.createObject();
|
||||
jsonObject.put("name", document.getFileName());
|
||||
jsonObject.put("progress", 100);
|
||||
jsonObject.put("complete", true);
|
||||
jsonObject.put("fileData", Base64.getEncoder().encodeToString(document.getFileData()));
|
||||
jsonArray.set(0, jsonObject);
|
||||
uploadButton.getElement().setPropertyJson("files", jsonArray);
|
||||
fileUploaded = true;
|
||||
}
|
||||
|
||||
private void configureComponents() {
|
||||
setFileNameProperties();
|
||||
setDocumentTypeProperties();
|
||||
setEmployeeComboBoxProperties();
|
||||
}
|
||||
|
||||
private void configureUploadButton() {
|
||||
uploadButton.setMaxFiles(1);
|
||||
uploadButton.setAcceptedFileTypes(".pdf");
|
||||
uploadButton.addSucceededListener(event -> {
|
||||
fileUploaded = true;
|
||||
Notification.show("Archivo cargado correctamente.");
|
||||
viewDocumentButton.setEnabled(true);
|
||||
});
|
||||
uploadButton.getElement().addEventListener("file-remove", event -> {
|
||||
fileUploaded = false;
|
||||
Notification.show("Archivo eliminado.");
|
||||
viewDocumentButton.setEnabled(false);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String action) {
|
||||
final RouteParameters params = beforeEvent.getRouteParameters();
|
||||
final String documentIdString = params.get("documentId").orElse(null);
|
||||
|
||||
if ("new".equals(action)) {
|
||||
setEntityWithEnabledSave(new Document());
|
||||
} else {
|
||||
assert documentIdString != null;
|
||||
UUID documentId = UUID.fromString(documentIdString);
|
||||
Document document = documentService.getDocument(documentId);
|
||||
|
||||
employeeComboBox.setValue(document.getEmployee());
|
||||
preLoadFile(document);
|
||||
|
||||
if ("edit".equals(action) && !documentIdString.isEmpty()) {
|
||||
setEntityWithEnabledSave(document);
|
||||
setFieldsReadOnly(false);
|
||||
preLoadFile(document);
|
||||
viewDocumentButton.setEnabled(true);
|
||||
} else if ("view".equals(action) && !documentIdString.isEmpty()) {
|
||||
setEntity(document);
|
||||
setFieldsReadOnly(true);
|
||||
preLoadFile(document);
|
||||
viewDocumentButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Component> getFormComponents() {
|
||||
final HorizontalLayout buttonLayout = new HorizontalLayout();
|
||||
buttonLayout.add(uploadButton, createViewDocumentButton());
|
||||
buttonLayout.setSpacing(true);
|
||||
|
||||
return List.of(documentType, fileName, employeeComboBox, pdfOnlyMessage, buttonLayout);
|
||||
}
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
package com.primefactorsolutions.views.employee;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.primefactorsolutions.model.Document;
|
||||
import com.primefactorsolutions.model.DocumentType;
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.service.DocumentService;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.primefactorsolutions.views.BaseView;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.primefactorsolutions.views.util.MenuBarUtils;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.UI;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.contextmenu.MenuItem;
|
||||
import com.vaadin.flow.component.grid.GridSortOrder;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.menubar.MenuBar;
|
||||
import com.vaadin.flow.component.menubar.MenuBarVariant;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.provider.SortDirection;
|
||||
import com.vaadin.flow.function.ValueProvider;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.StreamRegistration;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.grid.PagingGrid;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.List;
|
||||
|
||||
import static com.primefactorsolutions.views.Constants.PAGE_SIZE;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Documents")
|
||||
@Route(value = "/documents", layout = MainLayout.class)
|
||||
@PermitAll
|
||||
public class DocumentsListView extends BaseView {
|
||||
|
||||
private final DocumentService documentService;
|
||||
private final EmployeeService employeeService;
|
||||
private final PagingGrid<Document> documentGrid = new PagingGrid<>(Document.class);
|
||||
private ComboBox<Employee> employeeFilter;
|
||||
private ComboBox<DocumentType> documentTypeFilter;
|
||||
|
||||
public DocumentsListView(final AuthenticationContext authenticationContext,
|
||||
final DocumentService documentService,
|
||||
final EmployeeService employeeService) {
|
||||
super(authenticationContext);
|
||||
this.documentService = documentService;
|
||||
this.employeeService = employeeService;
|
||||
initializeView();
|
||||
updateDocumentGrid(null, null);
|
||||
}
|
||||
|
||||
private void initializeView() {
|
||||
getCurrentPageLayout().add(createActionButton("Añadir documento", this::navigateToAddDocumentView, true));
|
||||
|
||||
final HorizontalLayout hl = new HorizontalLayout();
|
||||
hl.add(createDocumentTypeFilter());
|
||||
hl.add(createEmployeeFilter());
|
||||
|
||||
getCurrentPageLayout().add(hl);
|
||||
|
||||
configureDocumentGrid();
|
||||
getCurrentPageLayout().add(documentGrid);
|
||||
}
|
||||
|
||||
private void configureDocumentGrid() {
|
||||
documentGrid.setColumns("fileName", "documentType", "creator");
|
||||
documentGrid.getColumnByKey("fileName").setHeader("Nombre archivo");
|
||||
documentGrid.getColumnByKey("documentType").setHeader("Tipo");
|
||||
documentGrid.getColumnByKey("creator").setHeader("Creador");
|
||||
documentGrid.addComponentColumn(this::createEmployeeSpan).setHeader("Empleado");
|
||||
addActionColumns();
|
||||
configurePagination();
|
||||
}
|
||||
|
||||
private Span createEmployeeSpan(final Document document) {
|
||||
Employee employee = document.getEmployee();
|
||||
String employeeName = employee.getFirstName() + " " + employee.getLastName();
|
||||
return new Span(employeeName);
|
||||
}
|
||||
|
||||
private void addActionColumns() {
|
||||
documentGrid.addComponentColumn((ValueProvider<Document, Component>) document -> {
|
||||
final MenuBar menuBar = new MenuBar();
|
||||
menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
|
||||
final MenuItem viewItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.EYE, "Ver");
|
||||
viewItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
|
||||
navigateToDocumentView(document));
|
||||
final MenuItem editItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.PENCIL, "Editar");
|
||||
editItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
|
||||
navigateToEditDocumentView(document));
|
||||
final MenuItem downloadItem = MenuBarUtils.createIconItem(menuBar, VaadinIcon.DOWNLOAD, "Descargar");
|
||||
downloadItem.addClickListener((ComponentEventListener<ClickEvent<MenuItem>>) menuItemClickEvent ->
|
||||
downloadDocument(document));
|
||||
return menuBar;
|
||||
});
|
||||
}
|
||||
|
||||
private Button createActionButton(final String label, final Runnable onClickAction, final boolean isPrimary) {
|
||||
Button actionButton = new Button(label);
|
||||
|
||||
if (isPrimary) {
|
||||
actionButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
}
|
||||
|
||||
actionButton.addClickListener(event -> onClickAction.run());
|
||||
return actionButton;
|
||||
}
|
||||
|
||||
private ComboBox<DocumentType> createDocumentTypeFilter() {
|
||||
documentTypeFilter = new ComboBox<>("Tipo de documento");
|
||||
documentTypeFilter.setClearButtonVisible(true);
|
||||
documentTypeFilter.setPlaceholder("Seleccionar ...");
|
||||
documentTypeFilter.setItems(DocumentType.values());
|
||||
documentTypeFilter.addValueChangeListener(event -> {
|
||||
updateDocumentGrid(event.getValue(), employeeFilter.getValue());
|
||||
});
|
||||
return documentTypeFilter;
|
||||
}
|
||||
|
||||
private ComboBox<Employee> createEmployeeFilter() {
|
||||
employeeFilter = new ComboBox<>("Empleado");
|
||||
employeeFilter.setPlaceholder("Seleccionar ...");
|
||||
employeeFilter.setClearButtonVisible(true);
|
||||
|
||||
final List<Employee> employees;
|
||||
|
||||
if (isRoleAdmin()) {
|
||||
employees = employeeService.findAllEmployees();
|
||||
employeeFilter.setItems(employees);
|
||||
} else {
|
||||
Employee employee = employeeService.getEmployee(getEmployeeId().get());
|
||||
employees = Lists.newArrayList(employee);
|
||||
employeeFilter.setItems(employees);
|
||||
employeeFilter.setValue(employees.getFirst());
|
||||
employeeFilter.setReadOnly(true);
|
||||
}
|
||||
|
||||
employeeFilter.setItemLabelGenerator(this::getEmployeeLabel);
|
||||
employeeFilter.addValueChangeListener(event -> {
|
||||
updateDocumentGrid(documentTypeFilter.getValue(), event.getValue());
|
||||
});
|
||||
return employeeFilter;
|
||||
}
|
||||
|
||||
private String getEmployeeLabel(final Employee employee) {
|
||||
return employee.getFirstName() + " " + employee.getLastName();
|
||||
}
|
||||
|
||||
private void navigateToEditDocumentView(final Document document) {
|
||||
navigateToDocumentView(document, "edit");
|
||||
}
|
||||
|
||||
private void navigateToDocumentView(final Document document) {
|
||||
navigateToDocumentView(document, "view");
|
||||
}
|
||||
|
||||
private void navigateToDocumentView(final Document document, final String action) {
|
||||
getUI().ifPresent(ui -> ui.navigate(DocumentView.class, document.getId().toString() + "/" + action));
|
||||
}
|
||||
|
||||
private void navigateToAddDocumentView() {
|
||||
getUI().ifPresent(ui -> ui.navigate(DocumentView.class, "new"));
|
||||
}
|
||||
|
||||
private void configurePagination() {
|
||||
documentGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
||||
documentGrid.setPageSize(PAGE_SIZE);
|
||||
}
|
||||
|
||||
private void updateDocumentGrid(final DocumentType documentType, final Employee employee) {
|
||||
DocumentType finalDocumentType = isValidDocumentType(documentType) ? documentType : null;
|
||||
Employee finalEmployee = isValidEmployee(employee) ? employee : null;
|
||||
documentGrid.setPagingDataProvider((page, pageSize) ->
|
||||
(finalDocumentType == null && finalEmployee == null)
|
||||
? fetchDocuments((int) page, pageSize)
|
||||
: fetchFilteredDocuments((int) page, pageSize, finalDocumentType, finalEmployee)
|
||||
);
|
||||
documentGrid.getDataProvider().refreshAll();
|
||||
}
|
||||
|
||||
private boolean isValidDocumentType(final DocumentType documentType) {
|
||||
return documentType != null && !"All".equals(documentType.name());
|
||||
}
|
||||
|
||||
private boolean isValidEmployee(final Employee employee) {
|
||||
return employee != null && !"All".equals(employee.getFirstName());
|
||||
}
|
||||
|
||||
private List<Document> fetchFilteredDocuments(final int page,
|
||||
final int pageSize,
|
||||
final DocumentType documentType,
|
||||
final Employee employee) {
|
||||
return documentService.findDocumentBy(documentType, employee, page, pageSize);
|
||||
}
|
||||
|
||||
private List<Document> fetchDocuments(final int page, final int size) {
|
||||
int startIndex = page * size;
|
||||
return isSortOrderPresent()
|
||||
? fetchSortedDocuments(startIndex, size)
|
||||
: documentService.findDocuments(startIndex, size);
|
||||
}
|
||||
|
||||
private boolean isSortOrderPresent() {
|
||||
return !documentGrid.getSortOrder().isEmpty();
|
||||
}
|
||||
|
||||
private List<Document> fetchSortedDocuments(final int start, final int pageSize) {
|
||||
GridSortOrder<Document> sortOrder = documentGrid.getSortOrder().getFirst();
|
||||
return documentService.findDocuments(start, pageSize,
|
||||
sortOrder.getSorted().getKey(),
|
||||
sortOrder.getDirection() == SortDirection.ASCENDING);
|
||||
}
|
||||
|
||||
private void downloadDocument(final Document document) {
|
||||
StreamResource resource = createDocumentStreamResource(document);
|
||||
getUI().ifPresent(ui -> openDocumentStream(resource, ui));
|
||||
}
|
||||
|
||||
private StreamResource createDocumentStreamResource(final Document document) {
|
||||
StreamResource resource = new StreamResource(document.getFileName(),
|
||||
() -> new ByteArrayInputStream(document.getFileData()));
|
||||
resource.setContentType("application/pdf");
|
||||
resource.setHeader("Content-Disposition", "attachment; filename=\"" + document.getFileName() + ".pdf\"");
|
||||
return resource;
|
||||
}
|
||||
|
||||
private void openDocumentStream(final StreamResource resource, final UI ui) {
|
||||
StreamRegistration registration = ui.getSession().getResourceRegistry().registerResource(resource);
|
||||
ui.getPage().open(registration.getResourceUri().toString());
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
package com.primefactorsolutions.views.employee;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.primefactorsolutions.service.ReportService;
|
||||
import com.vaadin.flow.component.UI;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.html.Anchor;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.UUID;
|
||||
@PermitAll
|
||||
@PageTitle("Reporte excel")
|
||||
@Route("employee-report")
|
||||
public class EmployeeReportView extends VerticalLayout implements HasUrlParameter<String> {
|
||||
private final EmployeeService employeeService;
|
||||
private final ReportService reportService;
|
||||
|
||||
public EmployeeReportView(final EmployeeService employeeService, final ReportService reportService) {
|
||||
this.employeeService = employeeService;
|
||||
this.reportService = reportService;
|
||||
Button backButton = new Button("Volver al Reporte de Empleados", event ->
|
||||
UI.getCurrent().navigate(EmployeesListView.class));
|
||||
backButton.addClassName("back-button");
|
||||
add(backButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent event, @OptionalParameter final String employeeId) {
|
||||
if (employeeId != null) {
|
||||
UUID id = UUID.fromString(employeeId);
|
||||
Employee employee = employeeService.getEmployee(id);
|
||||
if (employee != null) {
|
||||
generateExcelReport(employee);
|
||||
} else {
|
||||
Notification.show("Empleado no encontrado", 3000, Notification.Position.MIDDLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateExcelReport(final Employee employee) {
|
||||
try {
|
||||
byte[] excelContent = reportService.generateExcelReport(employee);
|
||||
StreamResource resource = new StreamResource(
|
||||
employee.getFirstName() + "_" + employee.getLastName() + "_report.xlsx",
|
||||
() -> new ByteArrayInputStream(excelContent)
|
||||
);
|
||||
Anchor downloadLink = new Anchor(resource, "Descargar Reporte Excel");
|
||||
downloadLink.getElement().setAttribute("download", true);
|
||||
add(downloadLink);
|
||||
} catch (Exception e) {
|
||||
Notification.show("Error al generar el reporte Excel", 3000, Notification.Position.MIDDLE);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,714 +0,0 @@
|
||||
package com.primefactorsolutions.views.employee;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.model.Team;
|
||||
import com.primefactorsolutions.model.*;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.primefactorsolutions.service.ReportService;
|
||||
import com.primefactorsolutions.service.TeamService;
|
||||
import com.primefactorsolutions.views.BaseEntityForm;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.vaadin.componentfactory.pdfviewer.PdfViewer;
|
||||
import com.vaadin.flow.component.ClickEvent;
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.dialog.Dialog;
|
||||
import com.vaadin.flow.component.html.*;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.tabs.TabSheet;
|
||||
import com.vaadin.flow.component.textfield.BigDecimalField;
|
||||
import com.vaadin.flow.component.textfield.EmailField;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.component.upload.Upload;
|
||||
import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
|
||||
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||
import com.vaadin.flow.router.*;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.vaadin.firitin.components.datepicker.VDatePicker;
|
||||
import org.vaadin.firitin.fields.ElementCollectionField;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@SpringComponent
|
||||
@PermitAll
|
||||
@Scope("prototype")
|
||||
@PageTitle("Employee")
|
||||
@Route(value = "/employees/:employeeId?/:action?", layout = MainLayout.class)
|
||||
@Slf4j
|
||||
public class EmployeeView extends BaseEntityForm<Employee> implements HasUrlParameter<String> {
|
||||
private final EmployeeService employeeService;
|
||||
private final ReportService reportService;
|
||||
private final TeamService teamService;
|
||||
private final TabSheet tabSheet = new TabSheet();
|
||||
// TODO: campo usado para registrar al empleado en LDAP. Este campo podria estar en otro form eventualmente.
|
||||
private final TextField username = createTextField("Username", 30, true);
|
||||
private final TextField firstName = createTextField("Nombres", 30, true);
|
||||
private final TextField lastName = createTextField("Apellidos", 30, true);
|
||||
private final ComboBox<Employee.Status> status = createStatusComboBox();
|
||||
private final ComboBox<Employee.Gender> gender = createGenderComboBox();
|
||||
private final VDatePicker birthday = new VDatePicker("Fecha de Nacimiento");
|
||||
private final TextField age = createTextField("Edad", 3, false);
|
||||
private final TextField birthCity = createTextField("Ciudad y País de Nacimiento", 30, false);
|
||||
private final TextField residenceAddress = createTextField("Dirección de Residencia", 50, false);
|
||||
private final TextField localAddress = createTextField("Departamento y Provincia de Residencia", 30, false);
|
||||
private final ComboBox<Employee.MaritalStatus> maritalStatus = createMaritalStatusComboBox();
|
||||
private final TextField numberOfChildren = createTextField("Numero de Hijos", 1, false);
|
||||
private final TextField ci = createTextField("CI", 10, false);
|
||||
private final TextField issuedIn = createTextField("Lugar de Expedicion", 10, false);
|
||||
private final TextField phoneNumber = createTextField("Teléfono", 8, false);
|
||||
private final EmailField personalEmail = createEmailField("E-mail");
|
||||
private final TextField phoneNumberProfessional = createTextField("Teléfono Laboral", 8, false);
|
||||
private final TextField emergencyCName = createTextField("Nombres y Apellidos de Contacto", 50, false);
|
||||
private final TextField emergencyCAddress = createTextField("Dirección de Contacto", 50, false);
|
||||
private final TextField emergencyCPhone = createTextField("Teléfono de Contacto", 8, false);
|
||||
private final EmailField emergencyCEmail = createEmailField("Email de Contacto");
|
||||
private final MemoryBuffer buffer = new MemoryBuffer();
|
||||
private final Upload upload = new Upload(buffer);
|
||||
private final Image profileImagePreview = new Image();
|
||||
private final ElementCollectionField<Certification> educationTitles =
|
||||
new ElementCollectionField<>(Certification.class);
|
||||
private final ElementCollectionField<Certification> certifications =
|
||||
new ElementCollectionField<>(Certification.class);
|
||||
private final TextField recognition = createTextField("Reconocimientos", 30, false);
|
||||
private final TextField achievements = createTextField("Logros Profesionales", 30, false);
|
||||
private final ElementCollectionField<Language> languages = new ElementCollectionField<>(Language.class);
|
||||
private final TextField cod = createTextField("Codigo de Empleado", 20, false);
|
||||
private final TextField position = createTextField("Cargo", 30, false);
|
||||
private final ComboBox<Team> team = new ComboBox<>("Equipo");
|
||||
private final TextField leadManager = createTextField("Lead/Manager", 30, false);
|
||||
private final VDatePicker dateOfEntry = new VDatePicker("Fecha de Ingreso");
|
||||
private final VDatePicker dateOfExit = new VDatePicker("Fecha de Retiro");
|
||||
private final ComboBox<Employee.ContractType> contractType = createContractTypeComboBox();
|
||||
private final TextField customContractType = createCustomContractTypeField();
|
||||
private final TextField seniority = createTextField("Antiguedad", 30, false);
|
||||
private final BigDecimalField salaryTotal = createBigDecimalField("Salario Total", false);
|
||||
private final BigDecimalField salaryBasic = createBigDecimalField("Salario Basico", false);
|
||||
private final BigDecimalField tenureBonus = createBigDecimalField("Bono de Antiguedad", false);
|
||||
private final BigDecimalField professionalBonus = createBigDecimalField("Bono Profesional", false);
|
||||
private final TextField bankName = createTextField("Banco", 30, false);
|
||||
private final TextField accountNumber = createTextField("Nro. de Cuenta", 30, false);
|
||||
private final TextField gpss = createTextField("Código Único de Asegurado (GPSS)", 30, false);
|
||||
private final TextField sss = createTextField("Matricula de Asegurado (SSS)", 30, false);
|
||||
private final TextField beneficiarie1 = createTextField("Derechohabiente 1", 30, false);
|
||||
private final TextField beneficiarie2 = createTextField("Derechohabiente 2", 30, false);
|
||||
private static final String NOTIFICATION_SAVE_SUCCESS = "Employee saved successfully.";
|
||||
private static final String NOTIFICATION_VALIDATE_ERROR = "Please complete the required fields correctly.";
|
||||
private static final String PHONE_NUMBER_ERROR_MESSAGE = "El teléfono debe contener solo números.";
|
||||
private final Button reportButton = new Button("Generar Ficha de Contratación");
|
||||
private final Dialog dialog = new Dialog();
|
||||
private final PdfViewer pdfViewer = new PdfViewer();
|
||||
private final Button excelReportButton = new Button("Información General del Empleado Excel",
|
||||
VaadinIcon.FILE_TABLE.create());
|
||||
|
||||
private final H3 generalInfo = new H3("Información General");
|
||||
private final H5 imagenSub = new H5("Insertar una imagen .jpg:");
|
||||
private final H3 contEmerg = new H3("Contacto de Emergencia");
|
||||
|
||||
private final H3 titulos = new H3("Titulos Profesionales y Estudios Realizados");
|
||||
private final H3 certif = new H3("Certificaciones Profesionales");
|
||||
private final H3 logros = new H3("Otros Logros y Reconocimientos");
|
||||
private final H3 idioma = new H3("Dominio de Idiomas");
|
||||
|
||||
private final H2 titleAdminInfo = new H2("Información Administrativa");
|
||||
private final H3 infoCont = new H3("Información de Contratación");
|
||||
private final H3 datBanc = new H3("Datos Bancarios");
|
||||
private final H3 datGest = new H3("Datos Gestora Pública y Seguro Social");
|
||||
|
||||
public EmployeeView(final AuthenticationContext authenticationContext,
|
||||
final EmployeeService employeeService,
|
||||
final ReportService reportService,
|
||||
final TeamService teamService) {
|
||||
super(authenticationContext, Employee.class);
|
||||
this.employeeService = employeeService;
|
||||
this.reportService = reportService;
|
||||
this.teamService = teamService;
|
||||
excelReportButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
configureComponents();
|
||||
addClassName("main-layout");
|
||||
excelReportButton.addClickListener(e ->
|
||||
getUI().ifPresent(ui ->
|
||||
ui.navigate(EmployeeReportView.class, getEntity().getId().toString())
|
||||
)
|
||||
);
|
||||
setSavedHandler(this::saveEmployee);
|
||||
}
|
||||
|
||||
private void makeUpperCase(final TextField textField) {
|
||||
textField.addValueChangeListener(event -> {
|
||||
String value = event.getValue();
|
||||
if (value != null) {
|
||||
textField.setValue(value.toUpperCase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void configureComponents() {
|
||||
tabSheet.setWidthFull();
|
||||
phoneNumber.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
phoneNumber.addValueChangeListener(e -> validatePhoneNumber(phoneNumber, e.getValue()));
|
||||
emergencyCPhone.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
emergencyCPhone.addValueChangeListener(e -> validatePhoneNumber(emergencyCPhone, e.getValue()));
|
||||
firstName.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
firstName.addValueChangeListener(e -> validateNameField(firstName, e.getValue()));
|
||||
lastName.setValueChangeMode(ValueChangeMode.EAGER);
|
||||
lastName.addValueChangeListener(e -> validateNameField(lastName, e.getValue()));
|
||||
createTeamComboBox();
|
||||
configureUpload();
|
||||
reportButton.setVisible(true);
|
||||
birthday.addValueChangeListener(event -> calculateAge());
|
||||
birthday.setMin(LocalDate.now().minusYears(100));
|
||||
birthday.setMax(LocalDate.now().minusYears(18));
|
||||
birthday.addValueChangeListener(event -> {
|
||||
LocalDate selectedDate = event.getValue();
|
||||
if (selectedDate != null && ChronoUnit.YEARS.between(selectedDate, LocalDate.now()) < 18) {
|
||||
birthday.setInvalid(true);
|
||||
birthday.setErrorMessage("El empleado debe ser mayor o tener 18 años");
|
||||
} else {
|
||||
birthday.setInvalid(false);
|
||||
}
|
||||
});
|
||||
salaryTotal.addValueChangeListener(event -> calculateSalaryTotal());
|
||||
dateOfEntry.addValueChangeListener(event -> calculateSeniority());
|
||||
dateOfExit.addValueChangeListener(event -> {
|
||||
if (event.getValue() != null) {
|
||||
status.setValue(Employee.Status.INACTIVE);
|
||||
} else {
|
||||
status.setValue(Employee.Status.ACTIVE);
|
||||
}
|
||||
});
|
||||
reportButton.addClickListener((ComponentEventListener<ClickEvent<Button>>) buttonClickEvent -> {
|
||||
var employee = getEntity();
|
||||
byte[] pdfContent = reportService.writeAsPdf("ficha", employee);
|
||||
var resource = new StreamResource("ficha.pdf", () -> new ByteArrayInputStream(pdfContent));
|
||||
pdfViewer.setSrc(resource);
|
||||
dialog.open();
|
||||
});
|
||||
|
||||
makeUpperCase(firstName);
|
||||
makeUpperCase(lastName);
|
||||
makeUpperCase(birthCity);
|
||||
makeUpperCase(residenceAddress);
|
||||
makeUpperCase(localAddress);
|
||||
makeUpperCase(position);
|
||||
makeUpperCase(emergencyCName);
|
||||
makeUpperCase(emergencyCAddress);
|
||||
makeUpperCase(ci);
|
||||
makeUpperCase(issuedIn);
|
||||
makeUpperCase(recognition);
|
||||
makeUpperCase(achievements);
|
||||
makeUpperCase(cod);
|
||||
makeUpperCase(leadManager);
|
||||
makeUpperCase(seniority);
|
||||
makeUpperCase(bankName);
|
||||
makeUpperCase(accountNumber);
|
||||
makeUpperCase(gpss);
|
||||
makeUpperCase(sss);
|
||||
makeUpperCase(beneficiarie1);
|
||||
makeUpperCase(beneficiarie2);
|
||||
initDialog();
|
||||
}
|
||||
|
||||
private void validateNameField(final TextField textField, final String value) {
|
||||
if (!value.matches("^[a-zA-ZáéíóúÁÉÍÓÚñÑ\\s]*$")) {
|
||||
textField.setInvalid(true);
|
||||
textField.setErrorMessage("Este campo solo debe contener letras.");
|
||||
} else {
|
||||
textField.setInvalid(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateAge() {
|
||||
if (birthday.getValue() != null) {
|
||||
int currentYear = java.time.LocalDate.now().getYear();
|
||||
int birthYear = birthday.getValue().getYear();
|
||||
int ages = currentYear - birthYear;
|
||||
age.setValue(String.valueOf(ages));
|
||||
birthday.setInvalid(ages < 18);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateSeniority() {
|
||||
LocalDate entryDate = dateOfEntry.getValue();
|
||||
LocalDate exitDate = dateOfExit.getValue() != null ? dateOfExit.getValue() : LocalDate.now();
|
||||
if (entryDate != null) {
|
||||
long yearsOfService = ChronoUnit.YEARS.between(entryDate, exitDate);
|
||||
String seniorityValue = yearsOfService + " años ";
|
||||
seniority.setValue(seniorityValue);
|
||||
} else {
|
||||
seniority.setValue("No disponible");
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateSalaryTotal() {
|
||||
if (contractType.getValue() == Employee.ContractType.CONTRATO_LABORAL) {
|
||||
salaryBasic.setVisible(true);
|
||||
professionalBonus.setVisible(true);
|
||||
tenureBonus.setVisible(true);
|
||||
salaryTotal.setVisible(true);
|
||||
salaryBasic.addValueChangeListener(event -> updateTotalSalary());
|
||||
professionalBonus.addValueChangeListener(event -> updateTotalSalary());
|
||||
tenureBonus.addValueChangeListener(event -> updateTotalSalary());
|
||||
} else {
|
||||
salaryBasic.setVisible(false);
|
||||
professionalBonus.setVisible(false);
|
||||
tenureBonus.setVisible(false);
|
||||
salaryTotal.setVisible(true);
|
||||
}
|
||||
salaryTotal.getValue();
|
||||
}
|
||||
|
||||
private void updateTotalSalary() {
|
||||
try {
|
||||
final BigDecimal basic = salaryBasic.getValue();
|
||||
final BigDecimal bonus = professionalBonus.getValue();
|
||||
final BigDecimal seniorityBonus = tenureBonus.getValue();
|
||||
final BigDecimal totalSalary = basic.add(bonus).add(seniorityBonus);
|
||||
salaryTotal.setValue(totalSalary);
|
||||
} catch (Exception e) {
|
||||
salaryTotal.setValue(BigDecimal.valueOf(0.0));
|
||||
}
|
||||
}
|
||||
|
||||
private double parseDoubleValue(final String value) {
|
||||
try {
|
||||
return value != null && !value.isEmpty() ? Double.parseDouble(value) : 0.0;
|
||||
} catch (NumberFormatException e) {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private void configureUpload() {
|
||||
upload.setAcceptedFileTypes("image/jpeg", "image/png");
|
||||
upload.setMaxFileSize(1024 * 1024);
|
||||
upload.addSucceededListener(event -> {
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
buffer.getInputStream().transferTo(outputStream);
|
||||
byte[] imageBytes = outputStream.toByteArray();
|
||||
String base64Image = Base64.getEncoder().encodeToString(imageBytes);
|
||||
getEntity().setProfileImage(base64Image);
|
||||
profileImagePreview.setSrc("data:image/png;base64," + base64Image);
|
||||
profileImagePreview.setMaxWidth("150px");
|
||||
profileImagePreview.setMaxHeight("150px");
|
||||
} catch (IOException e) {
|
||||
Notification.show("Error al subir la imagen: " + e.getMessage());
|
||||
log.error("Error uploading image", e);
|
||||
} catch (Exception e) {
|
||||
Notification.show("Error en el servidor al procesar la imagen.");
|
||||
log.error("Error uploading image", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void validatePhoneNumber(final TextField textField, final String value) {
|
||||
if (!value.matches("\\d*")) {
|
||||
textField.setErrorMessage(PHONE_NUMBER_ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void initDialog() {
|
||||
pdfViewer.setSizeFull();
|
||||
H2 headline = new H2("Ficha Empleado");
|
||||
headline.getStyle().set("margin", "var(--lumo-space-m) 0 0 0")
|
||||
.set("font-size", "1.5em").set("font-weight", "bold");
|
||||
final Button cancelDialogButton = new Button("Close", e -> dialog.close());
|
||||
final HorizontalLayout buttonLayout = new HorizontalLayout(cancelDialogButton);
|
||||
buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
|
||||
final VerticalLayout dialogLayout = new VerticalLayout(headline, pdfViewer, buttonLayout);
|
||||
dialogLayout.getStyle().set("height", "100%");
|
||||
dialogLayout.getStyle().set("overflow", "hidden");
|
||||
dialogLayout.getStyle().set("display", "flex");
|
||||
dialogLayout.getStyle().set("flex-direction", "column");
|
||||
dialogLayout.setPadding(false);
|
||||
dialogLayout.setAlignItems(FlexComponent.Alignment.STRETCH);
|
||||
dialogLayout.getStyle().set("width", "700px").set("max-width", "100%");
|
||||
dialogLayout.getStyle().set("height", "800px").set("max-height", "100%");
|
||||
dialog.add(dialogLayout);
|
||||
}
|
||||
|
||||
private ComboBox<Employee.MaritalStatus> createMaritalStatusComboBox() {
|
||||
ComboBox<Employee.MaritalStatus> comboBox = new ComboBox<>("Estado Civil");
|
||||
comboBox.setItems(Employee.MaritalStatus.values());
|
||||
comboBox.setItemLabelGenerator(Employee.MaritalStatus::name);
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private ComboBox<Employee.Status> createStatusComboBox() {
|
||||
ComboBox<Employee.Status> comboBox = new ComboBox<>("Estado");
|
||||
comboBox.setItems(Employee.Status.values());
|
||||
comboBox.setItemLabelGenerator(Employee.Status::name);
|
||||
comboBox.setRequiredIndicatorVisible(true);
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private ComboBox<Employee.ContractType> createContractTypeComboBox() {
|
||||
ComboBox<Employee.ContractType> comboBox = new ComboBox<>("Tipo de Contrato");
|
||||
comboBox.setItems(Employee.ContractType.values());
|
||||
comboBox.setItemLabelGenerator(Employee.ContractType::name);
|
||||
comboBox.setRequiredIndicatorVisible(true);
|
||||
comboBox.setWidth("300px");
|
||||
comboBox.addValueChangeListener(event -> handleContractTypeChange(event.getValue()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private TextField createCustomContractTypeField() {
|
||||
TextField textField = new TextField("Especificar Tipo de Contrato");
|
||||
textField.setPlaceholder("Ingrese el tipo de contrato...");
|
||||
textField.setVisible(false);
|
||||
textField.setWidth("300px");
|
||||
return textField;
|
||||
}
|
||||
|
||||
private void handleContractTypeChange(final Employee.ContractType selectedType) {
|
||||
if (selectedType == Employee.ContractType.OTROS) {
|
||||
customContractType.setVisible(true);
|
||||
customContractType.setRequired(true);
|
||||
} else {
|
||||
customContractType.setVisible(false);
|
||||
customContractType.clear();
|
||||
customContractType.setRequired(false);
|
||||
}
|
||||
}
|
||||
|
||||
private VerticalLayout createContentLayout() {
|
||||
VerticalLayout contentLayout = new VerticalLayout();
|
||||
contentLayout.setWidth("100%");
|
||||
return contentLayout;
|
||||
}
|
||||
|
||||
private TextField createTextField(final String label, final int maxLength, final boolean required) {
|
||||
TextField textField = new TextField(label);
|
||||
textField.setWidthFull();
|
||||
textField.setMaxLength(maxLength);
|
||||
textField.setRequired(required);
|
||||
return textField;
|
||||
}
|
||||
|
||||
private BigDecimalField createBigDecimalField(final String label, final boolean required) {
|
||||
BigDecimalField textField = new BigDecimalField(label);
|
||||
textField.setWidthFull();
|
||||
textField.setRequired(required);
|
||||
return textField;
|
||||
}
|
||||
|
||||
private EmailField createEmailField(final String label) {
|
||||
EmailField emailField = new EmailField(label);
|
||||
emailField.setWidthFull();
|
||||
emailField.setMaxLength(50);
|
||||
return emailField;
|
||||
}
|
||||
|
||||
private void createTeamComboBox() {
|
||||
List<Team> teams = teamService.findAllTeams();
|
||||
team.setItems(teams);
|
||||
team.setItemLabelGenerator(Team::getName);
|
||||
team.setWidthFull();
|
||||
}
|
||||
|
||||
private ComboBox<Employee.Gender> createGenderComboBox() {
|
||||
ComboBox<Employee.Gender> comboBox = new ComboBox<>("Genero");
|
||||
comboBox.setItems(Employee.Gender.values());
|
||||
comboBox.setItemLabelGenerator(Employee.Gender::name);
|
||||
comboBox.setRequiredIndicatorVisible(true);
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private boolean validateForm() {
|
||||
return !firstName.isEmpty() && !lastName.isEmpty() && status.getValue() != null;
|
||||
}
|
||||
|
||||
private void setVacationDuration(
|
||||
final Employee employee,
|
||||
final TimeOffRequest request,
|
||||
final LocalDate referenceDate) {
|
||||
double yearsOfService = ChronoUnit.YEARS.between(employee.getDateOfEntry(), referenceDate);
|
||||
request.setAvailableDays(calculateAvailableDays(yearsOfService));
|
||||
}
|
||||
|
||||
private double calculateAvailableDays(final double yearsOfService) {
|
||||
if (yearsOfService > 10) {
|
||||
return 30.0;
|
||||
} else if (yearsOfService > 5) {
|
||||
return 20.0;
|
||||
} else if (yearsOfService > 1) {
|
||||
return 15.0;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private void saveEmployee(final Employee employee) {
|
||||
if (validateForm()) {
|
||||
employee.setStatus(status.getValue());
|
||||
employee.setAge(age.getValue());
|
||||
employee.setSalaryBasic(salaryBasic.getValue());
|
||||
employee.setProfessionalBonus(professionalBonus.getValue());
|
||||
employee.setTenureBonus(tenureBonus.getValue());
|
||||
employee.setSalaryTotal((salaryTotal.getValue()));
|
||||
employee.setContractType(contractType.getValue());
|
||||
if (contractType.getValue() == Employee.ContractType.OTROS) {
|
||||
employee.setCustomContractType(customContractType.getValue());
|
||||
} else {
|
||||
employee.setCustomContractType(null);
|
||||
}
|
||||
employeeService.createOrUpdate(employee);
|
||||
Notification.show(NOTIFICATION_SAVE_SUCCESS);
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeesListView.class));
|
||||
} else {
|
||||
Notification.show(NOTIFICATION_VALIDATE_ERROR, 3000, Notification.Position.MIDDLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableEditMode() {
|
||||
setFieldsEditable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameter(final BeforeEvent beforeEvent, final String action) {
|
||||
final RouteParameters params = beforeEvent.getRouteParameters();
|
||||
final String s = params.get("employeeId").orElse(null);
|
||||
|
||||
if ("new".equals(action)) {
|
||||
setEntityWithEnabledSave(new Employee());
|
||||
setFieldsEditable();
|
||||
upload.setVisible(true);
|
||||
profileImagePreview.setVisible(true);
|
||||
salaryTotal.setValue(BigDecimal.valueOf(0.0));
|
||||
} else {
|
||||
final Employee employee;
|
||||
|
||||
if (s != null) {
|
||||
final UUID employeeId = UUID.fromString(s);
|
||||
employee = employeeService.getEmployee(employeeId);
|
||||
} else {
|
||||
employee = employeeService.getEmployee(getEmployeeId().get());
|
||||
}
|
||||
|
||||
if ("edit".equals(action)) {
|
||||
setEntityWithEnabledSave(employee);
|
||||
setEditHandler(null);
|
||||
status.setValue(employee.getStatus());
|
||||
setFieldsEditable();
|
||||
upload.setVisible(true);
|
||||
displayProfileImage(employee);
|
||||
profileImagePreview.setVisible(true);
|
||||
salaryTotal.setValue(employee.getSalaryTotal());
|
||||
} else if ("view".equals(action) || "me".equals(action)) {
|
||||
setEntity(employee);
|
||||
setEditHandler(__ -> getUI().ifPresent(ui -> ui.navigate("/employees/" + employee.getId() + "/edit")));
|
||||
setFieldsReadOnly();
|
||||
displayProfileImage(employee);
|
||||
salaryTotal.setValue(employee.getSalaryTotal());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void displayProfileImage(final Employee employee) {
|
||||
if (employee.getProfileImage() != null && !employee.getProfileImage().isEmpty()) {
|
||||
profileImagePreview.setSrc("data:image/jpeg;base64," + employee.getProfileImage());
|
||||
profileImagePreview.setVisible(true);
|
||||
profileImagePreview.setMaxWidth("250px");
|
||||
profileImagePreview.setMaxHeight("250px");
|
||||
upload.setVisible(true);
|
||||
} else {
|
||||
profileImagePreview.setVisible(true);
|
||||
upload.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void setFieldsReadOnly() {
|
||||
username.setReadOnly(true);
|
||||
firstName.setReadOnly(true);
|
||||
lastName.setReadOnly(true);
|
||||
status.setReadOnly(true);
|
||||
birthday.setReadOnly(true);
|
||||
birthCity.setReadOnly(true);
|
||||
residenceAddress.setReadOnly(true);
|
||||
localAddress.setReadOnly(true);
|
||||
maritalStatus.setReadOnly(true);
|
||||
numberOfChildren.setReadOnly(true);
|
||||
phoneNumber.setReadOnly(true);
|
||||
personalEmail.setReadOnly(true);
|
||||
phoneNumberProfessional.setReadOnly(true);
|
||||
position.setReadOnly(true);
|
||||
team.setReadOnly(true);
|
||||
emergencyCName.setReadOnly(true);
|
||||
emergencyCAddress.setReadOnly(true);
|
||||
emergencyCPhone.setReadOnly(true);
|
||||
emergencyCEmail.setReadOnly(true);
|
||||
profileImagePreview.setVisible(true);
|
||||
age.setReadOnly(true);
|
||||
gender.setReadOnly(true);
|
||||
status.setReadOnly(true);
|
||||
ci.setReadOnly(true);
|
||||
issuedIn.setReadOnly(true);
|
||||
educationTitles.setReadOnly(true);
|
||||
certifications.setReadOnly(true);
|
||||
recognition.setReadOnly(true);
|
||||
achievements.setReadOnly(true);
|
||||
languages.setReadOnly(true);
|
||||
cod.setReadOnly(true);
|
||||
leadManager.setReadOnly(true);
|
||||
dateOfEntry.setReadOnly(true);
|
||||
dateOfExit.setReadOnly(true);
|
||||
contractType.setReadOnly(true);
|
||||
customContractType.setReadOnly(true);
|
||||
seniority.setReadOnly(true);
|
||||
salaryTotal.setReadOnly(true);
|
||||
salaryBasic.setReadOnly(true);
|
||||
professionalBonus.setReadOnly(true);
|
||||
tenureBonus.setReadOnly(true);
|
||||
bankName.setReadOnly(true);
|
||||
accountNumber.setReadOnly(true);
|
||||
gpss.setReadOnly(true);
|
||||
sss.setReadOnly(true);
|
||||
beneficiarie1.setReadOnly(true);
|
||||
beneficiarie2.setReadOnly(true);
|
||||
}
|
||||
|
||||
private void setFieldsEditable() {
|
||||
username.setReadOnly(false);
|
||||
firstName.setReadOnly(false);
|
||||
lastName.setReadOnly(false);
|
||||
status.setReadOnly(false);
|
||||
birthday.setReadOnly(false);
|
||||
birthCity.setReadOnly(false);
|
||||
residenceAddress.setReadOnly(false);
|
||||
localAddress.setReadOnly(false);
|
||||
maritalStatus.setReadOnly(false);
|
||||
numberOfChildren.setReadOnly(false);
|
||||
phoneNumber.setReadOnly(false);
|
||||
personalEmail.setReadOnly(false);
|
||||
phoneNumberProfessional.setReadOnly(false);
|
||||
position.setReadOnly(false);
|
||||
team.setReadOnly(false);
|
||||
emergencyCName.setReadOnly(false);
|
||||
emergencyCAddress.setReadOnly(false);
|
||||
emergencyCPhone.setReadOnly(false);
|
||||
emergencyCEmail.setReadOnly(false);
|
||||
profileImagePreview.setVisible(true);
|
||||
age.setReadOnly(false);
|
||||
gender.setReadOnly(false);
|
||||
status.setReadOnly(false);
|
||||
ci.setReadOnly(false);
|
||||
issuedIn.setReadOnly(false);
|
||||
educationTitles.setReadOnly(false);
|
||||
certifications.setReadOnly(false);
|
||||
recognition.setReadOnly(false);
|
||||
achievements.setReadOnly(false);
|
||||
languages.setReadOnly(false);
|
||||
cod.setReadOnly(false);
|
||||
leadManager.setReadOnly(false);
|
||||
dateOfEntry.setReadOnly(false);
|
||||
dateOfExit.setReadOnly(false);
|
||||
contractType.setReadOnly(false);
|
||||
customContractType.setReadOnly(false);
|
||||
seniority.setReadOnly(false);
|
||||
salaryTotal.setReadOnly(false);
|
||||
salaryBasic.setReadOnly(false);
|
||||
professionalBonus.setReadOnly(false);
|
||||
tenureBonus.setReadOnly(false);
|
||||
bankName.setReadOnly(false);
|
||||
accountNumber.setReadOnly(false);
|
||||
gpss.setReadOnly(false);
|
||||
sss.setReadOnly(false);
|
||||
beneficiarie1.setReadOnly(false);
|
||||
beneficiarie2.setReadOnly(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Component> getFormComponents() {
|
||||
tabSheet.add("Info Personal", new VerticalLayout(
|
||||
generalInfo,
|
||||
imagenSub,
|
||||
upload,
|
||||
profileImagePreview,
|
||||
firstName,
|
||||
lastName,
|
||||
gender,
|
||||
status,
|
||||
birthday,
|
||||
age,
|
||||
birthCity,
|
||||
residenceAddress,
|
||||
localAddress,
|
||||
maritalStatus,
|
||||
ci,
|
||||
issuedIn,
|
||||
numberOfChildren,
|
||||
phoneNumber,
|
||||
personalEmail,
|
||||
phoneNumberProfessional,
|
||||
contEmerg,
|
||||
emergencyCName,
|
||||
emergencyCAddress,
|
||||
emergencyCPhone,
|
||||
emergencyCEmail
|
||||
));
|
||||
|
||||
tabSheet.add("Info Profesional", new VerticalLayout(
|
||||
titulos,
|
||||
educationTitles,
|
||||
certif,
|
||||
certifications,
|
||||
logros,
|
||||
recognition,
|
||||
achievements,
|
||||
idioma,
|
||||
languages
|
||||
));
|
||||
|
||||
if (isRoleAdmin()) {
|
||||
tabSheet.add("Info Administrativa", new VerticalLayout(
|
||||
cod,
|
||||
position,
|
||||
team,
|
||||
leadManager,
|
||||
infoCont,
|
||||
dateOfEntry,
|
||||
dateOfExit,
|
||||
seniority,
|
||||
contractType,
|
||||
customContractType,
|
||||
salaryBasic,
|
||||
professionalBonus,
|
||||
tenureBonus,
|
||||
salaryTotal,
|
||||
datBanc,
|
||||
bankName,
|
||||
accountNumber,
|
||||
datGest,
|
||||
gpss,
|
||||
sss,
|
||||
beneficiarie1,
|
||||
beneficiarie2
|
||||
));
|
||||
}
|
||||
|
||||
return List.of(
|
||||
new HorizontalLayout(reportButton, excelReportButton),
|
||||
username,
|
||||
tabSheet,
|
||||
dialog
|
||||
);
|
||||
}
|
||||
}
|
@ -1,206 +0,0 @@
|
||||
package com.primefactorsolutions.views.employee;
|
||||
|
||||
import com.primefactorsolutions.model.Employee;
|
||||
import com.primefactorsolutions.service.EmployeeService;
|
||||
import com.primefactorsolutions.views.BaseView;
|
||||
import com.primefactorsolutions.views.Constants;
|
||||
import com.primefactorsolutions.views.MainLayout;
|
||||
import com.primefactorsolutions.views.util.MenuBarUtils;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.html.Anchor;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.vaadin.firitin.components.grid.PagingGrid;
|
||||
import com.vaadin.flow.component.grid.GridSortOrder;
|
||||
import com.vaadin.flow.data.provider.SortDirection;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@PageTitle("Employees")
|
||||
@Route(value = "/employees", layout = MainLayout.class)
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
@Slf4j
|
||||
public class EmployeesListView extends BaseView {
|
||||
|
||||
private final EmployeeService employeeService;
|
||||
private final PagingGrid<Employee> employeePagingGrid = new PagingGrid<>(Employee.class);
|
||||
|
||||
public EmployeesListView(final AuthenticationContext authenticationContext, final EmployeeService employeeService) {
|
||||
super(authenticationContext);
|
||||
this.employeeService = employeeService;
|
||||
setupView();
|
||||
refreshGrid();
|
||||
}
|
||||
|
||||
private void setupView() {
|
||||
configureTable();
|
||||
final HorizontalLayout hl = new HorizontalLayout(createAddEmployeeButton(), createExportButton());
|
||||
getCurrentPageLayout().add(hl);
|
||||
getCurrentPageLayout().add(employeePagingGrid);
|
||||
}
|
||||
|
||||
private Button createExportButton() {
|
||||
final StreamResource excelResource = new StreamResource("employees.xlsx", this::generateExcel);
|
||||
final Anchor downloadLink = new Anchor(excelResource, "Export Employees");
|
||||
downloadLink.getElement().setAttribute("download", true); // Forzar descarga
|
||||
|
||||
return new Button("Exportar como Excel", e -> getCurrentPageLayout().add(downloadLink));
|
||||
}
|
||||
|
||||
private ByteArrayInputStream generateExcel() {
|
||||
final List<Employee> employees = employeeService.findAllEmployees();
|
||||
try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
Sheet sheet = workbook.createSheet("Employees");
|
||||
Row headerRow = sheet.createRow(0);
|
||||
String[] headers = {
|
||||
"ID", "Nombres", "Apellidos", "Status", "Genero", "Fecha de Nacimiento", "Edad",
|
||||
"Ciudad y Pais de Nacimiento", "Dirección de Residencia", "Departamento y Provincia de Residencia",
|
||||
"Marital Status",
|
||||
"Numero de Hijos", "CI", "Expedido en", "Teléfono", "E-mail",
|
||||
"Teléfono Laboral", "E-mail Laboral", "Codigo de Empleado", "Cargo",
|
||||
"Equipo", "Lead/Manager", "Fecha de Ingreso", "Fecha de Retiro", "Tipo de Contrato",
|
||||
"Otro Tipo de Contrato", "Antiguedad", "Salario Total"
|
||||
};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = headerRow.createCell(i);
|
||||
cell.setCellValue(headers[i]);
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
Font font = workbook.createFont();
|
||||
font.setBold(true);
|
||||
style.setFont(font);
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
int rowIndex = 1;
|
||||
for (Employee employee : employees) {
|
||||
Row row = sheet.createRow(rowIndex++);
|
||||
row.createCell(0).setCellValue(employee.getId().toString());
|
||||
row.createCell(1).setCellValue(employee.getFirstName());
|
||||
row.createCell(2).setCellValue(employee.getLastName());
|
||||
row.createCell(3).setCellValue(employee.getStatus().toString());
|
||||
row.createCell(4).setCellValue(employee.getGender() != null ? employee.getGender().toString() : "");
|
||||
row.createCell(5).setCellValue(employee.getBirthday() != null ? employee.getBirthday()
|
||||
.toString() : "");
|
||||
row.createCell(6).setCellValue(employee.getAge() != null ? employee.getAge() : "");
|
||||
row.createCell(7).setCellValue(employee.getBirthCity() != null ? employee.getBirthCity() : "");
|
||||
row.createCell(8).setCellValue(employee.getResidenceAddress() != null ? employee
|
||||
.getResidenceAddress() : "");
|
||||
row.createCell(9).setCellValue(employee.getLocalAddress() != null ? employee.getLocalAddress() : "");
|
||||
row.createCell(10).setCellValue(employee.getMaritalStatus() != null ? employee.getMaritalStatus()
|
||||
.toString() : "");
|
||||
row.createCell(11).setCellValue(employee.getNumberOfChildren() != null ? employee
|
||||
.getNumberOfChildren() : "");
|
||||
row.createCell(12).setCellValue(employee.getCi() != null ? employee.getCi() : "");
|
||||
row.createCell(13).setCellValue(employee.getIssuedIn() != null ? employee.getIssuedIn() : "");
|
||||
row.createCell(14).setCellValue(employee.getPhoneNumber() != null ? employee.getPhoneNumber() : "");
|
||||
row.createCell(15).setCellValue(employee.getPersonalEmail() != null ? employee
|
||||
.getPersonalEmail() : "");
|
||||
row.createCell(16).setCellValue(employee.getPhoneNumberProfessional() != null ? employee
|
||||
.getPhoneNumberProfessional() : "");
|
||||
row.createCell(17).setCellValue(employee.getProfessionalEmail() != null ? employee
|
||||
.getProfessionalEmail() : "");
|
||||
row.createCell(18).setCellValue(employee.getCod() != null ? employee.getCod() : "");
|
||||
row.createCell(19).setCellValue(employee.getPosition() != null ? employee.getPosition() : "");
|
||||
row.createCell(20).setCellValue(employee.getTeam() != null ? employee.getTeam().getName() : "");
|
||||
row.createCell(21).setCellValue(employee.getLeadManager() != null ? employee.getLeadManager() : "");
|
||||
row.createCell(22).setCellValue(employee.getDateOfEntry() != null ? employee.getDateOfEntry()
|
||||
.toString() : "");
|
||||
row.createCell(23).setCellValue(employee.getDateOfExit() != null ? employee.getDateOfExit()
|
||||
.toString() : "");
|
||||
row.createCell(24).setCellValue(employee.getContractType() != null ? employee.getContractType()
|
||||
.toString() : "");
|
||||
row.createCell(25).setCellValue(employee.getCustomContractType() != null
|
||||
? employee.getCustomContractType()
|
||||
: "");
|
||||
row.createCell(26).setCellValue(employee.getSeniority() != null ? employee.getSeniority() : "");
|
||||
row.createCell(27).setCellValue(employee.getSalaryTotal() != null
|
||||
? employee.getSalaryTotal().toString()
|
||||
: "");
|
||||
}
|
||||
workbook.write(out);
|
||||
return new ByteArrayInputStream(out.toByteArray());
|
||||
} catch (IOException e) {
|
||||
log.error("Error generating excel", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void configureTable() {
|
||||
employeePagingGrid.setColumns("username", "firstName", "lastName", "status");
|
||||
employeePagingGrid.addComponentColumn(employee -> MenuBarUtils.menuBar(
|
||||
Pair.of("View", __ -> navigateToEmployeeView(employee)),
|
||||
Pair.of("Edit", __ -> navigateToEditView(employee))));
|
||||
setupPagingGrid();
|
||||
}
|
||||
|
||||
private Button createButton(final String label, final Runnable onClickAction, final boolean isPrimary) {
|
||||
final Button button = new Button(label);
|
||||
|
||||
if (isPrimary) {
|
||||
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
}
|
||||
|
||||
button.addClickListener(event -> onClickAction.run());
|
||||
return button;
|
||||
}
|
||||
|
||||
private Button createAddEmployeeButton() {
|
||||
return createButton("Add Employee", this::navigateToAddEmployeeView, true);
|
||||
}
|
||||
|
||||
private void navigateToEditView(final Employee employee) {
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, employee.getId().toString() + "/edit"));
|
||||
}
|
||||
|
||||
private void navigateToEmployeeView(final Employee employee) {
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, employee.getId().toString() + "/view"));
|
||||
}
|
||||
|
||||
private void navigateToAddEmployeeView() {
|
||||
getUI().ifPresent(ui -> ui.navigate(EmployeeView.class, "new"));
|
||||
}
|
||||
|
||||
private void setupPagingGrid() {
|
||||
employeePagingGrid.setPaginationBarMode(PagingGrid.PaginationBarMode.BOTTOM);
|
||||
employeePagingGrid.setPageSize(Constants.PAGE_SIZE);
|
||||
}
|
||||
|
||||
private void refreshGrid() {
|
||||
employeePagingGrid.setPagingDataProvider((page, pageSize) -> fetchEmployees((int) page, pageSize));
|
||||
}
|
||||
|
||||
private List<Employee> fetchEmployees(final int page, final int pageSize) {
|
||||
int start = page * pageSize;
|
||||
if (hasSortOrder()) {
|
||||
return fetchSortedEmployees(start, pageSize);
|
||||
}
|
||||
return employeeService.findEmployees(start, pageSize);
|
||||
}
|
||||
|
||||
private boolean hasSortOrder() {
|
||||
return !employeePagingGrid.getSortOrder().isEmpty();
|
||||
}
|
||||
|
||||
private List<Employee> fetchSortedEmployees(final int start, final int pageSize) {
|
||||
final GridSortOrder<Employee> sortOrder = employeePagingGrid.getSortOrder().getFirst();
|
||||
|
||||
return employeeService.findEmployees(start, pageSize,
|
||||
sortOrder.getSorted().getKey(),
|
||||
sortOrder.getDirection() == SortDirection.ASCENDING);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user