Commit 492cec2b authored by ='s avatar =

Merge branch 'master' into hieunv

# Conflicts:
#	pom.xml
#	src/main/java/com/itsol/quantrivanphong/access/homepage/controller/NewsController.java
#	src/main/java/com/itsol/quantrivanphong/model/Project.java
#	src/main/resources/application.properties
parents a46bce3e 1fadf5fd
......@@ -23,10 +23,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-security</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
......@@ -53,11 +49,14 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.security</groupId>-->
<!-- <artifactId>spring-security-test</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
......@@ -67,6 +66,7 @@
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>Spring4MVCCRUDRestService</finalName>
</build>
</project>
//package com.itsol.quantrivanphong.access.homepage.controller;
//
//import com.itsol.quantrivanphong.access.homepage.business.CatalogiBusiness;
//import com.itsol.quantrivanphong.access.homepage.business.NewsBusiness;
//import com.itsol.quantrivanphong.employee.bussiness.EmployeeBussiness;
//import com.itsol.quantrivanphong.exception.ResourceNotFoundException;
//import com.itsol.quantrivanphong.model.Employee;
//import com.itsol.quantrivanphong.model.News;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.data.domain.Page;
//import org.springframework.data.domain.Pageable;
//import org.springframework.http.ResponseEntity;
//import org.springframework.web.bind.annotation.*;
//
//import javax.validation.Valid;
//import java.util.List;
//
//@RestController
//@RequestMapping("/api")
//public class NewsController {
// @Autowired
// private NewsBusiness newsBusiness;
//
// @Autowired
// private CatalogiBusiness catalogiBusiness;
//
// @Autowired
// private EmployeeBussiness employeeBusiness;
// // get All news
// @GetMapping("/news")
// public ResponseEntity<List<News>> getAllNews(){
// return ResponseEntity.ok(newsBusiness.findAllNews());
// }
//
// // get news by employeeId
// @GetMapping("/news/employees/{employeeId}")
// public List<News> getAllNewsByEmployeeId(@PathVariable(value = "employeeId") int employeeId) {
// return newsBusiness.findByEmployeeId(employeeId);
// }
// // get News by catalogiId
// @GetMapping("/news/catalogi/{catalogiId}")
// public List<News> getAllNewsByCatalogiId(@PathVariable(value="catalogiId") int catalogiId){
// return newsBusiness.findByCatalogiId(catalogiId);
// }
//
//
// // create news by employeesId
// @PostMapping("/news/employees/{employeeId}")
// public News createNews(@PathVariable (value = "employeeId") int employeeId,
// @Valid @RequestBody News news) {
// return employeeBusiness.findById(employeeId).map(employee -> {
// news.setEmployee(employee);
// return newsBusiness.save(news);
// }).orElseThrow(() -> new ResourceNotFoundException("Employee" ,"employeeId",employeeId));
// }
//
// // Edit news by EmployeeId
// @PutMapping("/employees/{employeeId}/news/{newsId}")
// public News updateNews(@PathVariable (value = "employeeId") int employeeId,
// @PathVariable (value = "newsId") int newsId,
// @Valid @RequestBody News newsRequest) {
// if(!employeeBusiness.findById(employeeId).isPresent()) {
// throw new ResourceNotFoundException("Employee" ,"employeeId",employeeId);
// }
// if (!newsBusiness.findById(newsId).isPresent()) {
// throw new ResourceNotFoundException("News", "id", newsId);
// }
// return newsBusiness.updateNews(newsId,newsRequest);
// }
//
// //delete news by employeeId and newsId
// @DeleteMapping("/employees/{employeeId}/news/{newsId}")
// public ResponseEntity<?> deleteNews(@PathVariable (value = "employeeId") int employeeId,
// @PathVariable (value = "newsId") int newsId) {
// if(!newsBusiness.findByIdAndEmployeeId(employeeId,newsId).isPresent()){
// throw new ResourceNotFoundException("News","newsId",newsId);
// }
// return ResponseEntity.ok(newsBusiness.deleteNews(employeeId,newsId));
// }
//}
package com.itsol.quantrivanphong.access.homepage.controller;
import com.itsol.quantrivanphong.access.homepage.business.CatalogiBusiness;
import com.itsol.quantrivanphong.access.homepage.business.NewsBusiness;
import com.itsol.quantrivanphong.business.EmployeeBusiness;
import com.itsol.quantrivanphong.exception.ResourceNotFoundException;
import com.itsol.quantrivanphong.model.Employee;
import com.itsol.quantrivanphong.model.News;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/api")
public class NewsController {
@Autowired
private NewsBusiness newsBusiness;
@Autowired
private CatalogiBusiness catalogiBusiness;
@Autowired
private EmployeeBusiness employeeBusiness;
// get All news
@GetMapping("/news")
public ResponseEntity<List<News>> getAllNews(){
return ResponseEntity.ok(newsBusiness.findAllNews());
}
// get news by employeeId
@GetMapping("/news/employees/{employeeId}")
public List<News> getAllNewsByEmployeeId(@PathVariable(value = "employeeId") int employeeId) {
return newsBusiness.findByEmployeeId(employeeId);
}
// get News by catalogiId
@GetMapping("/news/catalogi/{catalogiId}")
public List<News> getAllNewsByCatalogiId(@PathVariable(value="catalogiId") int catalogiId){
return newsBusiness.findByCatalogiId(catalogiId);
}
// create news by employeesId
@PostMapping("/news/employees/{employeeId}")
public News createNews(@PathVariable (value = "employeeId") int employeeId,
@Valid @RequestBody News news) {
Employee employee = employeeBusiness.findById(employeeId);
news.setEmployee(employee);
return newsBusiness.save(news);
}
// Edit news by EmployeeId
@PutMapping("/employees/{employeeId}/news/{newsId}")
public News updateNews(@PathVariable (value = "employeeId") int employeeId,
@PathVariable (value = "newsId") int newsId,
@Valid @RequestBody News newsRequest) {
if(employeeBusiness.findById(employeeId) == null) {
throw new ResourceNotFoundException("Employee" ,"employeeId",employeeId);
}
if (!newsBusiness.findById(newsId).isPresent()) {
throw new ResourceNotFoundException("News", "id", newsId);
}
return newsBusiness.updateNews(newsId,newsRequest);
}
//delete news by employeeId and newsId
@DeleteMapping("/employees/{employeeId}/news/{newsId}")
public ResponseEntity<?> deleteNews(@PathVariable (value = "employeeId") int employeeId,
@PathVariable (value = "newsId") int newsId) {
if(!newsBusiness.findByIdAndEmployeeId(employeeId,newsId).isPresent()){
throw new ResourceNotFoundException("News","newsId",newsId);
}
return ResponseEntity.ok(newsBusiness.deleteNews(employeeId,newsId));
}
}
package com.itsol.quantrivanphong.access.login.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeDTO {
private Integer id;
// tên đăng nhập
private String username;
// mật khẩu truy cập
private String password;
// ảnh đại diện
private String picture;
// họ
private String firstName;
// tên
private String lastName;
// email
private String email;
// số điện thoại
private String phoneNumber;
// tài khoản skype
private String skype;
// tài khoản facebook
private String facebookProfile;
// đối tượng
private String position;
// quê quán
private String homeTown;
// học vấn
private String education;
// trường
private String school;
// khoa
private String department;
// năm tốt nghiệp
private String graduationYear;
// kiểm tra tài khoản
private boolean checked;
// trạng thái kích hoạt
private int status;
}
package com.itsol.quantrivanphong.access.login.dto;
public class EmployeeRoleDTO {
}
package com.itsol.quantrivanphong.access.login.dto;
public class RoleDTO {
}
package com.itsol.quantrivanphong.access.register.controller;
import com.itsol.quantrivanphong.access.register.bussiness.InputException;
import com.itsol.quantrivanphong.exception.InputException;
import com.itsol.quantrivanphong.access.register.bussiness.RegisterBussiness;
import com.itsol.quantrivanphong.access.register.dto.RegisterDTO;
import org.springframework.beans.factory.annotation.Autowired;
......
package com.itsol.quantrivanphong.business;
import com.itsol.quantrivanphong.model.Employee;
import org.springframework.validation.Validator;
import java.util.List;
public interface EmployeeBusiness extends Validator {
List<Employee> findAll();
Employee findById(int id);
Employee findEmployeeByEmailAddress(String email);
Employee findEmployeeByUserName(String name);
Employee findEmployeeByUsernameAndPassword(String username, String password);
void save(Employee employee);
void deleteById(int id);
boolean confirmEmployee(Employee employee);
}
package com.itsol.quantrivanphong.business.impl;
import com.itsol.quantrivanphong.model.Employee;
import com.itsol.quantrivanphong.repository.EmployeeRepository;
import com.itsol.quantrivanphong.business.EmployeeBusiness;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.Errors;
import java.util.List;
@Service
public class EmployeeBusinessImpl implements EmployeeBusiness {
@Autowired
private EmployeeRepository employeeRepository;
@Override
public List<Employee> findAll() {
return employeeRepository.findAll();
}
@Override
public Employee findById(int id) {
return employeeRepository.findById(id).orElse(null);
}
@Override
public Employee findEmployeeByEmailAddress(String email) {
return employeeRepository.findEmployeeByEmailAddress(email);
}
@Override
public Employee findEmployeeByUserName(String name) {
return employeeRepository.findEmployeeByUsername(name);
}
@Override
public Employee findEmployeeByUsernameAndPassword(String username, String password) {
return employeeRepository.findEmployeeByUsernameAndPassword(username,password);
}
@Override
public void save(Employee employee) {
employeeRepository.save(employee);
}
@Override
public void deleteById( int id) {
employeeRepository.deleteById(id);
}
@Override
public boolean confirmEmployee(Employee employee) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return Employee.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
Employee employee = (Employee) target;
if(employeeRepository.findEmployeeByUsername(employee.getUsername())!=null){
errors.rejectValue("username","username.alreadyExist");
}
if(employeeRepository.findEmployeeByEmailAddress(employee.getEmailAddress())!=null){
errors.rejectValue("email","email.alreadyExist");
}
if(!employee.getPassword().equals(employee.getConfirmPassword())){
errors.rejectValue("password","password.wrongPassword");
}
}
}
package com.itsol.quantrivanphong.controller;
import com.itsol.quantrivanphong.model.Employee;
import com.itsol.quantrivanphong.business.EmployeeBusiness;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.List;
@RestController
public class EmployeeController {
@Autowired
//Retrieve Employee by id
private EmployeeBusiness employeeBusiness;
@RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
public ResponseEntity<Employee> getEmployee(@PathVariable("id") int id) {
System.out.println("Fetching employee with id " + id);
Employee employee = employeeBusiness.findById(id);
if (employee == null) {
System.out.println("Employee with id : " + id + " not found");
return new ResponseEntity<Employee>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Employee>( employee ,HttpStatus.OK);
}
//Retrieve all employee
@RequestMapping(value = "/list_employee", method = RequestMethod.GET)
public ResponseEntity<List<Employee>> listAllEmployee() {
List<Employee> employees = employeeBusiness.findAll();
if (employees == null) {
return new ResponseEntity<List<Employee>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<Employee>>( employees , null ,HttpStatus.OK);
}
//Update a Employee
@RequestMapping(value = "/employee/{id}", method = RequestMethod.PUT)
public ResponseEntity<Employee> updateEmployee(@PathVariable("id") int id, @RequestBody Employee employee) {
System.out.println("Update Employee " + id);
Employee currentEmployee = employeeBusiness.findById(id);
if (employee == null) {
System.out.println("Employee with id :" + id + "not found");
return new ResponseEntity<Employee>(HttpStatus.NOT_FOUND);
}
currentEmployee.setUsername(employee.getUsername());
currentEmployee.setPassword(employee.getPassword());
currentEmployee.setFirstName(employee.getFirstName());
currentEmployee.setLastName(employee.getLastName());
currentEmployee.setEmailAddress(employee.getEmailAddress());
currentEmployee.setPhoneNumber(employee.getPhoneNumber());
currentEmployee.setSkype(employee.getSkype());
currentEmployee.setFacebookProfile(employee.getFacebookProfile());
currentEmployee.setPosition(employee.getPosition());
currentEmployee.setHomeTown(employee.getHomeTown());
currentEmployee.setEducation(employee.getEducation());
currentEmployee.setSchool(employee.getSchool());
currentEmployee.setDepartment(employee.getDepartment());
currentEmployee.setGraduationYear(employee.getGraduationYear());
currentEmployee.setPicture(employee.getPicture());
employeeBusiness.save(currentEmployee);
return new ResponseEntity<Employee>( currentEmployee ,HttpStatus.OK);
}
//Create a Employee
@RequestMapping(value = "/list_employee", method = RequestMethod.POST)
public ResponseEntity<Void> createEmployee(@RequestBody Employee employee,
UriComponentsBuilder uriComponentsBuilder){
System.out.println("Create Employee "+ employee.getUsername());
employeeBusiness.save(employee);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(uriComponentsBuilder.path("/employee/{id}").buildAndExpand(employee.getId()).toUri());
return new ResponseEntity<Void>( httpHeaders ,HttpStatus.CREATED);
}
//Delete a Employee
@RequestMapping(value = "/employee/{id}" , method = RequestMethod.DELETE)
public ResponseEntity<Employee> deleteEmployee(@PathVariable("id") int id){
System.out.println("Fetching and deleting Employee with id :" + id );
Employee employee = employeeBusiness.findById(id);
if(employee == null) {
System.out.println("Unable to delete. Employee with id :" + id + "not found");
return new ResponseEntity<Employee>(HttpStatus.NOT_FOUND);
}
employeeBusiness.deleteById(id);
return new ResponseEntity<Employee>(HttpStatus.NO_CONTENT);
}
}
package com.itsol.quantrivanphong.access.register.bussiness;
package com.itsol.quantrivanphong.exception;
public class InputException extends Exception {
......
package com.itsol.quantrivanphong.manager.project.project.bussiness;
import com.itsol.quantrivanphong.manager.project.project.dto.ProjectDTO;
import java.util.List;
public interface ProjectBussiness {
// Danh sách dự án tất cả các dự án
List<ProjectDTO> findAllProject();
// upload thông tin dự án
String updateProject(ProjectDTO dto);
// thêm dự án mới
String saveProject(ProjectDTO dto);
// tìm kiếm dự án theo id
ProjectDTO findByProjectId(Integer id);
// xóa dự án
String deleteProject(Integer[] ids);
}
package com.itsol.quantrivanphong.manager.project.project.bussiness;
import com.itsol.quantrivanphong.manager.project.project.dto.ProjectDTO;
import com.itsol.quantrivanphong.model.Project;
import com.itsol.quantrivanphong.manager.project.project.repository.ProjectRepository;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class ProjectBussinessImpl implements ProjectBussiness {
private Logger logger = Logger.getLogger(ProjectBussinessImpl.class);
private String views = "";
@Autowired
private ProjectRepository projectRepository;
@Override
public List<ProjectDTO> findAllProject() {
try {
return lstDTO(projectRepository.finAllEntity());
} catch (Exception e) {
logger.info("Lỗi findAll " + e.getMessage());
}
return null;
}
@Override
public String updateProject(ProjectDTO dto) {
try {
ProjectDTO projectDTO = findByProjectId(dto.getId());
if (dto.getStartDate() == null) {
views = "ngày bắt đầu dự án không được null";
} else if (dto.getEndDate() == null) {
views = "ngày dự kiếm kết thúc dự án không được null";
} else if (projectDTO != null) {
ProjectDTO updateProject = modelparseDto(projectRepository.updateEntity(dtoParseModels(dto)));
if (updateProject != null) {
views = "sửa thành công project";
}
} else {
views = "không tìm thấy project phù hợp";
}
} catch (Exception e) {
logger.info("Lỗi update" + e.getMessage());
views = "lỗi update project";
}
return views;
}
@Override
public String saveProject(ProjectDTO dto) {
try {
if (dto.getStartDate() == null) {
views = "ngày bắt đầu dự án không được null";
} else if (dto.getEndDate() == null) {
views = "ngày dự kiếm kết thúc dự án không được null";
} else {
dto.setStatusPost(0);
projectRepository.saveEntity(dtoParseModels(dto));
views = "thêm thành công project !";
}
} catch (Exception e) {
logger.info("Lỗi insert " + e.getMessage());
views = "thêm project không thành công!";
}
return views;
}
@Override
public ProjectDTO findByProjectId(Integer id) {
try {
ProjectDTO projectDTO = modelparseDto(projectRepository.findByEmtityId(id));
if (projectDTO != null) {
return projectDTO;
}
} catch (Exception e) {
logger.info("( Lỗi tìm kiếm ) " + e.getMessage());
}
return null;
}
@Override
public String deleteProject(Integer[] ids) {
int count = 0;
count = projectRepository.deleteEntity(ids);
if (count != 0) {
views = "xóa thành công " + count + " project";
} else {
views = "project không tồn tại";
}
return views;
}
public List<ProjectDTO> lstDTO(List<Project> lstModels) {
List<ProjectDTO> lstDTO = new ArrayList<>();
for (Project project : lstModels) {
lstDTO.add(modelparseDto(project));
}
return lstDTO;
}
public ProjectDTO modelparseDto(Project model) {
ProjectDTO dto = new ProjectDTO();
dto.setId(model.getId());
dto.setName(model.getName());
dto.setDescriptions(model.getDescriptions());
dto.setStartDate(model.getStartDate());
dto.setEndDate(model.getEndDate());
if(model.getStatus()==0){
dto.setStatusGet("Dự Kiến");
}else if(model.getStatus()==1){
dto.setStatusGet("Đang Tiến Hành");
}else{
dto.setStatusGet("Đã Hoàn Thành");
}
return dto;
}
public Project dtoParseModels(ProjectDTO projectDTO) {
Project project = new Project();
project.setId(projectDTO.getId());
project.setName(projectDTO.getName());
project.setDescriptions(projectDTO.getDescriptions());
project.setStartDate(projectDTO.getStartDate());
project.setEndDate(projectDTO.getEndDate());
project.setStatus(projectDTO.getStatusPost());
return project;
}
}
package com.itsol.quantrivanphong.manager.project.project.controller;
import com.itsol.quantrivanphong.report.issue.common.SystemConstants;
import com.itsol.quantrivanphong.manager.project.project.bussiness.ProjectBussiness;
import com.itsol.quantrivanphong.manager.project.project.dto.ProjectDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(value = "/quan-tri")
public class ProjectController {
@Autowired
private ProjectBussiness projectBussiness;
@GetMapping(value = "/danh-sach-du-an")
public ResponseEntity<List<ProjectDTO>> getAllProject(){
return ResponseEntity.ok(projectBussiness.findAllProject());
}
@GetMapping(value = "/chi-tiet-du-an/{id}",produces = SystemConstants.TYPE_JSON)
public ResponseEntity<ProjectDTO> findProjectId(@PathVariable Integer id){
ProjectDTO projectDTO = projectBussiness.findByProjectId(id);
return ResponseEntity.ok(projectDTO);
}
@PostMapping(value = "/them-du-an",consumes = SystemConstants.TYPE_JSON)
public ResponseEntity saveProject(@RequestBody ProjectDTO projectDTO){
String views = projectBussiness.saveProject(projectDTO);
return ResponseEntity.ok(views);
}
@PutMapping(value = "/sua-du-an",consumes = SystemConstants.TYPE_JSON)
public ResponseEntity updateProject(@RequestBody ProjectDTO projectDTO){
String views = projectBussiness.updateProject(projectDTO);
return ResponseEntity.ok(views);
}
@DeleteMapping(value = "/xoa-du-an",consumes = SystemConstants.TYPE_JSON)
public ResponseEntity deleteProject(@RequestBody ProjectDTO projectDTO){
String views = projectBussiness.deleteProject(projectDTO.getIds());
return ResponseEntity.ok(views);
}
}
package com.itsol.quantrivanphong.manager.project.project.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.sql.Timestamp;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProjectDTO {
private int id;
// tên project
private String name;
//mô tả ngắn
private String descriptions;
//ngày bắt đầu của dự án
private Timestamp startDate;
//ngày kết thúc dự án
private Timestamp endDate;
//trạng thái thêm vào dataBase
private Integer statusPost;
//trạng thái lấy dữ liệu lên cline
private String statusGet;
// danh sách id
private Integer[] ids;
}
package com.itsol.quantrivanphong.manager.reportdetail.repository;
package com.itsol.quantrivanphong.manager.project.project.repository;
import com.itsol.quantrivanphong.model.Project;
import org.springframework.data.jpa.repository.JpaRepository;
......@@ -6,13 +6,13 @@ import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface ProjectRepository extends JpaRepository<Project, Integer> {
public interface ProjectRRepository extends JpaRepository<Project, Integer> {
@Query(value = "SELECT p.id, p.name, p.descriptions, p.start_date, p.end_date, p.status FROM project p where p.status = 2", nativeQuery = true)
List<Project> listProjectWorking();
// @Query(value = "SELECT p.name FROM project p where p.id = ?1", nativeQuery = true)
// String ProjectName(int projectId);
@Query(value = "SELECT p.name FROM project p where p.id = ?1", nativeQuery = true)
String ProjectName(int projectId);
......
package com.itsol.quantrivanphong.manager.project.project.repository;
import com.itsol.quantrivanphong.report.issue.common.GennericeEntityManagerDao;
import com.itsol.quantrivanphong.model.Project;
public interface ProjectRepository extends GennericeEntityManagerDao<Integer, Project> {
}
package com.itsol.quantrivanphong.manager.project.project.repository;
import com.itsol.quantrivanphong.report.issue.common.AbstractEntityManagerDao;
import com.itsol.quantrivanphong.model.Project;
import org.springframework.stereotype.Repository;
@Repository
public class ProjectRepositoryImpl extends AbstractEntityManagerDao<Integer, Project> implements ProjectRepository{
}
package com.itsol.quantrivanphong.manager.project.projectgroup.bussiness;
import com.itsol.quantrivanphong.manager.project.projectgroup.dto.ProjectGroupDTO;
import java.util.List;
public interface ProjectGroupBussiness {
// chi tiết nhóm dự án
List<ProjectGroupDTO> getGroupByProjectId(Integer projectId);
// thêm thành viên vào nhóm dự án
String saveEmployeeProject(ProjectGroupDTO dto);
// sửa thông tin nhóm dự án, các thành viên out nhóm
String updateEmployeeProject(ProjectGroupDTO dto);
// Tìm kiếm thành viên trong nhóm theo tên đăng nhập
ProjectGroupDTO findEmployeeProject(String username);
// thành viên out dự án
String outProjectGroup(Integer[]ids);
}
package com.itsol.quantrivanphong.manager.project.projectgroup.bussiness;
import com.itsol.quantrivanphong.model.Project;
import com.itsol.quantrivanphong.manager.project.project.repository.ProjectRepository;
import com.itsol.quantrivanphong.manager.project.projectgroup.common.EmployeeRepositoryImpl;
import com.itsol.quantrivanphong.manager.project.projectgroup.common.ProjectGroupUtils;
import com.itsol.quantrivanphong.manager.project.projectgroup.dto.ProjectGroupDTO;
import com.itsol.quantrivanphong.model.Eproject;
import com.itsol.quantrivanphong.manager.project.projectgroup.repository.ProjectGroupRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProjectGroupBussinessImpl implements ProjectGroupBussiness {
@Autowired
private ProjectGroupRepository projectGroupRepository;
@Autowired
private ProjectRepository projectRepository;
@Autowired
private EmployeeRepositoryImpl employeeRepository;
@Autowired
private ProjectGroupUtils utils;
@Override
public List<ProjectGroupDTO> getGroupByProjectId(Integer projectId) {
Project project = projectRepository.findByEmtityId(projectId);
if (project != null) {
List<Eproject> lstModels = projectGroupRepository.finByProperty("project", project, "joinDate", "DESC");
List<ProjectGroupDTO> lstDTO = utils.getListDTO(lstModels);
return lstDTO;
}
return null;
}
@Override
public String saveEmployeeProject(ProjectGroupDTO dto) {
String views = "";
try{
projectGroupRepository.saveEntity(utils.Model(dto));
views="thêm thành công nhân viên vào nhóm dự án";
}catch (Exception e){
views="thêm không thành công!";
}
return views;
}
@Override
public String updateEmployeeProject(ProjectGroupDTO dto) {
String views="";
Eproject eproject = projectGroupRepository.findByEmtityId(dto.getId());
if(eproject!=null){
Eproject updateProjectGroup = projectGroupRepository.updateEntity(utils.Model(dto));
if(updateProjectGroup!=null){
views = "Sửa thành công";
}
}else{
views = "đối tượng không tồn tại";
}
return null;
}
@Override
public ProjectGroupDTO findEmployeeProject(String username) {
return null;
}
@Override
public String outProjectGroup(Integer[] ids) {
String views = "";
int count=0;
count = projectGroupRepository.deleteEntity(ids);
if(count!=0){
views="Bạn đã cho "+count+" thoát ra khỏi nhóm";
}else{
views=" thành viên không tồn tại";
}
return views;
}
}
package com.itsol.quantrivanphong.manager.project.projectgroup.common;
import com.itsol.quantrivanphong.model.Employee;
import com.itsol.quantrivanphong.report.issue.common.AbstractEntityManagerDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
@Service
public class EmployeeRepositoryImpl extends AbstractEntityManagerDao<Integer, Employee> {
private Logger logger = Logger.getLogger(EmployeeRepositoryImpl.class);
public Employee getEmployeeById(Integer employeeId) {
try {
Employee employee = findByEmtityId(employeeId);
if (employee != null) {
return employee;
}
} catch (Exception e) {
logger.info("( Lỗi tìm employee theo ID: )" + e.getMessage());
}
return null;
}
}
package com.itsol.quantrivanphong.manager.project.projectgroup.common;
import com.itsol.quantrivanphong.access.login.dto.EmployeeDTO;
import com.itsol.quantrivanphong.model.Employee;
import com.itsol.quantrivanphong.manager.project.project.dto.ProjectDTO;
import com.itsol.quantrivanphong.model.Project;
import com.itsol.quantrivanphong.manager.project.project.repository.ProjectRepository;
import com.itsol.quantrivanphong.manager.project.projectgroup.dto.ProjectGroupDTO;
import com.itsol.quantrivanphong.model.Eproject;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class ProjectGroupUtils {
private static Logger logger = Logger.getLogger(ProjectGroupUtils.class);
@Autowired
private EmployeeRepositoryImpl employeeRepository;
@Autowired
private ProjectRepository projectRepository;
public Eproject Model(ProjectGroupDTO dto){
Eproject model = new Eproject();
model.setId(dto.getId());
model.setJoinDate(dto.getJoinDate());
model.setOutDate(dto.getOutDate());
model.setPosition(dto.getPosition());
try{
Employee findEmployee = employeeRepository.getEmployeeById(dto.getUserId());
if(findEmployee!=null){
model.setEmployee(findEmployee);
}
}catch (Exception e){
logger.info("(Lỗi không tìm thấy Employee) "+e.getMessage());
}
try{
Project project = projectRepository.findByEmtityId(dto.getProjectId());
if(project!=null){
model.setProject(project);
}
}catch (Exception e){
logger.info("(Lỗi không tìm thấy Project) "+e.getMessage());
}
return model;
}
public ProjectGroupDTO DTO(Eproject models) {
ProjectGroupDTO dto = new ProjectGroupDTO();
dto.setId(models.getId());
// set project
ProjectDTO projectDTO = new ProjectDTO();
BeanUtils.copyProperties(models.getProject(),projectDTO);
dto.setProjectDTO(projectDTO);
// set employee
EmployeeDTO employeeDTO = new EmployeeDTO();
employeeDTO.setId(models.getEmployee().getId());
employeeDTO.setUsername(models.getEmployee().getUsername());
employeeDTO.setLastName(models.getEmployee().getLastName());
employeeDTO.setEmail(models.getEmployee().getEmailAddress());
employeeDTO.setFacebookProfile(models.getEmployee().getFacebookProfile());
employeeDTO.setSkype(models.getEmployee().getSkype());
dto.setEmployeeDTO(employeeDTO);
dto.setJoinDate(models.getJoinDate());
dto.setOutDate(models.getOutDate());
dto.setPosition(models.getPosition());
return dto;
}
public List<ProjectGroupDTO> getListDTO(List<Eproject> lstModel){
if(!lstModel.isEmpty()||lstModel.size()!=0){
List<ProjectGroupDTO> lstDTO = new ArrayList<ProjectGroupDTO>();
for (Eproject eproject:lstModel) {
lstDTO.add(DTO(eproject));
}
return lstDTO;
}
return null;
}
}
package com.itsol.quantrivanphong.manager.project.projectgroup.controller;
import com.itsol.quantrivanphong.report.issue.common.SystemConstants;
import com.itsol.quantrivanphong.manager.project.projectgroup.bussiness.ProjectGroupBussiness;
import com.itsol.quantrivanphong.manager.project.projectgroup.dto.ProjectGroupDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class ProjectGroupController {
@Autowired
private ProjectGroupBussiness projectGroupBussiness;
// thông tin của 1 nhóm dư án theo id của dự án
// Team lead,Hr
@GetMapping(value = "/thong-tin-du-an/{id}", produces = SystemConstants.TYPE_JSON)
public ResponseEntity<List<ProjectGroupDTO>> getOneProjectGroup(@PathVariable("id") Integer projectId) {
return ResponseEntity.ok(projectGroupBussiness.getGroupByProjectId(projectId));
}
// thêm thành viên vào dự án
// hr,manager, teamlead thêm thành viên
@PostMapping(value = "/them-thanh-vien", consumes = SystemConstants.TYPE_JSON, produces = SystemConstants.TYPE_JSON)
public ResponseEntity addMemberProject(@RequestBody ProjectGroupDTO projectGroupDTO) {
String views = projectGroupBussiness.saveEmployeeProject(projectGroupDTO);
return ResponseEntity.ok(views);
}
// cập nhật thông tin thành viên
// manager cập nhật chức vụ cho nhân viên vào xét duyệt vào dự án
@PutMapping(value = "/cap-nhat-thong-tin-thanh-vien",consumes = SystemConstants.TYPE_JSON, produces = SystemConstants.TYPE_JSON)
public ResponseEntity updateMemberProject(@RequestBody ProjectGroupDTO projectGroupDTO) {
String views = projectGroupBussiness.updateEmployeeProject(projectGroupDTO);
return ResponseEntity.ok(views);
}
// xóa thành viên ra khỏi dự án
@DeleteMapping(value = "/thanh-vien-out-du-an")
public ResponseEntity deleteMemberProject(@RequestBody ProjectGroupDTO projectGroupDTO){
String views = projectGroupBussiness.outProjectGroup(projectGroupDTO.getIds());
return ResponseEntity.ok(views);
}
}
package com.itsol.quantrivanphong.manager.project.projectgroup.dto;
import com.itsol.quantrivanphong.access.login.dto.EmployeeDTO;
import com.itsol.quantrivanphong.manager.project.project.dto.ProjectDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.sql.Timestamp;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProjectGroupDTO {
private int id;
// chức vụ trong project
private String position;
//ngày vào dự án
private Timestamp joinDate;
// ngày ra dự án
private Timestamp outDate;
private Integer userId;
private Integer projectId;
private EmployeeDTO employeeDTO;
private ProjectDTO projectDTO;
private Integer[]ids;
}
package com.itsol.quantrivanphong.manager.project.projectgroup.repository;
import com.itsol.quantrivanphong.report.issue.common.GennericeEntityManagerDao;
import com.itsol.quantrivanphong.model.Eproject;
public interface ProjectGroupRepository extends GennericeEntityManagerDao<Integer, Eproject> {
}
package com.itsol.quantrivanphong.manager.project.projectgroup.repository;
import com.itsol.quantrivanphong.report.issue.common.AbstractEntityManagerDao;
import com.itsol.quantrivanphong.model.Eproject;
import org.springframework.stereotype.Repository;
@Repository
public class ProjectGroupRepositoryImpl extends AbstractEntityManagerDao<Integer, Eproject> implements ProjectGroupRepository {
}
......@@ -2,12 +2,11 @@ package com.itsol.quantrivanphong.manager.reportdetail.bussiness;
import com.itsol.quantrivanphong.manager.reportdetail.dto.request.ReportDTO;
import com.itsol.quantrivanphong.manager.reportdetail.dto.response.ReportResponseDTO;
import com.itsol.quantrivanphong.manager.reportdetail.repository.EmployeeRepository;
import com.itsol.quantrivanphong.manager.reportdetail.repository.ProjectReportRepository;
import com.itsol.quantrivanphong.manager.reportdetail.repository.ProjectRepository;
import com.itsol.quantrivanphong.manager.project.project.repository.ProjectRRepository;
import com.itsol.quantrivanphong.model.Project;
import com.itsol.quantrivanphong.model.ProjectReport;
import com.itsol.quantrivanphong.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -16,7 +15,7 @@ import java.util.List;
@Service
public class ReportProjectBussiness {
@Autowired
private ProjectRepository projectRepository;
private ProjectRRepository projectRepository;
@Autowired
private EmployeeRepository employeeRepository;
......
package com.itsol.quantrivanphong.manager.reportdetail.repository;
import com.itsol.quantrivanphong.model.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface EmployeeRepository extends JpaRepository<Employee,Integer> {
//new
// @Query(value = "SELECT e.username FROM employee e JOIN eproject ep ON e.id = ep.employee_id JOIN project p ON ep.project_id = p.id WHERE p.id = ?1 AND ep.position = 'team_lead' GROUP BY e.id",nativeQuery = true)
// String findTeamLeader(int projectId);
//
// @Query(value = "SELECT COUNT(e.id)FROM employee e JOIN eproject ep ON e.id = ep.employee_id JOIN project p ON ep.project_id = p.id WHERE p.id = ?1 AND ep.position = 'member'", nativeQuery = true)
// int numberOfMember(int projectId);
}
......@@ -7,11 +7,12 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name ="employee")
@Table(name = "employee")
@Data
@NoArgsConstructor
@AllArgsConstructor
......@@ -27,6 +28,9 @@ public class Employee {
@Column(name = "password", length = 128)
private String password;
@Column(name = "confirm_password")
@Size(min = 5, max = 20)
private String confirmPassword;
@Column(name = "first_name", length = 50)
private String firstName;
......
package com.itsol.quantrivanphong.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.itsol.quantrivanphong.model.Employee;
import com.itsol.quantrivanphong.model.TimeSheet;
import com.itsol.quantrivanphong.model.Project;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
......@@ -20,21 +24,19 @@ public class Eproject {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, unique = true)
private int id;
// chức vụ trong project
@Column(name = "position", nullable = false)
private String position;
//ngày vào dự án
@Column(name = "join_date",nullable =false)
private Timestamp joinDate;
// ngày ra dự án
@Column(name = "out_date",nullable = true)
private Timestamp outDate;
@Column(name = "join_date")
private String joinDate;
@Column(name = "out_date")
private String outDate;
// @JsonIgnore
@ManyToOne(fetch = FetchType.EAGER)
private Employee employee;
// @JsonIgnore
@ManyToOne(fetch = FetchType.EAGER)
private Project project;
......
package com.itsol.quantrivanphong.model;
import com.itsol.quantrivanphong.model.Project;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
......@@ -17,17 +18,16 @@ public class Issues {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, unique = true)
private int id;
// tiêu đề liên quan
@Column(name = "title")
private String title;
//nội dung
@Column(name = "content")
private String actionCode;
// trạng thái vấn đề đó trong project
@Column(name = "status")
private boolean status;
// @JsonIgnore
@ManyToOne(fetch = FetchType.EAGER)
private Project project;
}
......@@ -7,6 +7,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
......@@ -22,20 +23,22 @@ public class Project {
@Column(name = "id", nullable = false, unique = true)
private int id;
// tên project
@Column(name = "name", nullable = false)
private String name;
//mô tả ngắn
@Column(name = "descriptions")
private String descriptions;
//ngày bắt đầu của dự án
@Column(name = "start_date", nullable = false)
private String startDate;
@Column(name = "end_date", nullable = false)
private String endDate;
@Column(name = "status")
private int status;
private Timestamp startDate;
//ngày kết thúc dự án
@Column(name = "end_date")
private Timestamp endDate;
//trạng thái
@Column(name = "status",nullable = false)
private Integer status;
@JsonIgnore
@OneToMany(mappedBy = "project", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
......
......@@ -24,9 +24,8 @@ public class Role {
@Column(name = "role_name", nullable = false, unique = true)
private String roleName;
@JsonIgnore
@OneToMany(mappedBy = "role", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<RoleDetail> roleDetails = new ArrayList<>();
@Column(name = "role_code", nullable = false, unique = true)
private String roleCode;
@JsonIgnore
@OneToMany(mappedBy = "role", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
......
package com.itsol.quantrivanphong.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "role_detail")
public class RoleDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, unique = true)
private int id;
@Column(name = "action_name", length = 50)
private String actionName;
@Column(name = "action_code", length = 50)
private String actionCode;
@Column(name = "status")
private boolean status;
// @JsonIgnore
@ManyToOne(fetch = FetchType.EAGER)
private Role role;
}
......@@ -22,19 +22,19 @@ public class TimeSheet extends DateAudit {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, unique = true)
private int id;
// tiêu đề
@Column(name = "title")
private String title;
// nội dung
@Column(name = "content")
private String content;
// ghi chú
@Column(name = "note")
private String note;
// Duyệt, Chưa duyệt, Từ chối
@Column(name = "checked")
private String checked;
// trạng thái
@Column(name = "status")
private boolean status;
......
package com.itsol.quantrivanphong.report.employee;
public class Test {
}
package com.itsol.quantrivanphong.report.issue.common;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.springframework.beans.factory.annotation.Autowired;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
public class AbstractEntityManagerDao<ID extends Serializable, T> implements GennericeEntityManagerDao<ID, T> {
@Autowired
EntityManager entityManager;
@Autowired
EntityManagerFactory entityManagerFactory;
private final static Logger log = Logger.getLogger(AbstractEntityManagerDao.class);
private Class<T> persistenceClass;
// Lấy Entity T trong Generic
public AbstractEntityManagerDao() {
this.persistenceClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
}
// get persistenceClass
public String getPersistenceClass() {
return persistenceClass.getSimpleName();
}
public List<T> finAllEntity() {
log.info("find All record from db");
List<T> list = new ArrayList<T>();
try {
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
StringBuilder sql = new StringBuilder(" from ");
sql.append(this.getPersistenceClass());
list = entityManager.createQuery(sql.toString(), persistenceClass).getResultList();
} catch (HibernateException e) {
log.info(e.getMessage());
} finally {
if (entityManager != null) {
entityManager.close();
}
}
return list;
}
public void saveEntity(T t) {
log.info("save object");
try {
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(t);
entityManager.getTransaction().commit();
} catch (HibernateException e) {
entityManager.getTransaction().rollback();
log.info(e.getMessage());
} finally {
if (entityManager != null) {
entityManager.close();
}
}
}
public T updateEntity(T t) {
log.info("update object");
T entity = null;
try {
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entity = entityManager.merge(t);
entityManager.getTransaction().commit();
return entity;
} catch (HibernateException e) {
entityManager.getTransaction().rollback();
log.info(e.getMessage());
} finally {
if (entityManager != null) {
entityManager.close();
}
}
return entity;
}
public Integer deleteEntity(ID[] ids) {
log.info("delete by id ");
Integer count = 0;
try {
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
for (ID id : ids) {
T entity = entityManager.find(persistenceClass, id);
if (entity != null) {
entityManager.remove(entity);
count++;
}
}
entityManager.getTransaction().commit();
} catch (HibernateException e) {
entityManager.getTransaction().rollback();
log.info(e.getMessage());
} finally {
if (entityManager != null) {
entityManager.close();
}
}
return count;
}
@Override
public T findByEmtityId(ID id) {
log.info("find by id");
T entity = null;
try {
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entity = entityManager.find(persistenceClass,id);
entityManager.getTransaction().commit();
} catch (Exception e) {
entityManager.getTransaction().rollback();
log.info(e.getMessage());
} finally {
if (entityManager != null) {
entityManager.close();
}
}
return entity;
}
// Tìm kiếm 1 list danh sách theo value sắp xếp theo ASC or DESC size của list
@Override
public List<T> finByProperty(String property, Object value, String sortExperssion, String sortDirection) {
log.info("find by value");
List<T> list = new ArrayList<T>();
try {
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
StringBuilder sql = new StringBuilder(" from ");
sql.append(getPersistenceClass());
if(property!=null && value !=null) {
sql.append(" where ").append(property).append(" = ?1");
}
if(sortExperssion!=null && sortDirection!=null) {
sql.append(" order by ").append(sortExperssion);
sql.append(" "+(sortDirection.equals("ASC")?"asc":"desc"));
}
TypedQuery<T> query1 = entityManager.createQuery(sql.toString(),persistenceClass);
list = query1.setParameter(1,value).getResultList();
} catch (HibernateException e) {
entityManager.getTransaction().rollback();
log.info(e.getMessage());
}finally {
entityManager.close();
}
return list;
}
}
package com.itsol.quantrivanphong.report.issue.common;
import java.io.Serializable;
import java.util.List;
public interface GennericeEntityManagerDao<ID extends Serializable,T> {
List<T> finAllEntity();
void saveEntity(T entity);
T updateEntity(T entity);
Integer deleteEntity(ID[] ids);
T findByEmtityId(ID id);
List<T> finByProperty(String property, Object value, String sortExperssion, String sortDirection);
}
package com.itsol.quantrivanphong.report.issue.common;
public class SystemConstants {
public static final String TYPE_JSON = "application/json";
}
package com.itsol.quantrivanphong.report.issue.repository;
import com.itsol.quantrivanphong.report.issue.common.GennericeEntityManagerDao;
import com.itsol.quantrivanphong.model.Issues;
public interface IssueRepository extends GennericeEntityManagerDao<Integer, Issues> {
}
package com.itsol.quantrivanphong.report.issue.repository;
import com.itsol.quantrivanphong.report.issue.common.AbstractEntityManagerDao;
import com.itsol.quantrivanphong.model.Issues;
import org.springframework.stereotype.Repository;
@Repository
public class IssueRepositoryImpl extends AbstractEntityManagerDao<Integer, Issues> implements IssueRepository{
}
package com.itsol.quantrivanphong.repository;
import com.itsol.quantrivanphong.model.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
public interface EmployeeRepository extends JpaRepository<Employee,Integer > {
public Employee findEmployeeByUsername(String username);
public Employee findEmployeeByEmailAddress(String emailAddress);
public Employee findEmployeeByUsernameAndPassword(String username, String password);
Employee findByEmailAddress(String emailAddress);
//==================================================================================================================
//Emplyee Repository Of Hieunv
@Query(value = "SELECT e.username FROM employee e JOIN eproject ep ON e.id = ep.employee_id JOIN project p ON ep.project_id = p.id WHERE p.id = ?1 AND ep.position = 'team_lead' GROUP BY e.id",nativeQuery = true)
String findTeamLeader(int projectId);
@Query(value = "SELECT COUNT(e.id)FROM employee e JOIN eproject ep ON e.id = ep.employee_id JOIN project p ON ep.project_id = p.id WHERE p.id = ?1 AND ep.position = 'member'", nativeQuery = true)
int numberOfMember(int projectId);
}
......@@ -7,6 +7,7 @@ spring.datasource.url=jdbc:mysql://localhost:3306/quantrivanphong
spring.datasource.username=root
spring.datasource.password=
# ===============================
# JPA / HIBERNATE
# ===============================
......@@ -16,6 +17,7 @@ spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialec
#spring.jpa.properties.hibernate.default_schema=qlns_itsol
# ===============================
# SEND EMAIL
# ==============================
......
# Root logger option
log4j.rootLogger=DEBUG, stdout, file
# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Redirect log messages to a log file, support file rolling.
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=D:\\application1.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
\ No newline at end of file
<!-- Sticky Footer -->
<footer class="sticky-footer">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>PS: Phung Van Dung</span>
</div>
</div>
</footer>
\ No newline at end of file
<nav class="navbar navbar-expand navbar-dark bg-dark static-top">
<a class="navbar-brand mr-1" href="index.html">Trang Quản Trị</a>
<!-- Navbar Search -->
<form class="d-none d-md-inline-block form-inline ml-auto mr-0 mr-md-3 my-2 my-md-0">
</form>
<!-- Navbar -->
<ul class="navbar-nav ml-auto ml-md-0">
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fas fa-user-circle fa-fw"></i>Admin
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">Profile</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">Logout</a>
</div>
</li>
</ul>
</nav>
\ No newline at end of file
<div id="wrapper">
<!-- Sidebar -->
<ul class="sidebar navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="pagesDropdown" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fas fa-fw fa-folder"></i>
<span>Quản Trị Văn Phòng</span>
</a>
<div class="dropdown-menu" aria-labelledby="pagesDropdown">
<h6 class="dropdown-header">Quản Trị</h6>
<a class="dropdown-item" data-ng-href="/project/danh-sach-tat-ca-du-an.html">Dự Án</a>
<a class="dropdown-item" href="#">Nhân Viên</a>
<a class="dropdown-item" href="#">Báo Cáo</a>
<a class="dropdown-item" href="#">Tin Tức</a>
<div class="dropdown-divider">aaa</div>
<h6 class="dropdown-header">Báo Cáo</h6>
<a class="dropdown-item" href="#">Xin Phép</a>
<a class="dropdown-item" href="#">Time Sheet</a>
<a class="dropdown-item" href="#">Quản lý Issuses</a>
</div>
</li>
</ul>
</div>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
\ No newline at end of file
<!DOCTYPE HTML>
<html>
<head>
<title>Business_Blog a Blogging Category Flat Bootstrap Responsive Website Template | World :: w3layouts</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="keywords" content="Business_Blog Responsive web template, Bootstrap Web Templates, Flat Web Templates, Android Compatible web template,
Smartphone Compatible web template, free webdesigns for Nokia, Samsung, LG, SonyErricsson, Motorola web design" />
<script type="applijewelleryion/x-javascript"> addEventListener("load", function() { setTimeout(hideURLbar, 0); }, false); function hideURLbar(){ window.scrollTo(0,1); } </script>
<link href="css/bootstrap.css" rel='stylesheet' type='text/css' />
<!-- Custom Theme files -->
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed:400,700" rel='stylesheet' type='text/css'>
<link href="https://fonts.googleapis.com/css?family=Open+Sans" type='text/css'>
<link href="css/style.css" rel='stylesheet' type='text/css' />
<!--Khai báo các thư viện-->
<script src="js/jquery-3.2.1.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/angular.js"></script>
<script src="js/angular-ui-router.min.js"></script>
<!--End khai báo thư viện-->
<!--Khai báo các file js-->
<script src="js/app.js"></script>
<!--End khai báo các file js-->
<!-- khai báo các controllers -->
<script src="pages/employee/employeeController.js"></script>
<!--End khai báo controllers-->
</head>
<body ng-app="myApp">
<!--start-main-->
<div class="container">
</div>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
*
*/
angular.module("myApp", ["ui.router"]).config(function($stateProvider, $urlRouterProvider,$locationProvider) {
$locationProvider.hashPrefix('');
$urlRouterProvider.otherwise("/index");
$stateProvider
//index layout riêng
.state("index", {
url: "/index",
views:{
"index":{
templateUrl: "pages/index/index.htm",
controller: "indexController"
},
"banner":{
templateUrl: "pages/index/banner.htm"
}
}
})
// State chứa layout chung cho các trang
.state('app', {
abstract: true,
views: {
'main_layout': {
templateUrl: 'main_layout.html',
}
}
})
// Các state bên dưới kế thừa state app
.state("tintuc", { // Khai báo một state
parent: 'app',
url: "/tintuc", // URL hiển thị
views:{
"content":{
templateUrl: "pages/tintuc/tintuc.htm",
controller: "tintucController" // khai báo controller
}
}
})
.state("tuyendung", {
parent: 'app',
url: "/tuyendung",
views:{
"content":{
templateUrl: "pages/tuyendung/tuyendung.htm",
controller: "tuyendungController"
}
}
})
// .state("lienhe", {
// parent: 'app',
// url: "/lienhe",
// views:{
// "content":{
// templateUrl: "pages/lienhe/lienhe.htm",
// controller: "lienheController"
// }
// }
// })
.state("gioithieu", {
parent: 'app',
url: "/gioithieu",
views:{
"content":{
templateUrl: "pages/gioithieu/gioithieu.htm",
controller: "gioithieuController"
}
}
})
});
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!-- technology -->
<div class="technology-1">
<div class="container">
<div class="col-md-9 technology-left">
<div ui-view="content">
<!-- nội dung các trang -->
</div>
</div>
<!-- technology-right -->
<div class="col-md-3 technology-right-1">
<div class="blo-top">
<div class="tech-btm">
<img src="images/banner1.jpg" class="img-responsive" alt=""/>
</div>
</div>
<div class="blo-top">
<div class="tech-btm">
<h4>Sign up to our newsletter</h4>
<p>Pellentesque dui, non felis. Maecenas male</p>
<div class="name">
<form>
<input type="text" placeholder="Email" required="">
</form>
</div>
<div class="button">
<form>
<input type="submit" value="Subscribe">
</form>
</div>
<div class="clearfix"> </div>
</div>
</div>
<div class="blo-top1">
<div class="tech-btm">
<h4>Tin tức nổi bật </h4>
<div class="blog-grids">
<div class="blog-grid-left">
<a href="singlepage.html"><img src="images/6.jpg" class="img-responsive" alt=""/></a>
</div>
<div class="blog-grid-right">
<h5><a href="singlepage.html">Pellentesque dui, non felis. Maecenas male</a> </h5>
</div>
<div class="clearfix"> </div>
</div>
<div class="blog-grids">
<div class="blog-grid-left">
<a href="singlepage.html"><img src="images/7.jpg" class="img-responsive" alt=""/></a>
</div>
<div class="blog-grid-right">
<h5><a href="singlepage.html">Pellentesque dui, non felis. Maecenas male</a> </h5>
</div>
<div class="clearfix"> </div>
</div>
<div class="blog-grids">
<div class="blog-grid-left">
<a href="singlepage.html"><img src="images/11.jpg" class="img-responsive" alt=""/></a>
</div>
<div class="blog-grid-right">
<h5><a href="singlepage.html">Pellentesque dui, non felis. Maecenas male</a> </h5>
</div>
<div class="clearfix"> </div>
</div>
<div class="blog-grids">
<div class="blog-grid-left">
<a href="singlepage.html"><img src="images/9.jpg" class="img-responsive" alt=""/></a>
</div>
<div class="blog-grid-right">
<h5><a href="singlepage.html">Pellentesque dui, non felis. Maecenas male</a> </h5>
</div>
<div class="clearfix"> </div>
</div>
<div class="blog-grids">
<div class="blog-grid-left">
<a href="singlepage.html"><img src="images/10.jpg" class="img-responsive" alt=""/></a>
</div>
<div class="blog-grid-right">
<h5><a href="singlepage.html">Pellentesque dui, non felis. Maecenas male</a> </h5>
</div>
<div class="clearfix"> </div>
</div>
</div>
</div>
</div>
<div class="clearfix"></div>
<!-- technology-right -->
</div>
</div>
<!-- technology -->
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8">
<div>
<legend>Employee Details</legend>
<table>
<tr>
<td><label>User Name</label></td>
<td>
<input type="text" maxlength="29" ng-model="emp.username"/>
</td>
</tr>
<tr>
<td><label>First Name</label></td>
<td>
<input type="text" maxlength="29" ng-model="emp.firstName"/>
</td>
</tr>
<tr>
<td><label>Last Name</label></td>
<td>
<input type="text" maxlength="29" ng-model="emp.lastName"/>
</td>
</tr>
<tr>
<td><label id="email" for="email">Email</label> </td>
<td>
<input type="email" maxlength="150" ng-model="emp.emailAddress"/>
</td>
</tr>
<tr>
<td><label>Phone</label></td>
<td>
<input type="text" maxlength="10" value="" ng-model="emp.phoneNumber"/>
</td>
</tr>
<tr>
<td><label>education:</label></td>
<td>
<input ng-model="emp.education"/>
</td>
</tr>
<tr>
<td><label >home town:</label></td>
<td> <input type="text" ng-model="emp.homeTown"/></td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" name="submit" value="submit" ng-click="save();"/>
<input type="submit" name="clear" value="clear" ng-click=" emp = null"/>
</td>
</tr>
</table>
</div>
<div>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>User Name</th>
<th>First Name</th>
<th>Last Name</th>
<th>EmailAddress</th>
<th>Phone</th>
<th>Education</th>
<th>Home Town</th>
</tr>
</thead>
<tbody>
<tr class="vide" ng-repeat="emp in employess">
<td>{{$index + 1}}</td>
<td>{{emp.username}}</td>
<td>{{emp.firstName}}</td>
<td>{{emp.lastName}}</td>
<td>{{emp.emailAddress}}</td>
<td>{{emp.phoneNumber}}</td>
<td>{{emp.education}}</td>
<td>{{emp.homeTown}}</td>
<td><a href="#" ng-click="update(emp);">Update</a>
<td><a href="#" confirmed-click="delete(employee);" ng-confirm-click=" Do you want to delete this user?">Delete</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
/**
*
*/
angular.module("myApp",[]).controller("tintucController", function($scope, $http,$window) {
console.log("Tin tức controller");
$scope.emp= {
"username": "",
"password": "",
"firstName": "",
"lastName": "",
"emailAddress": "",
"phoneNumber": "",
"homeTown": "",
"education": ""
};
$scope.save = save;
function save(){
console.log($scope.emp);
$http({
method : 'POST',
url : "http://localhost:8081/list_employee/",
data: $scope.emp
}).then(function successCallback(response) {
console.log(response);
// $window.location.href ='http://localhost:8081/#/tintuc';
}, function errorCallback(response) {
console.log(response)
});
}
$scope.update = update;
function update(employee){
$scope.employee = employee;
list_employee();
}
$scope.deleteEmployee = function (employee) {
$http({
method : 'DELETE',
url : 'http://localhost:8081/deleteEmployee/' + employee.id
}).then(_success, _error);
}
$http({
method : 'GET',
url : "http://localhost:8081/list_employee/",
}).then(function successCallback(response) {
console.log(response)
$scope.employess=response.data;
}, function errorCallback(response) {
console.log(response)
});
});
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Nhóm Dự Án</title>
</head>
<body>
</body>
</html>
\ No newline at end of file
<div class="card-header">
<i class="fas fa-table"></i> Thêm mới dự án
</div>
<div class="card-body" ng-app="insertProjectModule">
<form ng-controller="insertProject">
<div class="form-group">
<div class="form-row">
<div class="col-md-6">
<div class="form-label-group">
<input type="text" ng-model="lstProject.name" id="name" class="form-control"
placeholder="Tên Dự Án"
required="required" autofocus="autofocus">
<label for="name">Tên Dự Án</label>
<span>{{lstProject.name}}</span>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" ng-model="lstProject.descriptions" id="descriptions"
class="form-control"
placeholder="Mô tả ngắn"
required="required">
<label for="descriptions">Mô tả ngắn</label>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="form-row">
<div class="col-md-6">
<div class="form-label-group">
<input type="text" ng-model="lstProject.startDate" id="startDate" class="form-control"
placeholder="Ngày Bắt Đầu" required="required">
<label for="startDate">Ngày Bắt Đầu</label>
</div>
</div>
<div class="col-md-6">
<div class="form-label-group">
<input type="text" ng-model="lstProject.endDate" id="endDate" class="form-control"
placeholder="nick skype" required="required">
<label for="endDate">Ngày Kết Thuc</label>
</div>
</div>
</div>
</div>
<div>
<input ng-click="insert_project()" type="submit" value="Lưu">
<input type="reset" value="Reset">
</div>
</form>
</div>
<script src="components/project/projectAddController.js"></script>
\ No newline at end of file
<div class="card mb-3">
<div class="card-header">
<i class="fas fa-table"></i> Danh Sách Dự Án
</div>
<div class="card-body" ng-app="GetAPI">
<div class="table-responsive" ng-controller="showProject">
<a href="#" class="btn btn-primary btn-circle btn-sm" style="margin-bottom: 10px;"> Thêm </a>
<table class="table table-bordered" id="dataTable" width="100%"
cellspacing="0">
<thead>
<tr>
<th>Tên Dự Án</th>
<th>Mô tả ngắn</th>
<th>Ngày bắt đầu</th>
<th>Hạn giao</th>
<th>Trạng Thái</th>
<th>Thao Tác</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="project in listProject">
<td>{{ project.name }}</td>
<td>{{ project.descriptions }}</td>
<td>{{ project.startDate | date:"dd/MM/yyyy" }}</td>
<td>{{ project.endDate | date:"dd/MM/yyyy" }}</td>
<td>{{ project.statusGet }}</td>
<td><a data-ng-href="#" class="btn btn-info btn-circle btn-sm">
Xem </a> <a data-ng-href="#" class="btn btn-warning btn-circle btn-sm">
Sửa </a> <a data-ng-href="#" class="btn btn-danger btn-circle btn-sm">Xóa</a>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!--angular js-->
<script src="components/project/projectController.js"></script>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
table.dataTable {
clear: both;
margin-top: 6px !important;
margin-bottom: 6px !important;
max-width: none !important;
border-collapse: separate !important;
border-spacing: 0;
}
table.dataTable td,
table.dataTable th {
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
table.dataTable td.dataTables_empty,
table.dataTable th.dataTables_empty {
text-align: center;
}
table.dataTable.nowrap th,
table.dataTable.nowrap td {
white-space: nowrap;
}
div.dataTables_wrapper div.dataTables_length label {
font-weight: normal;
text-align: left;
white-space: nowrap;
}
div.dataTables_wrapper div.dataTables_length select {
width: auto;
display: inline-block;
}
div.dataTables_wrapper div.dataTables_filter {
text-align: right;
}
div.dataTables_wrapper div.dataTables_filter label {
font-weight: normal;
white-space: nowrap;
text-align: left;
}
div.dataTables_wrapper div.dataTables_filter input {
margin-left: 0.5em;
display: inline-block;
width: auto;
}
div.dataTables_wrapper div.dataTables_info {
padding-top: 0.85em;
white-space: nowrap;
}
div.dataTables_wrapper div.dataTables_paginate {
margin: 0;
white-space: nowrap;
text-align: right;
}
div.dataTables_wrapper div.dataTables_paginate ul.pagination {
margin: 2px 0;
white-space: nowrap;
justify-content: flex-end;
}
div.dataTables_wrapper div.dataTables_processing {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
margin-left: -100px;
margin-top: -26px;
text-align: center;
padding: 1em 0;
}
table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
table.dataTable thead > tr > td.sorting_asc,
table.dataTable thead > tr > td.sorting_desc,
table.dataTable thead > tr > td.sorting {
padding-right: 30px;
}
table.dataTable thead > tr > th:active,
table.dataTable thead > tr > td:active {
outline: none;
}
table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc,
table.dataTable thead .sorting_asc_disabled,
table.dataTable thead .sorting_desc_disabled {
cursor: pointer;
position: relative;
}
table.dataTable thead .sorting:before, table.dataTable thead .sorting:after,
table.dataTable thead .sorting_asc:before,
table.dataTable thead .sorting_asc:after,
table.dataTable thead .sorting_desc:before,
table.dataTable thead .sorting_desc:after,
table.dataTable thead .sorting_asc_disabled:before,
table.dataTable thead .sorting_asc_disabled:after,
table.dataTable thead .sorting_desc_disabled:before,
table.dataTable thead .sorting_desc_disabled:after {
position: absolute;
bottom: 0.9em;
display: block;
opacity: 0.3;
}
table.dataTable thead .sorting:before,
table.dataTable thead .sorting_asc:before,
table.dataTable thead .sorting_desc:before,
table.dataTable thead .sorting_asc_disabled:before,
table.dataTable thead .sorting_desc_disabled:before {
right: 1em;
content: "\2191";
}
table.dataTable thead .sorting:after,
table.dataTable thead .sorting_asc:after,
table.dataTable thead .sorting_desc:after,
table.dataTable thead .sorting_asc_disabled:after,
table.dataTable thead .sorting_desc_disabled:after {
right: 0.5em;
content: "\2193";
}
table.dataTable thead .sorting_asc:before,
table.dataTable thead .sorting_desc:after {
opacity: 1;
}
table.dataTable thead .sorting_asc_disabled:before,
table.dataTable thead .sorting_desc_disabled:after {
opacity: 0;
}
div.dataTables_scrollHead table.dataTable {
margin-bottom: 0 !important;
}
div.dataTables_scrollBody table {
border-top: none;
margin-top: 0 !important;
margin-bottom: 0 !important;
}
div.dataTables_scrollBody table thead .sorting:before,
div.dataTables_scrollBody table thead .sorting_asc:before,
div.dataTables_scrollBody table thead .sorting_desc:before,
div.dataTables_scrollBody table thead .sorting:after,
div.dataTables_scrollBody table thead .sorting_asc:after,
div.dataTables_scrollBody table thead .sorting_desc:after {
display: none;
}
div.dataTables_scrollBody table tbody tr:first-child th,
div.dataTables_scrollBody table tbody tr:first-child td {
border-top: none;
}
div.dataTables_scrollFoot > .dataTables_scrollFootInner {
box-sizing: content-box;
}
div.dataTables_scrollFoot > .dataTables_scrollFootInner > table {
margin-top: 0 !important;
border-top: none;
}
@media screen and (max-width: 767px) {
div.dataTables_wrapper div.dataTables_length,
div.dataTables_wrapper div.dataTables_filter,
div.dataTables_wrapper div.dataTables_info,
div.dataTables_wrapper div.dataTables_paginate {
text-align: center;
}
}
table.dataTable.table-sm > thead > tr > th {
padding-right: 20px;
}
table.dataTable.table-sm .sorting:before,
table.dataTable.table-sm .sorting_asc:before,
table.dataTable.table-sm .sorting_desc:before {
top: 5px;
right: 0.85em;
}
table.dataTable.table-sm .sorting:after,
table.dataTable.table-sm .sorting_asc:after,
table.dataTable.table-sm .sorting_desc:after {
top: 5px;
}
table.table-bordered.dataTable th,
table.table-bordered.dataTable td {
border-left-width: 0;
}
table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child,
table.table-bordered.dataTable td:last-child,
table.table-bordered.dataTable td:last-child {
border-right-width: 0;
}
table.table-bordered.dataTable tbody th,
table.table-bordered.dataTable tbody td {
border-bottom-width: 0;
}
div.dataTables_scrollHead table.table-bordered {
border-bottom-width: 0;
}
div.table-responsive > div.dataTables_wrapper > div.row {
margin: 0;
}
div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:first-child {
padding-left: 0;
}
div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:last-child {
padding-right: 0;
}
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment