Compare commits
No commits in common. "60ae3c3197a3af7bff1c01553203be3430c419c3" and "a4978fd2afb49cd2061b14ba5ec9404cb36dfe78" have entirely different histories.
60ae3c3197
...
a4978fd2af
15
.vscode/launch.json
vendored
15
.vscode/launch.json
vendored
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"type": "java",
|
|
||||||
"name": "SeminarApplication",
|
|
||||||
"request": "launch",
|
|
||||||
"mainClass": "ru.ulstu.SeminarApplication",
|
|
||||||
"projectName": "seminar"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"java.compile.nullAnalysis.mode": "automatic"
|
|
||||||
}
|
|
@ -33,8 +33,8 @@ dependencies {
|
|||||||
implementation group: 'com.h2database', name:'h2'
|
implementation group: 'com.h2database', name:'h2'
|
||||||
implementation group: 'jakarta.xml.bind', name: 'jakarta.xml.bind-api', version: '4.0.2'
|
implementation group: 'jakarta.xml.bind', name: 'jakarta.xml.bind-api', version: '4.0.2'
|
||||||
implementation group: 'org.javassist', name: 'javassist', version: '3.30.2-GA'
|
implementation group: 'org.javassist', name: 'javassist', version: '3.30.2-GA'
|
||||||
|
implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-blackbird'
|
||||||
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.8.4'
|
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.13.2'
|
||||||
|
|
||||||
implementation group: 'org.eclipse.jetty', name: 'jetty-servlets', version: '11.0.24'
|
implementation group: 'org.eclipse.jetty', name: 'jetty-servlets', version: '11.0.24'
|
||||||
|
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package ru.ulstu.admin.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import ru.ulstu.admin.model.ReportForm;
|
||||||
|
import ru.ulstu.admin.service.AdminReportService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/admin")
|
||||||
|
public class AdminReportController {
|
||||||
|
|
||||||
|
private final AdminReportService adminReportService;
|
||||||
|
|
||||||
|
public AdminReportController(AdminReportService adminReportService) {
|
||||||
|
this.adminReportService = adminReportService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/report")
|
||||||
|
public String getReportForm(Model model) {
|
||||||
|
ReportForm reportForm = new ReportForm();
|
||||||
|
|
||||||
|
//todo get current user aspirant id
|
||||||
|
//reportForm.setAspirantId(aspirantId); // Устанавливаем ID аспиранта
|
||||||
|
model.addAttribute("report", reportForm);
|
||||||
|
return "admin/aspirantReport"; // Возвращает шаблон report.html
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/saveReport")
|
||||||
|
public String saveReport(@ModelAttribute ReportForm reportForm,
|
||||||
|
@RequestParam("file") List<MultipartFile> files) {
|
||||||
|
// Сохраняем отчет
|
||||||
|
adminReportService.saveReport(reportForm);
|
||||||
|
|
||||||
|
// Обработка загруженных файлов
|
||||||
|
if (!files.isEmpty()) {
|
||||||
|
for (MultipartFile file : files) {
|
||||||
|
System.out.println("Файл: " + file.getOriginalFilename());
|
||||||
|
// Здесь можно добавить логику сохранения файла на сервере
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "redirect:/admin/aspirants"; // Перенаправление на список аспирантов
|
||||||
|
}
|
||||||
|
}
|
@ -7,9 +7,6 @@ import ru.ulstu.aspirant.service.AspirantService;
|
|||||||
import ru.ulstu.manager.model.Manager;
|
import ru.ulstu.manager.model.Manager;
|
||||||
import ru.ulstu.manager.service.ManagerService;
|
import ru.ulstu.manager.service.ManagerService;
|
||||||
import ru.ulstu.model.User;
|
import ru.ulstu.model.User;
|
||||||
import ru.ulstu.model.UserRole;
|
|
||||||
import ru.ulstu.model.UserRoleConstants;
|
|
||||||
import ru.ulstu.user.UserRoleRepository;
|
|
||||||
import ru.ulstu.user.UserService;
|
import ru.ulstu.user.UserService;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -19,16 +16,13 @@ public class AdminAspirantService {
|
|||||||
private final AspirantService aspirantService;
|
private final AspirantService aspirantService;
|
||||||
private final ManagerService managerService;
|
private final ManagerService managerService;
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
private final UserRoleRepository userRoleRepository;
|
|
||||||
|
|
||||||
public AdminAspirantService(AspirantService aspirantService,
|
public AdminAspirantService(AspirantService aspirantService,
|
||||||
ManagerService managerService,
|
ManagerService managerService,
|
||||||
UserService userService,
|
UserService userService) {
|
||||||
UserRoleRepository userRoleRepository) {
|
|
||||||
this.aspirantService = aspirantService;
|
this.aspirantService = aspirantService;
|
||||||
this.managerService = managerService;
|
this.managerService = managerService;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.userRoleRepository = userRoleRepository;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Aspirant> getAspirants() {
|
public List<Aspirant> getAspirants() {
|
||||||
@ -52,18 +46,10 @@ public class AdminAspirantService {
|
|||||||
aspirant.setBirthDate(aspirantForm.getBirthDate());
|
aspirant.setBirthDate(aspirantForm.getBirthDate());
|
||||||
aspirant.setSpeciality(aspirantForm.getSpeciality());
|
aspirant.setSpeciality(aspirantForm.getSpeciality());
|
||||||
aspirant.setTheme(aspirantForm.getTheme());
|
aspirant.setTheme(aspirantForm.getTheme());
|
||||||
User user;
|
User user = userService.getUserById(aspirantForm.getUserId());
|
||||||
if (aspirantForm.getUserId() != null) {
|
if (!user.getLogin().equals(aspirantForm.getEmail())) {
|
||||||
user = userService.getUserById(aspirantForm.getUserId());
|
user.setLogin(aspirantForm.getEmail());
|
||||||
if (!user.getLogin().equals(aspirantForm.getEmail())) {
|
userService.createUser(user);
|
||||||
user.setLogin(aspirantForm.getEmail());
|
|
||||||
if (user.getRoles().stream().anyMatch(r -> !r.getName().equals(UserRoleConstants.ASPIRANT))) {
|
|
||||||
user.getRoles().add(userRoleRepository.save(new UserRole(UserRoleConstants.ASPIRANT)));
|
|
||||||
}
|
|
||||||
userService.createUser(user);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
user = userService.createAspirant(aspirantForm.getEmail());
|
|
||||||
}
|
}
|
||||||
aspirant.setUser(user);
|
aspirant.setUser(user);
|
||||||
|
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package ru.ulstu.aspirant.controller;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import ru.ulstu.aspirant.model.Report;
|
||||||
|
import ru.ulstu.aspirant.service.AspirantService;
|
||||||
|
import ru.ulstu.indicator.model.Indicator;
|
||||||
|
import ru.ulstu.model.OffsetablePageRequest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("aspirant")
|
||||||
|
public class AspirantController {
|
||||||
|
private static final Integer DEFAULT_PAGE_SIZE = 1;
|
||||||
|
private static final Integer DEFAULT_PAGE_NUMBER = 1;
|
||||||
|
private final AspirantService aspirantService;
|
||||||
|
|
||||||
|
public AspirantController(AspirantService aspirantService) {
|
||||||
|
this.aspirantService = aspirantService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("aspirantReport")
|
||||||
|
public String createReport(Model model,
|
||||||
|
@RequestParam Optional<Integer> page,
|
||||||
|
@RequestParam Optional<Integer> size) {
|
||||||
|
int currentPage = page.orElse(DEFAULT_PAGE_NUMBER);
|
||||||
|
int pageSize = size.orElse(DEFAULT_PAGE_SIZE);
|
||||||
|
|
||||||
|
Page<Indicator> indicators = aspirantService.getIndicatorsByCourse(new OffsetablePageRequest(currentPage - 1, pageSize));
|
||||||
|
model.addAttribute("indicators", indicators);
|
||||||
|
int totalPages = indicators.getTotalPages();
|
||||||
|
if (totalPages > 0) {
|
||||||
|
List<Integer> pageNumbers = IntStream.rangeClosed(1, totalPages)
|
||||||
|
.boxed()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
model.addAttribute("pageNumbers", pageNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
model.addAttribute("report", new Report());
|
||||||
|
return "aspirant/editReport";
|
||||||
|
}
|
||||||
|
}
|
36
src/main/java/ru/ulstu/aspirant/model/Report.java
Normal file
36
src/main/java/ru/ulstu/aspirant/model/Report.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package ru.ulstu.aspirant.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.Temporal;
|
||||||
|
import jakarta.persistence.TemporalType;
|
||||||
|
import ru.ulstu.model.BaseEntity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Report extends BaseEntity {
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date createDate = new Date();
|
||||||
|
|
||||||
|
@OneToMany
|
||||||
|
private List<ReportValue> values = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<ReportValue> getValues() {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValues(List<ReportValue> values) {
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreateDate() {
|
||||||
|
return createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateDate(Date createDate) {
|
||||||
|
this.createDate = createDate;
|
||||||
|
}
|
||||||
|
}
|
30
src/main/java/ru/ulstu/aspirant/model/ReportValue.java
Normal file
30
src/main/java/ru/ulstu/aspirant/model/ReportValue.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package ru.ulstu.aspirant.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import ru.ulstu.indicator.model.Indicator;
|
||||||
|
import ru.ulstu.model.BaseEntity;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ReportValue extends BaseEntity {
|
||||||
|
@ManyToOne
|
||||||
|
private Indicator indicator;
|
||||||
|
|
||||||
|
private int indicatorValue;
|
||||||
|
|
||||||
|
public Indicator getIndicator() {
|
||||||
|
return indicator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndicator(Indicator indicator) {
|
||||||
|
this.indicator = indicator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndicatorValue() {
|
||||||
|
return indicatorValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndicatorValue(int indicatorValue) {
|
||||||
|
this.indicatorValue = indicatorValue;
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,6 @@ package ru.ulstu.aspirant.repository;
|
|||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import ru.ulstu.aspirant.model.Aspirant;
|
import ru.ulstu.aspirant.model.Aspirant;
|
||||||
import ru.ulstu.model.User;
|
|
||||||
|
|
||||||
public interface AspirantRepository extends JpaRepository<Aspirant, Integer> {
|
public interface AspirantRepository extends JpaRepository<Aspirant, Integer> {
|
||||||
Aspirant findByUser(User user);
|
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,10 @@ import org.springframework.stereotype.Service;
|
|||||||
import ru.ulstu.admin.model.AspirantForm;
|
import ru.ulstu.admin.model.AspirantForm;
|
||||||
import ru.ulstu.aspirant.model.Aspirant;
|
import ru.ulstu.aspirant.model.Aspirant;
|
||||||
import ru.ulstu.aspirant.repository.AspirantRepository;
|
import ru.ulstu.aspirant.repository.AspirantRepository;
|
||||||
|
import ru.ulstu.indicator.model.Course;
|
||||||
import ru.ulstu.indicator.model.Indicator;
|
import ru.ulstu.indicator.model.Indicator;
|
||||||
import ru.ulstu.indicator.service.IndicatorService;
|
import ru.ulstu.indicator.service.IndicatorService;
|
||||||
import ru.ulstu.model.User;
|
import ru.ulstu.user.UserUtils;
|
||||||
import ru.ulstu.user.UserService;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -17,14 +17,11 @@ import java.util.List;
|
|||||||
public class AspirantService {
|
public class AspirantService {
|
||||||
private final AspirantRepository aspirantRepository;
|
private final AspirantRepository aspirantRepository;
|
||||||
private final IndicatorService indicatorService;
|
private final IndicatorService indicatorService;
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
public AspirantService(AspirantRepository aspirantRepository,
|
public AspirantService(AspirantRepository aspirantRepository,
|
||||||
IndicatorService indicatorService,
|
IndicatorService indicatorService) {
|
||||||
UserService userService) {
|
|
||||||
this.aspirantRepository = aspirantRepository;
|
this.aspirantRepository = aspirantRepository;
|
||||||
this.indicatorService = indicatorService;
|
this.indicatorService = indicatorService;
|
||||||
this.userService = userService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Aspirant> getAspirants() {
|
public List<Aspirant> getAspirants() {
|
||||||
@ -43,12 +40,14 @@ public class AspirantService {
|
|||||||
aspirantRepository.deleteById(aspirantForm.getId());
|
aspirantRepository.deleteById(aspirantForm.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Aspirant getAspirantByUser(User user) {
|
public Aspirant getAspirantByUser(String currentUserLogin) {
|
||||||
return aspirantRepository.findByUser(user);
|
//return aspirantRepository.getAspirantByLogin();
|
||||||
|
//TODO: read aspirant
|
||||||
|
return aspirantRepository.findAll().stream().findAny().orElse(new Aspirant("default", Course.FIRST));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Indicator> getCurrentAspirantIndicators() {
|
public List<Indicator> getIndicatorsByCourse() {
|
||||||
Aspirant aspirant = getAspirantByUser(userService.getCurrentUser());
|
Aspirant aspirant = getAspirantByUser(UserUtils.getCurrentUserLogin());
|
||||||
return indicatorService.getIndicatorsByCourse(aspirant.getCourse());
|
return indicatorService.getIndicatorsByCourse(aspirant.getCourse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ public class SecurityConfiguration {
|
|||||||
log.debug("Security enabled");
|
log.debug("Security enabled");
|
||||||
|
|
||||||
http
|
http
|
||||||
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
|
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
.authorizeHttpRequests(auth ->
|
.authorizeHttpRequests(auth ->
|
||||||
auth.requestMatchers("/").permitAll()
|
auth.requestMatchers("/").permitAll()
|
||||||
.requestMatchers(permittedUrls).permitAll()
|
.requestMatchers(permittedUrls).permitAll()
|
||||||
.requestMatchers("/swagger-ui/*").hasAuthority(UserRoleConstants.ADMIN)
|
.requestMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN)
|
||||||
.anyRequest().authenticated())
|
.anyRequest().authenticated())
|
||||||
.formLogin(form ->
|
.formLogin(form ->
|
||||||
form.loginPage("/login")
|
form.loginPage("/login")
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package ru.ulstu.file.controller;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
import ru.ulstu.file.model.FileData;
|
|
||||||
import ru.ulstu.file.model.FileDataDto;
|
|
||||||
import ru.ulstu.file.service.FileService;
|
|
||||||
import ru.ulstu.model.response.Response;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("files")
|
|
||||||
public class FileController {
|
|
||||||
private final FileService fileService;
|
|
||||||
|
|
||||||
public FileController(FileService fileService) {
|
|
||||||
this.fileService = fileService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/download-tmp/{tmp-file-name}")
|
|
||||||
public ResponseEntity<byte[]> getFile(@PathVariable("tmp-file-name") String tmpFileName) throws IOException {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.add("Content-Disposition", "attachment; filename='"
|
|
||||||
+ URLEncoder.encode(fileService.getTmpFileName(tmpFileName), UTF_8.toString()) + "'");
|
|
||||||
return new ResponseEntity<>(fileService.getTmpFile(tmpFileName), headers, HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/download/{file-id}")
|
|
||||||
public ResponseEntity<byte[]> getFile(@PathVariable("file-id") Integer fileId) throws UnsupportedEncodingException {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
FileData fileData = fileService.getFile(fileId);
|
|
||||||
headers.add("Content-Disposition", "attachment; filename='" +
|
|
||||||
URLEncoder.encode(fileData.getName(), UTF_8.toString()) + "'");
|
|
||||||
return new ResponseEntity<>(fileData.getData(), headers, HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/uploadTmpFile")
|
|
||||||
public Response<FileDataDto> upload(@RequestParam("file") MultipartFile multipartFile) throws IOException {
|
|
||||||
return new Response<>(fileService.createFromMultipartFile(multipartFile));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
package ru.ulstu.file.model;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Lob;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import ru.ulstu.model.BaseEntity;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "file")
|
|
||||||
public class FileData extends BaseEntity {
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private long size;
|
|
||||||
|
|
||||||
@Column(name = "create_date")
|
|
||||||
private Date createDate;
|
|
||||||
|
|
||||||
@Lob
|
|
||||||
private byte[] data;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSize(long size) {
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getCreateDate() {
|
|
||||||
return createDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreateDate(Date createDate) {
|
|
||||||
this.createDate = createDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setData(byte[] data) {
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package ru.ulstu.file.model;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
|
|
||||||
public class FileDataDto {
|
|
||||||
private Integer id;
|
|
||||||
private String name;
|
|
||||||
private String fileName;
|
|
||||||
private String tmpFileName;
|
|
||||||
private boolean deleted;
|
|
||||||
|
|
||||||
public FileDataDto() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonCreator
|
|
||||||
public FileDataDto(@JsonProperty("id") Integer id,
|
|
||||||
@JsonProperty("name") String name,
|
|
||||||
@JsonProperty("fileName") String fileName,
|
|
||||||
@JsonProperty("tmpFileName") String tmpFileName) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.fileName = fileName;
|
|
||||||
this.tmpFileName = tmpFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileDataDto(FileData fileData) {
|
|
||||||
this.id = fileData.getId();
|
|
||||||
this.name = fileData.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileDataDto(String fileName, String tmpFileName) {
|
|
||||||
this.fileName = fileName;
|
|
||||||
this.tmpFileName = tmpFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Integer id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFileName() {
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFileName(String fileName) {
|
|
||||||
this.fileName = fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTmpFileName() {
|
|
||||||
return tmpFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTmpFileName(String tmpFileName) {
|
|
||||||
this.tmpFileName = tmpFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDeleted() {
|
|
||||||
return deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeleted(boolean deleted) {
|
|
||||||
this.deleted = deleted;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package ru.ulstu.file.repository;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import ru.ulstu.file.model.FileData;
|
|
||||||
|
|
||||||
public interface FileRepository extends JpaRepository<FileData, Integer> {
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
package ru.ulstu.file.service;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
import ru.ulstu.file.model.FileData;
|
|
||||||
import ru.ulstu.file.model.FileDataDto;
|
|
||||||
import ru.ulstu.file.repository.FileRepository;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class FileService {
|
|
||||||
private final static int META_FILE_NAME_INDEX = 0;
|
|
||||||
private final static int META_FILE_SIZE_INDEX = 1;
|
|
||||||
|
|
||||||
private final String tmpDir;
|
|
||||||
private final FileRepository fileRepository;
|
|
||||||
|
|
||||||
public FileService(FileRepository fileRepository) {
|
|
||||||
tmpDir = System.getProperty("java.io.tmpdir");
|
|
||||||
this.fileRepository = fileRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileData createFileFromTmp(String tmpFileName) throws IOException {
|
|
||||||
FileData fileData = new FileData();
|
|
||||||
fileData.setData(getTmpFile(tmpFileName));
|
|
||||||
fileData.setSize(getTmpFileSize(tmpFileName));
|
|
||||||
fileData.setCreateDate(new Date());
|
|
||||||
return fileRepository.save(fileData);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String uploadToTmpDir(MultipartFile multipartFile) throws IOException {
|
|
||||||
String tmpFileName = String.valueOf(System.currentTimeMillis()) + UUID.randomUUID();
|
|
||||||
Files.write(getTmpFilePath(tmpFileName), multipartFile.getBytes());
|
|
||||||
String meta = multipartFile.getOriginalFilename() + "\n" + multipartFile.getSize();
|
|
||||||
Files.write(getTmpFileMetaPath(tmpFileName), meta.getBytes(UTF_8));
|
|
||||||
return tmpFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] getMeta(String tmpFileName) throws IOException {
|
|
||||||
return new String(Files.readAllBytes(getTmpFileMetaPath(tmpFileName)), UTF_8)
|
|
||||||
.split("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getTmpFileSize(String tmpFileName) throws IOException {
|
|
||||||
return Long.valueOf(getMeta(tmpFileName)[META_FILE_SIZE_INDEX]).longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTmpFileName(String tmpFileName) throws IOException {
|
|
||||||
return getMeta(tmpFileName)[META_FILE_NAME_INDEX];
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getTmpFile(String tmpFileName) throws IOException {
|
|
||||||
return Files.readAllBytes(getTmpFilePath(tmpFileName));
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileData getFile(Integer fileId) {
|
|
||||||
return fileRepository.getOne(fileId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteTmpFile(String tmpFileName) throws IOException {
|
|
||||||
Files.delete(getTmpFilePath(tmpFileName));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Path getTmpFilePath(String tmpFileName) {
|
|
||||||
return Paths.get(tmpDir, tmpFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Path getTmpFileMetaPath(String tmpFileName) {
|
|
||||||
return Paths.get(getTmpFilePath(tmpFileName) + ".meta");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteFile(FileData fileData) {
|
|
||||||
fileRepository.delete(fileData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<FileData> saveOrCreate(List<FileDataDto> fileDtos) throws IOException {
|
|
||||||
List<FileData> files = new ArrayList<>();
|
|
||||||
for (FileDataDto file : fileDtos) {
|
|
||||||
files.add(file.getId() != null ? update(file) : create(file));
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
private FileData update(FileDataDto fileDataDto) {
|
|
||||||
return fileRepository.findById(fileDataDto.getId())
|
|
||||||
.orElseThrow(() -> new RuntimeException("File not found by id"));
|
|
||||||
//return fileRepository.save(copyFromDto(file, fileDataDto));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
private FileData create(FileDataDto fileDataDto) throws IOException {
|
|
||||||
FileData newFile = createFileFromTmp(fileDataDto.getTmpFileName());
|
|
||||||
copyFromDto(newFile, fileDataDto);
|
|
||||||
return fileRepository.save(newFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileData copyFromDto(FileData fileData, FileDataDto fileDataDto) {
|
|
||||||
fileData.setName(fileDataDto.getName());
|
|
||||||
return fileData;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void delete(Integer fileId) {
|
|
||||||
fileRepository.deleteById(fileId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileDataDto createFromMultipartFile(MultipartFile multipartFile) throws IOException {
|
|
||||||
return new FileDataDto(multipartFile.getOriginalFilename(), uploadToTmpDir(multipartFile));
|
|
||||||
}
|
|
||||||
}
|
|
80
src/main/java/ru/ulstu/files/FileSystemStorageService.java
Normal file
80
src/main/java/ru/ulstu/files/FileSystemStorageService.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package ru.ulstu.files;
|
||||||
|
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.UrlResource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.FileSystemUtils;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class FileSystemStorageService implements StorageService {
|
||||||
|
public static final String UPLOAD_DIR = "upload";
|
||||||
|
|
||||||
|
private final Path rootLocation = Paths.get(UPLOAD_DIR);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void store(MultipartFile file) {
|
||||||
|
try {
|
||||||
|
if (file.isEmpty()) {
|
||||||
|
throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
|
||||||
|
}
|
||||||
|
Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<Path> loadAll() {
|
||||||
|
try {
|
||||||
|
return Files.walk(this.rootLocation, 1)
|
||||||
|
.filter(path -> !path.equals(this.rootLocation))
|
||||||
|
.map(path -> this.rootLocation.relativize(path));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new StorageException("Failed to read stored files", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path load(String filename) {
|
||||||
|
return rootLocation.resolve(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource loadAsResource(String filename) {
|
||||||
|
try {
|
||||||
|
Path file = load(filename);
|
||||||
|
Resource resource = new UrlResource(file.toUri());
|
||||||
|
if (resource.exists() || resource.isReadable()) {
|
||||||
|
return resource;
|
||||||
|
} else {
|
||||||
|
throw new StorageFileNotFoundException("Could not read file: " + filename);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new StorageFileNotFoundException("Could not read file: " + filename, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAll() {
|
||||||
|
FileSystemUtils.deleteRecursively(rootLocation.toFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
try {
|
||||||
|
Files.createDirectory(rootLocation);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new StorageException("Could not initialize storage", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
src/main/java/ru/ulstu/files/FileUtil.java
Normal file
29
src/main/java/ru/ulstu/files/FileUtil.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package ru.ulstu.files;
|
||||||
|
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
|
||||||
|
public class FileUtil {
|
||||||
|
|
||||||
|
public static void saveFile(String uploadDir, String fileName,
|
||||||
|
MultipartFile multipartFile) throws IOException {
|
||||||
|
Path uploadPath = Paths.get(uploadDir);
|
||||||
|
|
||||||
|
if (!Files.exists(uploadPath)) {
|
||||||
|
Files.createDirectories(uploadPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStream inputStream = multipartFile.getInputStream()) {
|
||||||
|
Path filePath = uploadPath.resolve(fileName);
|
||||||
|
Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new IOException("Could not save image file: " + fileName, ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/ru/ulstu/files/FilesController.java
Normal file
28
src/main/java/ru/ulstu/files/FilesController.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package ru.ulstu.files;
|
||||||
|
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class FilesController {
|
||||||
|
private final StorageService storageService;
|
||||||
|
|
||||||
|
public FilesController(StorageService storageService) {
|
||||||
|
this.storageService = storageService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/files/{filename:.+}")
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseEntity<Resource> serveFile(@PathVariable String filename) {
|
||||||
|
Resource file = storageService.loadAsResource((filename == null || filename.equals("null") || filename.isEmpty())
|
||||||
|
? "logo.png"
|
||||||
|
: filename);
|
||||||
|
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
|
||||||
|
"filename=\"" + file.getFilename() + "\"").body(file);
|
||||||
|
}
|
||||||
|
}
|
12
src/main/java/ru/ulstu/files/StorageException.java
Normal file
12
src/main/java/ru/ulstu/files/StorageException.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package ru.ulstu.files;
|
||||||
|
|
||||||
|
public class StorageException extends RuntimeException {
|
||||||
|
|
||||||
|
public StorageException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package ru.ulstu.files;
|
||||||
|
|
||||||
|
public class StorageFileNotFoundException extends StorageException {
|
||||||
|
|
||||||
|
public StorageFileNotFoundException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageFileNotFoundException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
23
src/main/java/ru/ulstu/files/StorageService.java
Normal file
23
src/main/java/ru/ulstu/files/StorageService.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package ru.ulstu.files;
|
||||||
|
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public interface StorageService {
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void store(MultipartFile file);
|
||||||
|
|
||||||
|
Stream<Path> loadAll();
|
||||||
|
|
||||||
|
Path load(String filename);
|
||||||
|
|
||||||
|
Resource loadAsResource(String filename);
|
||||||
|
|
||||||
|
void deleteAll();
|
||||||
|
|
||||||
|
}
|
@ -1,39 +0,0 @@
|
|||||||
package ru.ulstu.model;
|
|
||||||
|
|
||||||
public enum ErrorConstants {
|
|
||||||
UNKNOWN(0, "Unknown error"),
|
|
||||||
ID_IS_NULL(1, "Id of entity has null value"),
|
|
||||||
VALIDATION_ERROR(2, "Validation error"),
|
|
||||||
USER_ID_EXISTS(100, "New user can't have id"),
|
|
||||||
USER_ACTIVATION_ERROR(101, "Invalid activation key"),
|
|
||||||
USER_EMAIL_EXISTS(102, "Пользователь с таким почтовым ящиком уже существует"),
|
|
||||||
USER_LOGIN_EXISTS(103, "Пользователь с таким логином уже существует"),
|
|
||||||
USER_PASSWORDS_NOT_VALID_OR_NOT_MATCH(104, "Пароли введены неверно"),
|
|
||||||
USER_NOT_FOUND(105, "Аккаунт не найден"),
|
|
||||||
USER_NOT_ACTIVATED(106, "User is not activated"),
|
|
||||||
USER_RESET_ERROR(107, "Некорректный ключ подтверждения"),
|
|
||||||
USER_UNDEAD_ERROR(108, "Can't edit/delete that user"),
|
|
||||||
FILE_UPLOAD_ERROR(110, "File upload error"),
|
|
||||||
USER_SENDING_MAIL_EXCEPTION(111, "Во время отправки приглашения пользователю произошла ошибка");
|
|
||||||
|
|
||||||
private final int code;
|
|
||||||
private final String message;
|
|
||||||
|
|
||||||
ErrorConstants(int code, String message) {
|
|
||||||
this.code = code;
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("%d: %s", code, message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package ru.ulstu.model.response;
|
|
||||||
|
|
||||||
class ControllerResponse<D, E> {
|
|
||||||
private final D data;
|
|
||||||
private final ControllerResponseError<E> error;
|
|
||||||
|
|
||||||
ControllerResponse(D data) {
|
|
||||||
this.data = data;
|
|
||||||
this.error = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerResponse(ControllerResponseError<E> error) {
|
|
||||||
this.data = null;
|
|
||||||
this.error = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
public D getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControllerResponseError<E> getError() {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package ru.ulstu.model.response;
|
|
||||||
|
|
||||||
|
|
||||||
import ru.ulstu.model.ErrorConstants;
|
|
||||||
|
|
||||||
class ControllerResponseError<D> {
|
|
||||||
private final ErrorConstants description;
|
|
||||||
private final D data;
|
|
||||||
|
|
||||||
ControllerResponseError(ErrorConstants description, D data) {
|
|
||||||
this.description = description;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCode() {
|
|
||||||
return description.getCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return description.getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public D getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package ru.ulstu.model.response;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public class PageableItems<T> {
|
|
||||||
private final long count;
|
|
||||||
private final Collection<T> items;
|
|
||||||
|
|
||||||
public PageableItems(long count, Collection<T> items) {
|
|
||||||
this.count = count;
|
|
||||||
this.items = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<T> getItems() {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package ru.ulstu.model.response;
|
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import ru.ulstu.model.ErrorConstants;
|
|
||||||
|
|
||||||
public class Response<D> extends ResponseEntity<Object> {
|
|
||||||
|
|
||||||
public Response(D data) {
|
|
||||||
super(new ControllerResponse<D, Void>(data), HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Response(ErrorConstants error) {
|
|
||||||
super(new ControllerResponse<Void, Void>(new ControllerResponseError<>(error, null)), HttpStatus.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package ru.ulstu.model.response;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import ru.ulstu.model.ErrorConstants;
|
|
||||||
|
|
||||||
|
|
||||||
public class ResponseExtended<E> extends ResponseEntity<Object> {
|
|
||||||
|
|
||||||
public ResponseExtended(ErrorConstants error, E errorData) {
|
|
||||||
super(new ControllerResponse<Void, E>(new ControllerResponseError<E>(error, errorData)), HttpStatus.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
package ru.ulstu.report.controller;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import ru.ulstu.aspirant.service.AspirantService;
|
|
||||||
import ru.ulstu.indicator.model.Indicator;
|
|
||||||
import ru.ulstu.indicator.service.IndicatorService;
|
|
||||||
import ru.ulstu.report.model.ReportListForm;
|
|
||||||
import ru.ulstu.report.model.ReportPeriod;
|
|
||||||
import ru.ulstu.report.model.dto.ReportDto;
|
|
||||||
import ru.ulstu.report.service.ReportPeriodService;
|
|
||||||
import ru.ulstu.report.service.ReportService;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("report")
|
|
||||||
public class ReportController {
|
|
||||||
private final IndicatorService indicatorService;
|
|
||||||
private final AspirantService aspirantService;
|
|
||||||
private final ReportService reportService;
|
|
||||||
private final ReportPeriodService reportPeriodService;
|
|
||||||
|
|
||||||
public ReportController(IndicatorService indicatorService,
|
|
||||||
AspirantService aspirantService,
|
|
||||||
ReportService reportService,
|
|
||||||
ReportPeriodService reportPeriodService) {
|
|
||||||
this.indicatorService = indicatorService;
|
|
||||||
this.aspirantService = aspirantService;
|
|
||||||
this.reportService = reportService;
|
|
||||||
this.reportPeriodService = reportPeriodService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("reportList")
|
|
||||||
public String getReportPeriods(Model model) {
|
|
||||||
List<ReportPeriod> periods = reportPeriodService.getReportPeriods();
|
|
||||||
model.addAttribute("reportPeriods", periods);
|
|
||||||
model.addAttribute("reportListForm", new ReportListForm(periods.isEmpty() ? null : periods.getFirst()));
|
|
||||||
model.addAttribute("reports", reportService.getReports(periods.isEmpty() ? null : periods.getFirst()));
|
|
||||||
model.addAttribute("canCreate", !periods.isEmpty() && reportService.canCreateReport(periods.getFirst()));
|
|
||||||
return "report/reportList";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("reportList")
|
|
||||||
public String getReportPeriods(ReportListForm reportListForm, Model model) {
|
|
||||||
model.addAttribute("reportListForm", reportListForm);
|
|
||||||
model.addAttribute("reports", reportService.getReports(reportListForm.getReportPeriod()));
|
|
||||||
List<ReportPeriod> periods = reportPeriodService.getReportPeriods();
|
|
||||||
model.addAttribute("reportPeriods", periods);
|
|
||||||
model.addAttribute("canCreate", !periods.isEmpty() && reportService.canCreateReport(reportListForm.getReportPeriod()));
|
|
||||||
return "report/reportList";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("new-report/{reportPeriodId}")
|
|
||||||
public String createReport(@PathVariable("reportPeriodId") Integer reportPeriodId,
|
|
||||||
Model model) {
|
|
||||||
List<Indicator> indicators = aspirantService.getCurrentAspirantIndicators();
|
|
||||||
model.addAttribute("report", new ReportDto(reportPeriodId, indicators));
|
|
||||||
return "report/editReport";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("edit-report/{reportId}")
|
|
||||||
public String editReportWithoutReportPeriod(@PathVariable("reportId") Integer reportId, Model model) {
|
|
||||||
List<Indicator> indicators = reportService.getIndicators(reportId);
|
|
||||||
model.addAttribute("report", new ReportDto(reportService.getReportById(reportId), indicators));
|
|
||||||
return "report/editReport";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(value = "save-report", params = "save")
|
|
||||||
public String saveReport(@ModelAttribute("report") ReportDto reportDto, Model model) {
|
|
||||||
reportService.saveReport(reportDto);
|
|
||||||
return "redirect:/report/reportList";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(value = "save-report", params = "delete")
|
|
||||||
public String deleteReport(@ModelAttribute("report") ReportDto reportDto) {
|
|
||||||
reportService.deleteReport(reportDto.getId());
|
|
||||||
return "redirect:/report/reportList";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package ru.ulstu.report.controller;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import ru.ulstu.report.model.ReportPeriod;
|
|
||||||
import ru.ulstu.report.service.ReportPeriodService;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("admin")
|
|
||||||
public class ReportPeriodController {
|
|
||||||
private final ReportPeriodService reportPeriodService;
|
|
||||||
|
|
||||||
public ReportPeriodController(ReportPeriodService reportPeriodService) {
|
|
||||||
this.reportPeriodService = reportPeriodService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("reportPeriodList")
|
|
||||||
public String getReportPeriods(Model model) {
|
|
||||||
model.addAttribute("reportPeriods", reportPeriodService.getReportPeriods());
|
|
||||||
return "admin/reportPeriodList";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("editReportPeriod/{reportPeriodId}")
|
|
||||||
public String getReportPeriods(@PathVariable(value = "reportPeriodId") Integer reportPeriodId, Model model) {
|
|
||||||
model.addAttribute("reportPeriod",
|
|
||||||
reportPeriodId == 0
|
|
||||||
? new ReportPeriod()
|
|
||||||
: reportPeriodService.getById(reportPeriodId));
|
|
||||||
return "admin/editReportPeriod";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(value = "saveReportPeriod", params = "save")
|
|
||||||
public String saveReportPeriods(ReportPeriod reportPeriod) {
|
|
||||||
reportPeriodService.save(reportPeriod);
|
|
||||||
return "redirect:/admin/reportPeriodList";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(value = "saveReportPeriod", params = "delete")
|
|
||||||
public String delete(ReportPeriod reportPeriod) {
|
|
||||||
reportPeriodService.delete(reportPeriod);
|
|
||||||
return "redirect:/admin/reportPeriodList";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package ru.ulstu.report.controller;
|
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import ru.ulstu.report.model.dto.ReportValueDto;
|
|
||||||
import ru.ulstu.report.service.ReportValueService;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("report-value")
|
|
||||||
public class ReportValueController {
|
|
||||||
private final ReportValueService reportValueService;
|
|
||||||
|
|
||||||
public ReportValueController(ReportValueService reportValueService) {
|
|
||||||
this.reportValueService = reportValueService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("edit-report-value/{reportId}/{indicatorId}")
|
|
||||||
public String getReportValue(@PathVariable("reportId") Integer reportId,
|
|
||||||
@PathVariable("indicatorId") Integer indicatorId,
|
|
||||||
Model model) {
|
|
||||||
model.addAttribute("reportValue", reportValueService.getByIndicatorId(reportId, indicatorId));
|
|
||||||
model.addAttribute("canEdit", reportValueService.canEdit(reportId));
|
|
||||||
model.addAttribute("status", reportValueService.getStatus(reportId));
|
|
||||||
return "report/editReportValue";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("save-report-value")
|
|
||||||
public String saveReportValue(@Valid ReportValueDto reportValueDto, Model model) throws IOException {
|
|
||||||
reportValueService.saveReportValue(reportValueDto);
|
|
||||||
return "redirect:/report/edit-report/" + reportValueDto.getReportId();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package ru.ulstu.report.model;
|
|
||||||
|
|
||||||
import jakarta.persistence.CascadeType;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.EnumType;
|
|
||||||
import jakarta.persistence.Enumerated;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.OneToMany;
|
|
||||||
import jakarta.persistence.Temporal;
|
|
||||||
import jakarta.persistence.TemporalType;
|
|
||||||
import ru.ulstu.aspirant.model.Aspirant;
|
|
||||||
import ru.ulstu.model.BaseEntity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
public class Report extends BaseEntity {
|
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
|
||||||
private Date createDate = new Date();
|
|
||||||
|
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
|
||||||
private List<ReportValue> values = new ArrayList<>();
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
private ReportPeriod reportPeriod;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
private Aspirant aspirant;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
private ReportStatus status = ReportStatus.NEW;
|
|
||||||
|
|
||||||
public Report() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Report(Integer id) {
|
|
||||||
setId(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ReportValue> getValues() {
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValues(List<ReportValue> values) {
|
|
||||||
this.values = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getCreateDate() {
|
|
||||||
return createDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreateDate(Date createDate) {
|
|
||||||
this.createDate = createDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportPeriod getReportPeriod() {
|
|
||||||
return reportPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReportPeriod(ReportPeriod reportPeriod) {
|
|
||||||
this.reportPeriod = reportPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Aspirant getAspirant() {
|
|
||||||
return aspirant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAspirant(Aspirant aspirant) {
|
|
||||||
this.aspirant = aspirant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportStatus getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(ReportStatus status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package ru.ulstu.report.model;
|
|
||||||
|
|
||||||
public class ReportListForm {
|
|
||||||
private ReportPeriod reportPeriod;
|
|
||||||
|
|
||||||
public ReportListForm() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportListForm(ReportPeriod reportPeriod) {
|
|
||||||
this.reportPeriod = reportPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportPeriod getReportPeriod() {
|
|
||||||
return reportPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReportPeriod(ReportPeriod reportPeriod) {
|
|
||||||
this.reportPeriod = reportPeriod;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package ru.ulstu.report.model;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Temporal;
|
|
||||||
import jakarta.persistence.TemporalType;
|
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
|
||||||
import ru.ulstu.model.BaseEntity;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
public class ReportPeriod extends BaseEntity {
|
|
||||||
@Temporal(TemporalType.DATE)
|
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
|
||||||
private Date startDate = new Date();
|
|
||||||
|
|
||||||
@Temporal(TemporalType.DATE)
|
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
|
||||||
private Date endDate = new Date();
|
|
||||||
|
|
||||||
public Date getStartDate() {
|
|
||||||
return startDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStartDate(Date startDate) {
|
|
||||||
this.startDate = startDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getEndDate() {
|
|
||||||
return endDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEndDate(Date endDate) {
|
|
||||||
this.endDate = endDate;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package ru.ulstu.report.model;
|
|
||||||
|
|
||||||
public enum ReportStatus {
|
|
||||||
NEW("новый"),
|
|
||||||
REVIEW("проверка руководителем"),
|
|
||||||
CHECKING("проверка в отделе аспирантуры"),
|
|
||||||
APPROVED("подтвержден");
|
|
||||||
|
|
||||||
private final String title;
|
|
||||||
|
|
||||||
ReportStatus(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package ru.ulstu.report.model;
|
|
||||||
|
|
||||||
import jakarta.persistence.CascadeType;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.OneToMany;
|
|
||||||
import org.hibernate.annotations.Fetch;
|
|
||||||
import org.hibernate.annotations.FetchMode;
|
|
||||||
import ru.ulstu.file.model.FileData;
|
|
||||||
import ru.ulstu.indicator.model.Indicator;
|
|
||||||
import ru.ulstu.model.BaseEntity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
public class ReportValue extends BaseEntity {
|
|
||||||
@ManyToOne
|
|
||||||
private Indicator indicator;
|
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
|
||||||
@JoinColumn(name = "report_value_id")
|
|
||||||
@Fetch(FetchMode.SUBSELECT)
|
|
||||||
private List<FileData> files = new ArrayList<>();
|
|
||||||
private int indicatorValue;
|
|
||||||
private String comment;
|
|
||||||
|
|
||||||
public Indicator getIndicator() {
|
|
||||||
return indicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIndicator(Indicator indicator) {
|
|
||||||
this.indicator = indicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndicatorValue() {
|
|
||||||
return indicatorValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIndicatorValue(int indicatorValue) {
|
|
||||||
this.indicatorValue = indicatorValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<FileData> getFiles() {
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFiles(List<FileData> files) {
|
|
||||||
this.files = files;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getComment() {
|
|
||||||
return comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setComment(String comment) {
|
|
||||||
this.comment = comment;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package ru.ulstu.report.model.dto;
|
|
||||||
|
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
|
||||||
import ru.ulstu.indicator.model.Indicator;
|
|
||||||
import ru.ulstu.report.model.Report;
|
|
||||||
import ru.ulstu.report.model.ReportStatus;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ReportDto {
|
|
||||||
private Integer id;
|
|
||||||
private Integer reportPeriodId;
|
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
|
|
||||||
private Date createDate = new Date();
|
|
||||||
private List<ReportValueDto> reportValues = new ArrayList<>();
|
|
||||||
private ReportStatus status;
|
|
||||||
|
|
||||||
public ReportDto() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportDto(Integer reportPeriodId, List<Indicator> indicators) {
|
|
||||||
this.reportPeriodId = reportPeriodId;
|
|
||||||
this.reportValues = indicators.stream().map(ReportValueDto::new).toList();
|
|
||||||
this.status = ReportStatus.NEW;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportDto(Report report, List<Indicator> indicators) {
|
|
||||||
this.id = report.getId();
|
|
||||||
this.reportPeriodId = report.getReportPeriod().getId();
|
|
||||||
this.createDate = report.getCreateDate();
|
|
||||||
this.reportValues = indicators.stream().map(ReportValueDto::new).toList();
|
|
||||||
this.status = report.getStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ReportValueDto> getReportValues() {
|
|
||||||
return reportValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReportValues(List<ReportValueDto> reportValues) {
|
|
||||||
this.reportValues = reportValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Integer id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getReportPeriodId() {
|
|
||||||
return reportPeriodId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReportPeriodId(Integer reportPeriodId) {
|
|
||||||
this.reportPeriodId = reportPeriodId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getCreateDate() {
|
|
||||||
return createDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreateDate(Date createDate) {
|
|
||||||
this.createDate = createDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportStatus getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(ReportStatus status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
package ru.ulstu.report.model.dto;
|
|
||||||
|
|
||||||
import ru.ulstu.file.model.FileDataDto;
|
|
||||||
import ru.ulstu.indicator.model.Indicator;
|
|
||||||
import ru.ulstu.report.model.ReportValue;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ReportValueDto {
|
|
||||||
private Integer id = 0;
|
|
||||||
private Integer reportId;
|
|
||||||
private Indicator indicator;
|
|
||||||
private int indicatorValue;
|
|
||||||
private List<FileDataDto> files = new ArrayList<>();
|
|
||||||
private String comment;
|
|
||||||
|
|
||||||
public ReportValueDto() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportValueDto(Integer reportId, Indicator indicator) {
|
|
||||||
this.reportId = reportId;
|
|
||||||
this.indicator = indicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportValueDto(Indicator indicator) {
|
|
||||||
this.indicator = indicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportValueDto(ReportValue reportValue, Integer reportId) {
|
|
||||||
this.id = reportValue.getId();
|
|
||||||
this.reportId = reportId;
|
|
||||||
this.indicator = reportValue.getIndicator();
|
|
||||||
this.files = reportValue.getFiles().stream().map(FileDataDto::new).collect(Collectors.toList());
|
|
||||||
this.indicatorValue = reportValue.getIndicatorValue();
|
|
||||||
this.comment = reportValue.getComment();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Indicator getIndicator() {
|
|
||||||
return indicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIndicator(Indicator indicator) {
|
|
||||||
this.indicator = indicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndicatorValue() {
|
|
||||||
return indicatorValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIndicatorValue(int indicatorValue) {
|
|
||||||
this.indicatorValue = indicatorValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<FileDataDto> getFiles() {
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFiles(List<FileDataDto> files) {
|
|
||||||
this.files = files;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Integer id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getReportId() {
|
|
||||||
return reportId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReportId(Integer reportId) {
|
|
||||||
this.reportId = reportId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getComment() {
|
|
||||||
return comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setComment(String comment) {
|
|
||||||
this.comment = comment;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package ru.ulstu.report.repository;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import ru.ulstu.report.model.ReportPeriod;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface ReportPeriodRepository extends JpaRepository<ReportPeriod, Integer> {
|
|
||||||
List<ReportPeriod> findAllByOrderByStartDateDesc();
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package ru.ulstu.report.repository;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.data.repository.query.Param;
|
|
||||||
import ru.ulstu.aspirant.model.Aspirant;
|
|
||||||
import ru.ulstu.indicator.model.Indicator;
|
|
||||||
import ru.ulstu.report.model.Report;
|
|
||||||
import ru.ulstu.report.model.ReportPeriod;
|
|
||||||
import ru.ulstu.statistic.model.RatingItem;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface ReportRepository extends JpaRepository<Report, Integer> {
|
|
||||||
|
|
||||||
List<Report> findAllByReportPeriod(ReportPeriod reportPeriod);
|
|
||||||
|
|
||||||
Report findByReportPeriodAndAspirant(ReportPeriod reportPeriod, Aspirant aspirant);
|
|
||||||
|
|
||||||
@Query("SELECT new ru.ulstu.statistic.model.RatingItem(r.aspirant, (SELECT cast(sum(rv.indicatorValue) AS Integer) FROM ReportValue rv WHERE rv MEMBER OF r.values)) FROM Report r JOIN r.reportPeriod rp WHERE rp.id = :reportPeriodId")
|
|
||||||
List<RatingItem> getRating(@Param("reportPeriodId") Integer reportPeriodId);
|
|
||||||
|
|
||||||
@Query("SELECT DISTINCT v.indicator FROM Report r JOIN r.values v WHERE r.id = :reportId")
|
|
||||||
List<Indicator> getIndicatorsById(@Param("reportId") Integer reportId);
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package ru.ulstu.report.repository;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.data.repository.query.Param;
|
|
||||||
import ru.ulstu.report.model.ReportValue;
|
|
||||||
|
|
||||||
public interface ReportValueRepository extends JpaRepository<ReportValue, Integer> {
|
|
||||||
@Query("SELECT rv FROM Report r JOIN r.values rv WHERE r.id = :reportId AND rv.indicator.id = :indicatorId")
|
|
||||||
ReportValue findByReportIdAndIndicatorId(@Param("reportId") Integer reportId, @Param("indicatorId") Integer indicatorId);
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package ru.ulstu.report.service;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.ulstu.report.model.ReportPeriod;
|
|
||||||
import ru.ulstu.report.repository.ReportPeriodRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class ReportPeriodService {
|
|
||||||
private final ReportPeriodRepository reportPeriodRepository;
|
|
||||||
|
|
||||||
public ReportPeriodService(ReportPeriodRepository reportPeriodRepository) {
|
|
||||||
this.reportPeriodRepository = reportPeriodRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ReportPeriod> getReportPeriods() {
|
|
||||||
return reportPeriodRepository.findAllByOrderByStartDateDesc();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportPeriod save(ReportPeriod reportPeriod) {
|
|
||||||
ReportPeriod dbReportPeriod;
|
|
||||||
if (reportPeriod.getId() != null) {
|
|
||||||
dbReportPeriod = getById(reportPeriod.getId());
|
|
||||||
dbReportPeriod.setStartDate(reportPeriod.getStartDate());
|
|
||||||
dbReportPeriod.setEndDate(reportPeriod.getEndDate());
|
|
||||||
} else {
|
|
||||||
dbReportPeriod = reportPeriod;
|
|
||||||
}
|
|
||||||
return reportPeriodRepository.save(dbReportPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete(ReportPeriod reportPeriod) {
|
|
||||||
reportPeriodRepository.deleteById(reportPeriod.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportPeriod getById(Integer reportPeriodId) {
|
|
||||||
return reportPeriodRepository
|
|
||||||
.findById(reportPeriodId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Report period not found by id"));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package ru.ulstu.report.service;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.ulstu.aspirant.model.Aspirant;
|
|
||||||
import ru.ulstu.aspirant.service.AspirantService;
|
|
||||||
import ru.ulstu.indicator.model.Indicator;
|
|
||||||
import ru.ulstu.report.model.Report;
|
|
||||||
import ru.ulstu.report.model.ReportPeriod;
|
|
||||||
import ru.ulstu.report.model.ReportValue;
|
|
||||||
import ru.ulstu.report.model.dto.ReportDto;
|
|
||||||
import ru.ulstu.report.repository.ReportRepository;
|
|
||||||
import ru.ulstu.user.UserService;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class ReportService {
|
|
||||||
private final ReportRepository reportRepository;
|
|
||||||
private final UserService userService;
|
|
||||||
private final AspirantService aspirantService;
|
|
||||||
private final ReportPeriodService reportPeriodService;
|
|
||||||
|
|
||||||
public ReportService(ReportRepository reportRepository,
|
|
||||||
UserService userService,
|
|
||||||
AspirantService aspirantService, ReportPeriodService reportPeriodService) {
|
|
||||||
this.reportRepository = reportRepository;
|
|
||||||
this.userService = userService;
|
|
||||||
this.aspirantService = aspirantService;
|
|
||||||
this.reportPeriodService = reportPeriodService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Report> getReports(ReportPeriod reportPeriod) {
|
|
||||||
return reportRepository.findAllByReportPeriod(reportPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canCreateReport(ReportPeriod reportPeriod) {
|
|
||||||
Aspirant currentAspirant = aspirantService.getAspirantByUser(userService.getCurrentUser());
|
|
||||||
return currentAspirant != null && reportRepository.findByReportPeriodAndAspirant(reportPeriod, currentAspirant) == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Report saveReport(ReportDto reportDto) {
|
|
||||||
Report report;
|
|
||||||
if (reportDto.getId() == null || reportDto.getId() == 0) {
|
|
||||||
report = new Report();
|
|
||||||
} else {
|
|
||||||
report = getReportById(reportDto.getId());
|
|
||||||
}
|
|
||||||
if (reportDto.getReportPeriodId() != null) {
|
|
||||||
report.setReportPeriod(reportPeriodService.getById(reportDto.getReportPeriodId()));
|
|
||||||
}
|
|
||||||
report.setAspirant(aspirantService.getAspirantByUser(userService.getCurrentUser()));
|
|
||||||
report.setCreateDate(reportDto.getCreateDate());
|
|
||||||
report.setStatus(reportDto.getStatus());
|
|
||||||
return reportRepository.save(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Report getReportById(Integer reportId) {
|
|
||||||
return reportRepository
|
|
||||||
.findById(reportId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Report not found by id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteReport(Integer id) {
|
|
||||||
reportRepository.deleteById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addReportValue(Integer reportId, ReportValue reportValue) {
|
|
||||||
Report report = getReportById(reportId);
|
|
||||||
report.getValues().remove(reportValue);
|
|
||||||
report.getValues().add(reportValue);
|
|
||||||
reportRepository.save(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Indicator> getIndicators(Integer reportId) {
|
|
||||||
return reportRepository.getIndicatorsById(reportId);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
package ru.ulstu.report.service;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.ulstu.file.model.FileData;
|
|
||||||
import ru.ulstu.file.service.FileService;
|
|
||||||
import ru.ulstu.indicator.service.IndicatorService;
|
|
||||||
import ru.ulstu.report.model.ReportStatus;
|
|
||||||
import ru.ulstu.report.model.ReportValue;
|
|
||||||
import ru.ulstu.report.model.dto.ReportValueDto;
|
|
||||||
import ru.ulstu.report.repository.ReportValueRepository;
|
|
||||||
import ru.ulstu.user.UserService;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class ReportValueService {
|
|
||||||
private final ReportValueRepository reportValueRepository;
|
|
||||||
private final IndicatorService indicatorService;
|
|
||||||
private final FileService fileService;
|
|
||||||
private final ReportService reportService;
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
public ReportValueService(ReportValueRepository reportValueRepository,
|
|
||||||
IndicatorService indicatorService,
|
|
||||||
FileService fileService,
|
|
||||||
ReportService reportService, UserService userService) {
|
|
||||||
this.reportValueRepository = reportValueRepository;
|
|
||||||
this.indicatorService = indicatorService;
|
|
||||||
this.fileService = fileService;
|
|
||||||
this.reportService = reportService;
|
|
||||||
this.userService = userService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportValue saveReportValue(ReportValueDto reportValueDto) throws IOException {
|
|
||||||
ReportValue reportValue;
|
|
||||||
if (reportValueDto.getId() == null || reportValueDto.getId() == 0) {
|
|
||||||
reportValue = new ReportValue();
|
|
||||||
} else {
|
|
||||||
reportValue = getReportValueById(reportValueDto.getId());
|
|
||||||
}
|
|
||||||
reportValue.setIndicatorValue(reportValueDto.getIndicatorValue());
|
|
||||||
reportValue.setIndicator(indicatorService.getIndicatorById(reportValueDto.getIndicator().getId()));
|
|
||||||
List<FileData> files = fileService.saveOrCreate(reportValueDto.getFiles().stream()
|
|
||||||
.filter(f -> !f.isDeleted())
|
|
||||||
.toList());
|
|
||||||
reportValue.getFiles().removeAll(files);
|
|
||||||
reportValue.setFiles(files);
|
|
||||||
reportValue.setComment(reportValueDto.getComment());
|
|
||||||
reportValue = reportValueRepository.save(reportValue);
|
|
||||||
reportService.addReportValue(reportValueDto.getReportId(), reportValue);
|
|
||||||
|
|
||||||
return reportValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportValue getReportValueById(Integer reportValueId) {
|
|
||||||
return reportValueRepository
|
|
||||||
.findById(reportValueId)
|
|
||||||
.orElseThrow(() -> new RuntimeException("Report value not found by id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteReportValue(Integer id) {
|
|
||||||
reportValueRepository.deleteById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportValueDto getByIndicatorId(Integer reportId, Integer indicatorId) {
|
|
||||||
ReportValue reportValue = reportValueRepository.findByReportIdAndIndicatorId(reportId, indicatorId);
|
|
||||||
if (reportValue == null) {
|
|
||||||
return new ReportValueDto(reportId, indicatorService.getIndicatorById(indicatorId));
|
|
||||||
}
|
|
||||||
return new ReportValueDto(reportValue, reportId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canEdit(Integer reportId) {
|
|
||||||
return reportService.getReportById(reportId).getAspirant().getUser().equals(userService.getCurrentUser());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportStatus getStatus(Integer reportId) {
|
|
||||||
return reportService.getReportById(reportId).getStatus();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
package ru.ulstu.statistic.controller;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import ru.ulstu.report.service.ReportPeriodService;
|
|
||||||
import ru.ulstu.statistic.model.StatisticForm;
|
|
||||||
import ru.ulstu.statistic.service.StatisticService;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("statistic")
|
|
||||||
public class StatisticController {
|
|
||||||
private final ReportPeriodService reportPeriodService;
|
|
||||||
private final StatisticService statisticService;
|
|
||||||
|
|
||||||
public StatisticController(ReportPeriodService reportPeriodService,
|
|
||||||
StatisticService statisticService) {
|
|
||||||
this.reportPeriodService = reportPeriodService;
|
|
||||||
this.statisticService = statisticService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("statistic")
|
|
||||||
public String getStatistic(Model model) {
|
|
||||||
model.addAttribute("statisticForm", new StatisticForm());
|
|
||||||
model.addAttribute("reportPeriods", reportPeriodService.getReportPeriods());
|
|
||||||
return "/statistic/statistic";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("statistic")
|
|
||||||
public String getStatistic(StatisticForm form, Model model) {
|
|
||||||
model.addAttribute("rating", statisticService.getRating(form.getReportPeriod().getId()));
|
|
||||||
model.addAttribute("statisticForm", form);
|
|
||||||
model.addAttribute("reportPeriods", reportPeriodService.getReportPeriods());
|
|
||||||
return "/statistic/statistic";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package ru.ulstu.statistic.model;
|
|
||||||
|
|
||||||
import ru.ulstu.aspirant.model.Aspirant;
|
|
||||||
|
|
||||||
public class RatingItem {
|
|
||||||
private Aspirant aspirant;
|
|
||||||
private Integer score;
|
|
||||||
|
|
||||||
public RatingItem() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public RatingItem(Aspirant aspirant, Integer score) {
|
|
||||||
this.aspirant = aspirant;
|
|
||||||
this.score = score;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Aspirant getAspirant() {
|
|
||||||
return aspirant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAspirant(Aspirant aspirant) {
|
|
||||||
this.aspirant = aspirant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getScore() {
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScore(Integer score) {
|
|
||||||
this.score = score;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package ru.ulstu.statistic.model;
|
|
||||||
|
|
||||||
import ru.ulstu.report.model.ReportPeriod;
|
|
||||||
|
|
||||||
public class StatisticForm {
|
|
||||||
private ReportPeriod reportPeriod;
|
|
||||||
|
|
||||||
public ReportPeriod getReportPeriod() {
|
|
||||||
return reportPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReportPeriod(ReportPeriod reportPeriod) {
|
|
||||||
this.reportPeriod = reportPeriod;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package ru.ulstu.statistic.service;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.ulstu.report.repository.ReportRepository;
|
|
||||||
import ru.ulstu.statistic.model.RatingItem;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class StatisticService {
|
|
||||||
private final ReportRepository reportRepository;
|
|
||||||
|
|
||||||
public StatisticService(ReportRepository reportRepository) {
|
|
||||||
this.reportRepository = reportRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RatingItem> getRating(Integer reportPeriodId) {
|
|
||||||
return reportRepository.getRating(reportPeriodId);
|
|
||||||
}
|
|
||||||
}
|
|
@ -72,16 +72,11 @@ public class UserService implements UserDetailsService {
|
|||||||
return userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found by id"));
|
return userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found by id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private User createDefaultUser(String login, String userRole) {
|
private void createDefaultUser(String login, String userRole) {
|
||||||
if (getUserByLogin(login) == null) {
|
if (getUserByLogin(login) == null) {
|
||||||
UserRole role = userRoleRepository.save(new UserRole(userRole.toString()));
|
UserRole role = userRoleRepository.save(new UserRole(userRole.toString()));
|
||||||
return createUser(new User(login, login.equals("admin") ? adminPassword : login, Set.of(role)));
|
createUser(new User(login, login.equals("admin") ? adminPassword : login, Set.of(role)));
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public User createAspirant(String login) {
|
|
||||||
return createDefaultUser(login, UserRoleConstants.ASPIRANT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initDefaultAdmin() {
|
public void initDefaultAdmin() {
|
||||||
@ -99,8 +94,4 @@ public class UserService implements UserDetailsService {
|
|||||||
public void initDefaultHead() {
|
public void initDefaultHead() {
|
||||||
createDefaultUser("head", UserRoleConstants.HEAD);
|
createDefaultUser("head", UserRoleConstants.HEAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getCurrentUser() {
|
|
||||||
return getUserByLogin(UserUtils.getCurrentUserLogin());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,236 +0,0 @@
|
|||||||
// from config.js
|
|
||||||
/* global urlVersions */
|
|
||||||
|
|
||||||
var urlFileUpload = "/files/uploadTmpFile";
|
|
||||||
var urlFileDownload = "/files/download/";
|
|
||||||
var urlFileDownloadTmp = "/files/download-tmp/";
|
|
||||||
|
|
||||||
/* exported MessageTypesEnum */
|
|
||||||
var MessageTypesEnum = {
|
|
||||||
INFO: "info",
|
|
||||||
SUCCESS: "success",
|
|
||||||
WARNING: "warning",
|
|
||||||
DANGER: "danger"
|
|
||||||
};
|
|
||||||
Object.freeze(MessageTypesEnum);
|
|
||||||
|
|
||||||
function isEmpty(value) {
|
|
||||||
if (typeof value === "function") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (value == null || value.length === 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported showFeedbackMessage */
|
|
||||||
function showFeedbackMessage(message, type) {
|
|
||||||
var drawMessage = function (message, type) {
|
|
||||||
var li = $(
|
|
||||||
"<li class=\"alert alert-" + type + "\">" +
|
|
||||||
"<span>" + message + "</span>" +
|
|
||||||
"</li>"
|
|
||||||
);
|
|
||||||
li.click(function () {
|
|
||||||
$(this).remove();
|
|
||||||
});
|
|
||||||
messageDiv.append(li);
|
|
||||||
};
|
|
||||||
|
|
||||||
var liveTimeMs = 15000;
|
|
||||||
var messageDiv = $("#messages");
|
|
||||||
if (isEmpty(message)) {
|
|
||||||
messageDiv.html("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
drawMessage(message, (isEmpty(type) || isEmpty(MessageTypesEnum[type.toUpperCase()]) ?
|
|
||||||
MessageTypesEnum.INFO : type));
|
|
||||||
setTimeout(function () {
|
|
||||||
messageDiv.find("li").first().remove();
|
|
||||||
}, liveTimeMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported errorHandler */
|
|
||||||
function errorHandler(response, callBack, errorCallBack) {
|
|
||||||
if (isEmpty(response)) {
|
|
||||||
showFeedbackMessage("Empty response", MessageTypesEnum.DANGER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isEmpty(response.error)) {
|
|
||||||
// TODO: add l10n
|
|
||||||
// showFeedbackMessage(response.error.code + ": " + response.error.message, MessageTypesEnum.DANGER);
|
|
||||||
if (!isEmpty(errorCallBack)) {
|
|
||||||
errorCallBack(response.data);
|
|
||||||
}
|
|
||||||
throw response.error.code + ": " + response.error.message +
|
|
||||||
" / Details: " + response.error.data;
|
|
||||||
}
|
|
||||||
if (!isEmpty(callBack)) {
|
|
||||||
if (isLoginPageResponse(response)) {
|
|
||||||
window.location.href = "/";
|
|
||||||
} else {
|
|
||||||
callBack(response.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isLoginPageResponse(response) {
|
|
||||||
return (typeof response) === 'string' && response.indexOf("<!DOCTYPE html>") >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported getFromRest */
|
|
||||||
function getFromRest(url, callBack, errorCallBack) {
|
|
||||||
$.ajax({
|
|
||||||
url: url,
|
|
||||||
cache: false,
|
|
||||||
success: function (response) {
|
|
||||||
errorHandler(response, callBack, errorCallBack);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported getFromRestWithVersionAndParams */
|
|
||||||
function getFromRestWithParams(url, params, callBack, errorCallBack) {
|
|
||||||
$.ajax({
|
|
||||||
url: url + "?" + params,
|
|
||||||
cache: false,
|
|
||||||
success: function (response) {
|
|
||||||
errorHandler(response, callBack, errorCallBack);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported postToRest */
|
|
||||||
function postToRest(url, postData, callBack, completeCallback, errorCallBack) {
|
|
||||||
$.ajax({
|
|
||||||
url: url,
|
|
||||||
cache: false,
|
|
||||||
dataType: "json",
|
|
||||||
data: postData,
|
|
||||||
contentType: "application/json; charset=utf-8",
|
|
||||||
processData: false,
|
|
||||||
method: "POST",
|
|
||||||
success: function (response) {
|
|
||||||
errorHandler(response, callBack, errorCallBack);
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
if (isEmpty(completeCallback)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
completeCallback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported postToRestWithVersion */
|
|
||||||
function postToRestWithVersion(url, postData, callBack, errorCallBack) {
|
|
||||||
postToRestWithVersionAndParams(url, postData, "", callBack, errorCallBack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported postToRestWithVersionAndParams */
|
|
||||||
function postToRestWithVersionAndParams(url, postData, params, callBack, errorCallBack) {
|
|
||||||
getCurrentVersion(function (version) {
|
|
||||||
$.ajax({
|
|
||||||
url: url + "?versionId=" + version + params,
|
|
||||||
cache: false,
|
|
||||||
dataType: "json",
|
|
||||||
data: postData,
|
|
||||||
contentType: "application/json; charset=utf-8",
|
|
||||||
processData: false,
|
|
||||||
method: "POST",
|
|
||||||
success: function (response) {
|
|
||||||
errorHandler(response, callBack, errorCallBack);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported putToRestWithVersion */
|
|
||||||
function putToRestWithVersion(url, putData, callBack, errorCallBack) {
|
|
||||||
putToRestWithVersionAndParams(url, putData, "", callBack, errorCallBack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported putToRestWithVersionAndParams */
|
|
||||||
function putToRestWithVersionAndParams(url, putData, params, callBack, errorCallBack) {
|
|
||||||
getCurrentVersion(function (version) {
|
|
||||||
$.ajax({
|
|
||||||
url: url + "?versionId=" + version + params,
|
|
||||||
cache: false,
|
|
||||||
dataType: "json",
|
|
||||||
data: putData,
|
|
||||||
contentType: "application/json; charset=utf-8",
|
|
||||||
processData: false,
|
|
||||||
method: "PUT",
|
|
||||||
success: function (response) {
|
|
||||||
errorHandler(response, callBack, errorCallBack);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported deleteFromRest */
|
|
||||||
function deleteFromRest(url, callBack, completeCallback, errorCallBack) {
|
|
||||||
$.ajax({
|
|
||||||
url: url,
|
|
||||||
cache: false,
|
|
||||||
method: "DELETE",
|
|
||||||
success: function (response) {
|
|
||||||
errorHandler(response, callBack, errorCallBack);
|
|
||||||
},
|
|
||||||
complete: function () {
|
|
||||||
if (isEmpty(completeCallback)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
completeCallback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported fillSelect */
|
|
||||||
function fillSelect(selectElement, values) {
|
|
||||||
$(selectElement).html("");
|
|
||||||
$.each(values, function (key, value) {
|
|
||||||
$(selectElement).append(
|
|
||||||
"<option value=\"" + value.id + "\">" + value.name + "</option>"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported isUrlVarExists */
|
|
||||||
function isUrlVarExists(key) {
|
|
||||||
var URL = window.location.href;
|
|
||||||
if (URL.indexOf("?" + key + "=") !== -1) {
|
|
||||||
return true;
|
|
||||||
} else if (URL.indexOf("&" + key + "=") !== -1) {
|
|
||||||
return true;
|
|
||||||
} else if (URL.indexOf("?" + key + "&") !== -1) {
|
|
||||||
return true;
|
|
||||||
} else if (URL.indexOf("&" + key + "&") !== -1) {
|
|
||||||
return true;
|
|
||||||
} else if (URL.endsWith("?" + key)) {
|
|
||||||
return true;
|
|
||||||
} else if (URL.endsWith("&" + key)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exported getUrlVar */
|
|
||||||
function getUrlVar(key) {
|
|
||||||
var result = new RegExp(key + "=([^&]*)", "i").exec(window.location.search);
|
|
||||||
return result && decodeURIComponent(result[1]) || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendPing(field, url) {
|
|
||||||
id = document.getElementById(field).value
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: url + `?${field}=` + id,
|
|
||||||
contentType: "application/json; charset=utf-8",
|
|
||||||
method: "POST",
|
|
||||||
success: function () {
|
|
||||||
showFeedbackMessage("Ping был отправлен", MessageTypesEnum.SUCCESS)
|
|
||||||
},
|
|
||||||
error: function (errorData) {
|
|
||||||
showFeedbackMessage(errorData.responseJSON.error.message, MessageTypesEnum.WARNING)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,134 +0,0 @@
|
|||||||
// form core.js
|
|
||||||
/* global isEmpty, errorHandler, showFeedbackMessage, MessageTypesEnum */
|
|
||||||
|
|
||||||
/* exported FileLoader */
|
|
||||||
function FileLoader(args) {
|
|
||||||
var MAX_FILE_SIZE_MB = 20;
|
|
||||||
var SIZE_TO_MB = 1048576;
|
|
||||||
var CHOOSE_FILE_TEXT = "Выберите файл";
|
|
||||||
var ALERT_CHOOSE_FILE = "Необходимо выбрать файл";
|
|
||||||
var ALERT_UNKNOWN_FILE_EXT = "Неизвестный тип файлов";
|
|
||||||
var ALERT_MAX_FILE = "Файл превышает разрешенный размер";
|
|
||||||
var ALERT_EMPTY_FILE = "Файл пуст";
|
|
||||||
var ERROR = "Ошибка загрузки файла";
|
|
||||||
|
|
||||||
if (isEmpty(args)) {
|
|
||||||
throw "Empty arguments";
|
|
||||||
}
|
|
||||||
var divId = args.div;
|
|
||||||
if (isEmpty(divId)) {
|
|
||||||
throw "Div id parameter is not set";
|
|
||||||
}
|
|
||||||
var url = args.url;
|
|
||||||
if (isEmpty(url)) {
|
|
||||||
throw "URL parameter is not set";
|
|
||||||
}
|
|
||||||
var callback = args.callback;
|
|
||||||
var maxFileSize = args.maxSize;
|
|
||||||
MAX_FILE_SIZE_MB = Math.min((isEmpty(maxFileSize) ? MAX_FILE_SIZE_MB : maxFileSize), MAX_FILE_SIZE_MB);
|
|
||||||
var fileExtensions = args.extensions;
|
|
||||||
fileExtensions = isEmpty(fileExtensions) ? [] : fileExtensions;
|
|
||||||
|
|
||||||
var div = $("#" + divId).addClass("input-group");
|
|
||||||
if (isEmpty(div)) {
|
|
||||||
throw "Div with id " + divId + " is not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileLabel = $("<input>")
|
|
||||||
.attr("type", "text")
|
|
||||||
.attr("placeholder", CHOOSE_FILE_TEXT)
|
|
||||||
.attr("disabled", true)
|
|
||||||
.addClass("form-control");
|
|
||||||
div.append(fileLabel);
|
|
||||||
var fileInput = $("<input>")
|
|
||||||
.attr("type", "file")
|
|
||||||
.attr("multiple", '')
|
|
||||||
.hide();
|
|
||||||
fileInput.change(function () {
|
|
||||||
var files = $(this).prop("files");
|
|
||||||
if (isEmpty(files)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fileLabel.val(files[0].name);
|
|
||||||
});
|
|
||||||
div.append(fileInput);
|
|
||||||
|
|
||||||
var buttonGroup = $("<div>")
|
|
||||||
.addClass("input-group-btn");
|
|
||||||
div.append(buttonGroup);
|
|
||||||
|
|
||||||
var chooseButton = $("<button>")
|
|
||||||
.attr("type", "button")
|
|
||||||
.addClass("btn btn-default")
|
|
||||||
.append($("<i>").addClass("fa fa-ellipsis-h"));
|
|
||||||
chooseButton.click(function () {
|
|
||||||
fileInput.click();
|
|
||||||
});
|
|
||||||
buttonGroup.append(chooseButton);
|
|
||||||
|
|
||||||
var uploadButton = $("<button>")
|
|
||||||
.attr("type", "button")
|
|
||||||
.addClass("btn btn-default")
|
|
||||||
.append($("<i>").addClass("fa fa-upload"));
|
|
||||||
uploadButton.click(function () {
|
|
||||||
var files = fileInput.prop("files");
|
|
||||||
if (isEmpty(files)) {
|
|
||||||
showFeedbackMessage(ALERT_CHOOSE_FILE, MessageTypesEnum.DANGER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (var i = 0; i < files.length; i++) {
|
|
||||||
var currentFile = files[i];
|
|
||||||
if (!isEmpty(fileExtensions) && fileExtensions.indexOf(getFileExt(currentFile)) === -1) {
|
|
||||||
showFeedbackMessage(ALERT_UNKNOWN_FILE_EXT, MessageTypesEnum.DANGER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (currentFile.size === 0) {
|
|
||||||
showFeedbackMessage(ALERT_EMPTY_FILE, MessageTypesEnum.DANGER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (MAX_FILE_SIZE_MB != -1 && currentFile.size / SIZE_TO_MB > MAX_FILE_SIZE_MB) {
|
|
||||||
showFeedbackMessage(ALERT_MAX_FILE + " " + MAX_FILE_SIZE_MB + "Mb", MessageTypesEnum.DANGER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
upload(currentFile);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
buttonGroup.append(uploadButton);
|
|
||||||
|
|
||||||
var progressDiv = $("<div>")
|
|
||||||
.addClass("progress margined-top-10")
|
|
||||||
.css("background-color", "#FFFFFF");
|
|
||||||
progressDiv.insertAfter(div);
|
|
||||||
var progressBar = $("<div>")
|
|
||||||
.addClass("progress-bar")
|
|
||||||
.attr("role", "progressbar")
|
|
||||||
.css("width", "0%");
|
|
||||||
progressDiv.append(progressBar);
|
|
||||||
|
|
||||||
function getFileExt(file) {
|
|
||||||
return file.name.slice((Math.max(0, file.name.lastIndexOf(".")) || Infinity) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function upload(file) {
|
|
||||||
progressBar.css("width", "0%");
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.upload.onprogress = function (event) {
|
|
||||||
var curProgress = Math.floor(event.loaded / event.total * 100) + "%";
|
|
||||||
progressBar
|
|
||||||
.css("width", curProgress)
|
|
||||||
.text(curProgress);
|
|
||||||
};
|
|
||||||
xhr.onload = xhr.onerror = function () {
|
|
||||||
if (this.status === 200) {
|
|
||||||
errorHandler(JSON.parse(this.responseText), callback);
|
|
||||||
} else {
|
|
||||||
showFeedbackMessage(ERROR, MessageTypesEnum.DANGER);
|
|
||||||
console.error("error " + this.status);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.open("POST", url, true);
|
|
||||||
var formData = new FormData();
|
|
||||||
formData.append("file", file);
|
|
||||||
xhr.send(formData);
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,11 +24,9 @@
|
|||||||
<td th:text="${a.surname}"></td>
|
<td th:text="${a.surname}"></td>
|
||||||
<td th:text="${a.name}"></td>
|
<td th:text="${a.name}"></td>
|
||||||
<td th:text="${a.patronymic}"></td>
|
<td th:text="${a.patronymic}"></td>
|
||||||
<td th:if="${a.course != null}" th:text="${a.course.name}"></td>
|
<td th:text="${a.course.name}"></td>
|
||||||
<td th:if="${a.course == null}"></td>
|
|
||||||
<td th:text="${a.theme}"></td>
|
<td th:text="${a.theme}"></td>
|
||||||
<td th:if="${a.manager != null}" th:text="${a.manager.name}"></td>
|
<td th:text="${a.manager.name}"></td>
|
||||||
<td th:if="${a.manager == null}"></td>
|
|
||||||
<td>
|
<td>
|
||||||
<!-- Ссылка на редактирование -->
|
<!-- Ссылка на редактирование -->
|
||||||
<a th:href="@{'/admin/editAspirant/' + ${a.id}}" class="btn btn-sm btn-primary">
|
<a th:href="@{'/admin/editAspirant/' + ${a.id}}" class="btn btn-sm btn-primary">
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
|
||||||
<html
|
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
|
||||||
layout:decorate="~{default}">
|
|
||||||
<div class="container" layout:fragment="content">
|
|
||||||
<h3>Редактирование отчетного периода:</h3>
|
|
||||||
<form action="#" th:action="@{/admin/saveReportPeriod}"
|
|
||||||
th:object="${reportPeriod}"
|
|
||||||
method="post">
|
|
||||||
<input type="hidden" th:field="*{id}">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="startDate">Дата начала</label>
|
|
||||||
<input th:field="*{startDate}"
|
|
||||||
id="startDate"
|
|
||||||
type="date"
|
|
||||||
required
|
|
||||||
class="form-control">
|
|
||||||
<p th:if="${#fields.hasErrors('startDate')}"
|
|
||||||
th:class="${#fields.hasErrors('startDate')}? error">
|
|
||||||
Ошибка
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="endDate">Дата окончания</label>
|
|
||||||
<input th:field="*{endDate}"
|
|
||||||
id="endDate"
|
|
||||||
type="date"
|
|
||||||
required
|
|
||||||
class="form-control">
|
|
||||||
<p th:if="${#fields.hasErrors('endDate')}"
|
|
||||||
th:class="${#fields.hasErrors('endDate')}? error">
|
|
||||||
Ошибка
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
|
|
||||||
<button name="delete"
|
|
||||||
type="submit"
|
|
||||||
class="btn btn-outline-dark"
|
|
||||||
onclick="return confirm('Удалить запись?')">
|
|
||||||
Удалить
|
|
||||||
</button>
|
|
||||||
<a href="/admin/reportPeriodList" class="btn btn-outline-dark">Отмена</a>
|
|
||||||
</form>
|
|
||||||
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
|
||||||
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
|
|
||||||
</div>
|
|
||||||
</html>
|
|
@ -1,32 +0,0 @@
|
|||||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
|
||||||
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
|
||||||
layout:decorate="~{default}">
|
|
||||||
<div class="container" layout:fragment="content">
|
|
||||||
<a href="/admin/editReportPeriod/0" class="btn btn-outline-dark">
|
|
||||||
<i class="fa fa-plus-square" aria-hidden="true"> Добавить отчетный период</i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Таблица периодов отчетности -->
|
|
||||||
<table class="table table-bordered table-striped mt-3">
|
|
||||||
<thead class="table-dark">
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Дата начала</th>
|
|
||||||
<th scope="col">Дата окончания</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr th:each="r : ${reportPeriods}">
|
|
||||||
<td th:text="${#calendars.format(r.startDate, 'dd.MM.yyyy')}"></td>
|
|
||||||
<td th:text="${#calendars.format(r.endDate, 'dd.MM.yyyy')}"></td>
|
|
||||||
<td>
|
|
||||||
<!-- Ссылка на редактирование -->
|
|
||||||
<a th:href="@{'/admin/editReportPeriod/' + ${r.id}}" class="btn btn-sm btn-primary">
|
|
||||||
<i class="fa fa-edit" aria-hidden="true"></i> Редактировать
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</html>
|
|
114
src/main/resources/templates/aspirant/editReport.html
Normal file
114
src/main/resources/templates/aspirant/editReport.html
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||||
|
<html
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||||
|
layout:decorate="~{default}">
|
||||||
|
<div class="container" layout:fragment="content">
|
||||||
|
<h3 th:text="${'Редактирование отчета аспиранта '} +${report.createDate}"></h3>
|
||||||
|
<form action="#" th:action="@{/aspirant/saveReport}"
|
||||||
|
th:object="${report}"
|
||||||
|
method="post">
|
||||||
|
<input type="hidden" th:field="*{id}">
|
||||||
|
|
||||||
|
<div class="form-group" th:each="i, ind : ${indicators}">
|
||||||
|
<label th:text="${i.name}"></label>
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="form-control btn btn-danger" type="button" onclick="deleteAllFiles();">Удалить все
|
||||||
|
документы
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="input-file" class="form-group">
|
||||||
|
<button class="btn btn-primary btn-upload btn-choose pull-right" type="button">Обзор</button>
|
||||||
|
<button class="btn btn-success btn-upload" type="button" onclick="uploadFile();">Загрузить</button>
|
||||||
|
</div>
|
||||||
|
<div id="file-input-list" class="form-group">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<th:block layout:fragment="scripts">
|
||||||
|
<script src="/js/bootstrap.file-input.js"></script>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
/*<![CDATA[*/
|
||||||
|
$(document).ready(function() {
|
||||||
|
uploadFile = function(index = 0) {
|
||||||
|
const files = $('#input-file .input-ghost').prop('files');
|
||||||
|
if (index == 0) {
|
||||||
|
showFeedbackMessage();
|
||||||
|
$('button').prop('disabled', true);
|
||||||
|
}
|
||||||
|
if (index >= files.length) {
|
||||||
|
$('button').prop('disabled', false);
|
||||||
|
$('#input-file .input-ghost').val('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$('#file-' + index + ' i').removeClass('fa-circle-o').addClass('fa-circle-o-notch fa-spin');
|
||||||
|
$('#file-' + index).removeClass('alert-danger alert-success');
|
||||||
|
var response = false;
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append('file', files[index]);
|
||||||
|
uploadAjax('api/1.0/documents.upload', formData,
|
||||||
|
(result) => {
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response = result.response;
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
() => {
|
||||||
|
var resultIcon = 'fa-times-circle-o';
|
||||||
|
var resultStyle = 'alert-danger';
|
||||||
|
if (response) {
|
||||||
|
resultIcon = 'fa-check-circle-o';
|
||||||
|
resultStyle = 'alert-success';
|
||||||
|
}
|
||||||
|
$('#file-' + index + ' i').removeClass('fa-circle-o-notch fa-spin').addClass(resultIcon);
|
||||||
|
$('#file-' + index).addClass(resultStyle);
|
||||||
|
uploadFile(index + 1);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
deleteAllFiles = function() {
|
||||||
|
$('#file-input-list').html('');
|
||||||
|
//input.replaceWith(input = input.val('').clone(true));
|
||||||
|
$('#spinner').show()
|
||||||
|
getAjax('api/1.0/documents.delete_all',
|
||||||
|
(result) => {
|
||||||
|
if (result.response) {
|
||||||
|
showFeedbackMessage('Удалено ' + result.response + ' документов');
|
||||||
|
}
|
||||||
|
if (result.error) {
|
||||||
|
showFeedbackMessage(result.error, 'danger');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
() => $('#spinner').hide(),
|
||||||
|
'DELETE'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
$('#input-file').bootstrapFileInput(true);
|
||||||
|
});
|
||||||
|
/*]]>*/
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</th:block>
|
||||||
|
|
||||||
|
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
|
||||||
|
<button name="delete"
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-outline-dark"
|
||||||
|
onclick="return confirm('Удалить запись?')">
|
||||||
|
Удалить
|
||||||
|
</button>
|
||||||
|
<a href="/aspirant/reports" class="btn btn-outline-dark">Отмена</a>
|
||||||
|
</form>
|
||||||
|
<div th:if="${indicators.totalPages > 0}" class="pagination">
|
||||||
|
<span style="float: left; padding: 5px 5px;">Страницы:</span>
|
||||||
|
</div>
|
||||||
|
<div th:if="${indicators.totalPages > 0}" class="pagination"
|
||||||
|
th:each="pageNumber : ${pageNumbers}">
|
||||||
|
<a th:href="@{/aspirant/aspirantReport(size=${indicators.size}, page=${pageNumber})}"
|
||||||
|
th:text=${pageNumber}
|
||||||
|
th:class="${pageNumber == indicators.number+1} ? active"></a>
|
||||||
|
</div>
|
||||||
|
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||||
|
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
|
||||||
|
</div>
|
||||||
|
</html>
|
@ -7,7 +7,6 @@
|
|||||||
<title th:text="#{messages.app-name}">app-name</title>
|
<title th:text="#{messages.app-name}">app-name</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script>
|
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="/js/core.js"></script>
|
|
||||||
<script type="text/javascript" src="/webjars/bootstrap/4.3.0/js/bootstrap.bundle.min.js"></script>
|
<script type="text/javascript" src="/webjars/bootstrap/4.3.0/js/bootstrap.bundle.min.js"></script>
|
||||||
<link rel="stylesheet" href="/webjars/bootstrap/4.3.0/css/bootstrap.min.css"/>
|
<link rel="stylesheet" href="/webjars/bootstrap/4.3.0/css/bootstrap.min.css"/>
|
||||||
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||||
@ -37,7 +36,8 @@
|
|||||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
|
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
|
||||||
aria-haspopup="true" aria-expanded="false">Аспиранту</a>
|
aria-haspopup="true" aria-expanded="false">Аспиранту</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
<a class="dropdown-item" href="/report/reportList">Список отчетов</a>
|
<a class="dropdown-item" href="/aspirant/aspirantReport">Новый отчет аспиранта по БРС</a>
|
||||||
|
<a class="dropdown-item" href="/aspirant/listAspirantReports">Список отчетов</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_MANAGER')">
|
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_MANAGER')">
|
||||||
@ -45,16 +45,14 @@
|
|||||||
aria-haspopup="true" aria-expanded="false">Руководителю</a>
|
aria-haspopup="true" aria-expanded="false">Руководителю</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
<a class="dropdown-item" href="/aspirantList">Список аспирантов</a>
|
<a class="dropdown-item" href="/aspirantList">Список аспирантов</a>
|
||||||
<a class="dropdown-item" href="/report/reportList">Список отчетов</a>
|
<a class="dropdown-item" href="/listAspirantReports">Список отчетов</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_HEAD')">
|
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_HEAD')">
|
||||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
|
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
|
||||||
aria-haspopup="true" aria-expanded="false">Аспирантура</a>
|
aria-haspopup="true" aria-expanded="false">Аспирантура</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
<a class="dropdown-item" href="/admin/reportPeriodList">Список периодов отчетности</a>
|
<a class="dropdown-item" href="/listAspirantReports">Список отчетов</a>
|
||||||
<a class="dropdown-item" href="/report/reportList">Список отчетов</a>
|
|
||||||
<a class="dropdown-item" href="/statistic/statistic">Статистика по баллам</a>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_ADMIN')">
|
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_ADMIN')">
|
||||||
@ -64,12 +62,11 @@
|
|||||||
<a class="dropdown-item" href="/admin/indicators">Список показателей</a>
|
<a class="dropdown-item" href="/admin/indicators">Список показателей</a>
|
||||||
<a class="dropdown-item" href="/admin/managers">Список научных руководителей</a>
|
<a class="dropdown-item" href="/admin/managers">Список научных руководителей</a>
|
||||||
<a class="dropdown-item" href="/admin/aspirants">Список аспирантов</a>
|
<a class="dropdown-item" href="/admin/aspirants">Список аспирантов</a>
|
||||||
<a class="dropdown-item" href="/admin/reportPeriodList">Список периодов отчетности</a>
|
<a class="dropdown-item" href="/admin">Новости и заседания</a>
|
||||||
|
<a class="dropdown-item" href="/admin/reports">Отчетность аспирантов</a>
|
||||||
<a class="dropdown-item" href="/admin/rules">Правила БРС</a>
|
<a class="dropdown-item" href="/admin/rules">Правила БРС</a>
|
||||||
<a class="dropdown-item" href="/admin/confirmation">Подтверждение БРС</a>
|
<a class="dropdown-item" href="/admin/confirmation">Подтверждение БРС</a>
|
||||||
<a class="dropdown-item" href="/report/reportList">Список отчетов</a>
|
<a class="dropdown-item" href="/admin/stats">Статистика по баллам</a>
|
||||||
<a class="dropdown-item" href="/statistic/statistic">Статистика по баллам</a>
|
|
||||||
<a class="dropdown-item" href="/admin">Новости и заседания</a>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
@ -1,140 +0,0 @@
|
|||||||
<html
|
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
|
||||||
layout:decorate="~{default}">
|
|
||||||
<div class="container" layout:fragment="content">
|
|
||||||
<h3 th:text="${'Редактирование отчета аспиранта от '} +${#calendars.format(report.createDate, 'dd.MM.yyyy HH:mm')}"></h3>
|
|
||||||
<form action="#" th:action="@{/report/save-report}"
|
|
||||||
th:object="${report}"
|
|
||||||
method="post">
|
|
||||||
<input type="hidden" th:field="*{id}">
|
|
||||||
<input type="hidden" th:field="*{reportPeriodId}">
|
|
||||||
<input type="hidden" th:field="*{createDate}">
|
|
||||||
<input type="hidden" th:field="*{status}">
|
|
||||||
|
|
||||||
<div class="form-group" th:each="rv, ind : *{reportValues}">
|
|
||||||
<a th:if="${report.id != null}"
|
|
||||||
th:href="${'/report-value/edit-report-value/'+report.id + '/' + rv.indicator.id}"
|
|
||||||
th:text="${rv.indicator.name}"></a>
|
|
||||||
<p th:if="${report.id == null}" th:text="${rv.indicator.name}"></p>
|
|
||||||
<p th:text="${rv.indicator.proofDocuments}"></p>
|
|
||||||
<p th:text="'Максимальное количество баллов за показатель: '+ ${rv.indicator.max}"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
|
|
||||||
<button name="delete"
|
|
||||||
type="submit"
|
|
||||||
class="btn btn-outline-dark"
|
|
||||||
th:if="${report.id != null}"
|
|
||||||
onclick="return confirm('Удалить запись?')">
|
|
||||||
Удалить
|
|
||||||
</button>
|
|
||||||
<a href="/report/reportList" class="btn btn-outline-dark">Отмена</a>
|
|
||||||
</form>
|
|
||||||
<script type="text/javascript" src="/js/file-loader.js"></script>
|
|
||||||
<script>
|
|
||||||
/*<![CDATA[*/
|
|
||||||
$(document).ready(function () {
|
|
||||||
new FileLoader({
|
|
||||||
div: "loader",
|
|
||||||
url: urlFileUpload,
|
|
||||||
maxSize: -1,
|
|
||||||
extensions: [],
|
|
||||||
callback: function (response) {
|
|
||||||
console.debug(response);
|
|
||||||
addNewFile(response, $("#files-list"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('.selectpicker').selectpicker();
|
|
||||||
});
|
|
||||||
|
|
||||||
/*]]>*/
|
|
||||||
function addNewFile(fileDto, listElement) {
|
|
||||||
var fileNumber = $('.files-list div.row').length;
|
|
||||||
|
|
||||||
var newFileRow = $("<div/>")
|
|
||||||
.attr("id", 'files' + fileNumber)
|
|
||||||
.addClass("row");
|
|
||||||
|
|
||||||
var idInput = $("<input/>")
|
|
||||||
.attr("type", "hidden")
|
|
||||||
.attr("id", "files" + fileNumber + ".id")
|
|
||||||
.attr("value", '')
|
|
||||||
.attr("name", "files[" + fileNumber + "].id");
|
|
||||||
newFileRow.append(idInput);
|
|
||||||
|
|
||||||
var flagInput = $("<input/>")
|
|
||||||
.attr("type", "hidden")
|
|
||||||
.attr("id", "files" + fileNumber + ".deleted")
|
|
||||||
.attr("value", "false")
|
|
||||||
.attr("name", "files[" + fileNumber + "].deleted");
|
|
||||||
newFileRow.append(flagInput);
|
|
||||||
|
|
||||||
var nameInput = $("<input/>")
|
|
||||||
.attr("type", "hidden")
|
|
||||||
.attr("id", "files" + fileNumber + ".name")
|
|
||||||
.attr("value", fileDto.fileName)
|
|
||||||
.attr("name", "files[" + fileNumber + "].name");
|
|
||||||
newFileRow.append(nameInput);
|
|
||||||
|
|
||||||
var tmpFileNameInput = $("<input/>")
|
|
||||||
.attr("type", "hidden")
|
|
||||||
.attr("id", "files" + fileNumber + ".tmpFileName")
|
|
||||||
.attr("value", fileDto.tmpFileName)
|
|
||||||
.attr("name", "files[" + fileNumber + "].tmpFileName");
|
|
||||||
newFileRow.append(tmpFileNameInput);
|
|
||||||
|
|
||||||
var nextDiv = $("<div/>")
|
|
||||||
.addClass("col-2");
|
|
||||||
|
|
||||||
var nextA = $("<a/>")
|
|
||||||
.addClass("btn btn-danger float-right")
|
|
||||||
.attr("onclick", "$('#files" + fileNumber + "\\\\.deleted').val('true'); $('#files" + fileNumber + "').hide();")
|
|
||||||
.append(($("<span/>").attr("aria-hidden", "true")).append($("<i/>").addClass("fa fa-times")))
|
|
||||||
;
|
|
||||||
nextDiv.append(nextA)
|
|
||||||
newFileRow.append(nextDiv);
|
|
||||||
|
|
||||||
var nameDiv = $("<div/>")
|
|
||||||
.addClass("col-10")
|
|
||||||
.append($("<a/>").text(fileDto.fileName)
|
|
||||||
.attr("href", 'javascript:void(0)')
|
|
||||||
.attr("onclick", "downloadFile('" + fileDto.tmpFileName + "',null,'" + fileDto.fileName + "')"));
|
|
||||||
newFileRow.append(nameDiv);
|
|
||||||
|
|
||||||
listElement.append(newFileRow);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadFile(tmpName, fileId, downloadName) {
|
|
||||||
let xhr = new XMLHttpRequest();
|
|
||||||
if (fileId != null) xhr.open('GET', urlFileDownload + fileId);
|
|
||||||
if (tmpName != null) xhr.open('GET', urlFileDownloadTmp + tmpName);
|
|
||||||
xhr.responseType = 'blob';
|
|
||||||
|
|
||||||
var formData = new FormData();
|
|
||||||
if (fileId != null) formData.append("file-id", fileId);
|
|
||||||
if (tmpName != null) formData.append("tmp-file-name", tmpName);
|
|
||||||
|
|
||||||
xhr.send(formData);
|
|
||||||
|
|
||||||
xhr.onload = function () {
|
|
||||||
if (this.status == 200) {
|
|
||||||
console.debug(this.response);
|
|
||||||
var blob = new Blob([this.response], {type: '*'});
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.style = "display: none";
|
|
||||||
document.body.appendChild(a);
|
|
||||||
let url = window.URL.createObjectURL(blob);
|
|
||||||
a.href = url;
|
|
||||||
a.download = downloadName;
|
|
||||||
a.click();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</html>
|
|
@ -1,189 +0,0 @@
|
|||||||
<html
|
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
|
||||||
xmlns:sec="http://www.w3.org/1999/xhtml"
|
|
||||||
layout:decorate="~{default}">
|
|
||||||
<div class="container" layout:fragment="content">
|
|
||||||
<h3>Редактирование показателя</h3>
|
|
||||||
<h3 th:text="${reportValue.indicator.name + '(' + reportValue.indicator.max + ')'}"></h3>
|
|
||||||
|
|
||||||
<form action="#" th:action="@{/report-value/save-report-value}"
|
|
||||||
th:object="${reportValue}" method="post">
|
|
||||||
<input type="hidden" th:field="*{id}">
|
|
||||||
<input type="hidden" th:field="*{reportId}">
|
|
||||||
<input type="hidden" th:field="*{indicator.id}">
|
|
||||||
|
|
||||||
<div class="row" th:if="${canEdit}">
|
|
||||||
<div class="col col-md-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="form-label" for="loader">Загрузка подтверждающих документов</label>
|
|
||||||
<div id="loader">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group files-list" id="files-list">
|
|
||||||
<div th:each="file, rowStat : ${reportValue.files}">
|
|
||||||
|
|
||||||
<div class="row" th:id="|files${rowStat.index}|"
|
|
||||||
th:style="${file.deleted} ? 'display: none;' :''">
|
|
||||||
<input type="hidden" th:field="*{files[__${rowStat.index}__].id}"/>
|
|
||||||
<input type="hidden"
|
|
||||||
th:field="*{files[__${rowStat.index}__].deleted}"/>
|
|
||||||
<input type="hidden"
|
|
||||||
th:field="*{files[__${rowStat.index}__].name}"/>
|
|
||||||
<input type="hidden"
|
|
||||||
th:field="*{files[__${rowStat.index}__].tmpFileName}"/>
|
|
||||||
<div class="col col-md-1 m-1">
|
|
||||||
<a class="btn btn-danger float-right" th:if="${canEdit}"
|
|
||||||
th:onclick="|$('#files${rowStat.index}\\.deleted').val('true'); $('#files${rowStat.index}').hide(); |">
|
|
||||||
<span><i class="fa fa-times"></i></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="col col-md-8 m-2">
|
|
||||||
<a th:if="${file.id != null}"
|
|
||||||
th:onclick="downloadFile(null, [[${file.id}]], [[${file.name}]])"
|
|
||||||
href="javascript:void(0)"
|
|
||||||
th:text="*{files[__${rowStat.index}__].name}">
|
|
||||||
</a>
|
|
||||||
<a th:if="${file.id == null}"
|
|
||||||
th:onclick="downloadFile([[${file.tmpFileName}]],null,[[${file.name}]])"
|
|
||||||
href="javascript:void(0)"
|
|
||||||
th:text="*{files[__${rowStat.index}__].name}">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col col-md-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="comment" class="form-label">Комментарии</label>
|
|
||||||
<textarea class="form-control" id="comment" th:field="*{comment}" rows="5"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row" sec:authorize="hasAnyRole('ROLE_ADMIN', 'ROLE_MANAGER', ROLE_HEAD)">
|
|
||||||
<div class="col col-md-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="val" class="form-label">Получаемый балл</label>
|
|
||||||
<input type="text" class="form-control" id="val" th:field="*{indicatorValue}" rows="5"></input>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
|
|
||||||
<a th:href="${'/report/edit-report/' + reportValue.reportId}" class="btn btn-outline-dark">Отмена</a>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/file-loader.js"></script>
|
|
||||||
<script>
|
|
||||||
/*<![CDATA[*/
|
|
||||||
$(document).ready(function () {
|
|
||||||
new FileLoader({
|
|
||||||
div: "loader",
|
|
||||||
url: urlFileUpload,
|
|
||||||
maxSize: -1,
|
|
||||||
extensions: [],
|
|
||||||
callback: function (response) {
|
|
||||||
console.debug(response);
|
|
||||||
addNewFile(response, $("#files-list"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/*]]>*/
|
|
||||||
function addNewFile(fileDto, listElement) {
|
|
||||||
var fileNumber = $('.files-list div.row').length;
|
|
||||||
|
|
||||||
var newFileRow = $("<div/>")
|
|
||||||
.attr("id", 'files' + fileNumber)
|
|
||||||
.addClass("row");
|
|
||||||
|
|
||||||
var idInput = $("<input/>")
|
|
||||||
.attr("type", "hidden")
|
|
||||||
.attr("id", "files" + fileNumber + ".id")
|
|
||||||
.attr("value", '')
|
|
||||||
.attr("name", "files[" + fileNumber + "].id");
|
|
||||||
newFileRow.append(idInput);
|
|
||||||
|
|
||||||
var flagInput = $("<input/>")
|
|
||||||
.attr("type", "hidden")
|
|
||||||
.attr("id", "files" + fileNumber + ".deleted")
|
|
||||||
.attr("value", "false")
|
|
||||||
.attr("name", "files[" + fileNumber + "].deleted");
|
|
||||||
newFileRow.append(flagInput);
|
|
||||||
|
|
||||||
var nameInput = $("<input/>")
|
|
||||||
.attr("type", "hidden")
|
|
||||||
.attr("id", "files" + fileNumber + ".name")
|
|
||||||
.attr("value", fileDto.fileName)
|
|
||||||
.attr("name", "files[" + fileNumber + "].name");
|
|
||||||
newFileRow.append(nameInput);
|
|
||||||
|
|
||||||
var tmpFileNameInput = $("<input/>")
|
|
||||||
.attr("type", "hidden")
|
|
||||||
.attr("id", "files" + fileNumber + ".tmpFileName")
|
|
||||||
.attr("value", fileDto.tmpFileName)
|
|
||||||
.attr("name", "files[" + fileNumber + "].tmpFileName");
|
|
||||||
newFileRow.append(tmpFileNameInput);
|
|
||||||
|
|
||||||
var nextDiv = $("<div/>")
|
|
||||||
.addClass("col col-md-1 m-1");
|
|
||||||
|
|
||||||
var nextA = $("<a/>")
|
|
||||||
.addClass("btn btn-danger float-right")
|
|
||||||
.attr("onclick", "$('#files" + fileNumber + "\\\\.deleted').val('true'); $('#files" + fileNumber + "').hide();")
|
|
||||||
.append(($("<span/>").attr("aria-hidden", "true")).append($("<i/>").addClass("fa fa-times")))
|
|
||||||
;
|
|
||||||
nextDiv.append(nextA)
|
|
||||||
newFileRow.append(nextDiv);
|
|
||||||
|
|
||||||
var nameDiv = $("<div/>")
|
|
||||||
.addClass("col-10 m-2")
|
|
||||||
.append($("<a/>").text(fileDto.fileName)
|
|
||||||
.attr("href", 'javascript:void(0)')
|
|
||||||
.attr("onclick", "downloadFile('" + fileDto.tmpFileName + "',null,'" + fileDto.fileName + "')"));
|
|
||||||
newFileRow.append(nameDiv);
|
|
||||||
|
|
||||||
listElement.append(newFileRow);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadFile(tmpName, fileId, downloadName) {
|
|
||||||
let xhr = new XMLHttpRequest();
|
|
||||||
if (fileId != null) xhr.open('GET', urlFileDownload + fileId);
|
|
||||||
if (tmpName != null) xhr.open('GET', urlFileDownloadTmp + tmpName);
|
|
||||||
xhr.responseType = 'blob';
|
|
||||||
|
|
||||||
var formData = new FormData();
|
|
||||||
if (fileId != null) formData.append("file-id", fileId);
|
|
||||||
if (tmpName != null) formData.append("tmp-file-name", tmpName);
|
|
||||||
|
|
||||||
xhr.send(formData);
|
|
||||||
|
|
||||||
xhr.onload = function () {
|
|
||||||
if (this.status == 200) {
|
|
||||||
console.debug(this.response);
|
|
||||||
var blob = new Blob([this.response], {type: '*'});
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.style = "display: none";
|
|
||||||
document.body.appendChild(a);
|
|
||||||
let url = window.URL.createObjectURL(blob);
|
|
||||||
a.href = url;
|
|
||||||
a.download = downloadName;
|
|
||||||
a.click();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</html>
|
|
@ -1,65 +0,0 @@
|
|||||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
|
||||||
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
|
||||||
layout:decorate="~{default}">
|
|
||||||
<div class="container" layout:fragment="content">
|
|
||||||
<form action="/report/reportList" method="post" th:object="${reportListForm}">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col col-md-2">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="period">Период отчетности</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col col-md-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<select class="form-select form-control"
|
|
||||||
id="period" aria-label="multiple select example"
|
|
||||||
th:field="*{reportPeriod}">
|
|
||||||
<option th:each="p : ${reportPeriods}"
|
|
||||||
th:value="${p.id}"
|
|
||||||
th:text="${#calendars.format(p.startDate, 'dd.MM.yyyy') + ' - ' + #calendars.format(p.endDate, 'dd.MM.yyyy')}">
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col col-md-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-outline-dark">Применить</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<a th:href="@{'/report/new-report/'+ ${reportListForm.reportPeriod.id}}" class="btn btn-outline-dark"
|
|
||||||
th:if="${canCreate}">
|
|
||||||
<i class="fa fa-plus-square" aria-hidden="true"> Добавить отчет</i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Таблица аспирантов -->
|
|
||||||
<table class="table table-bordered table-striped mt-3">
|
|
||||||
<thead class="table-dark">
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Период отчета</th>
|
|
||||||
<th scope="col">Аспирант</th>
|
|
||||||
<th scope="col">Дата создания</th>
|
|
||||||
<th scope="col">Статус</th>
|
|
||||||
<th scope="col"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr th:each="r : ${reports}">
|
|
||||||
<td th:text="${#calendars.format(r.reportPeriod.startDate, 'dd.MM.yyyy') + ' - ' + #calendars.format(r.reportPeriod.endDate, 'dd.MM.yyyy')}"></td>
|
|
||||||
<td th:text="${r.aspirant.surname + ' '+ r.aspirant.name + ' '+ r.aspirant.patronymic }"></td>
|
|
||||||
<td th:text="${#calendars.format(r.createDate, 'dd.MM.yyyy HH:mm')}"></td>
|
|
||||||
<td th:if="${r.status != null}" th:text="${r.status.title}"></td>
|
|
||||||
<td th:if="${r.status == null}">не определен</td>
|
|
||||||
<td>
|
|
||||||
<!-- Ссылка на редактирование -->
|
|
||||||
<a th:href="@{'/report/edit-report/' + ${r.id}}" class="btn btn-sm btn-primary">
|
|
||||||
<i class="fa fa-edit" aria-hidden="true"></i> Редактировать
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</html>
|
|
@ -1,49 +0,0 @@
|
|||||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
|
||||||
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
|
||||||
layout:decorate="~{default}">
|
|
||||||
<div class="container" layout:fragment="content">
|
|
||||||
|
|
||||||
<form action="/statistic/statistic" method="post" th:object="${statisticForm}">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col col-md-2">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="period">Период отчетности</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col col-md-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<select class="form-select form-control"
|
|
||||||
id="period" aria-label="multiple select example"
|
|
||||||
th:field="*{reportPeriod}">
|
|
||||||
<option th:each="p : ${reportPeriods}"
|
|
||||||
th:value="${p.id}"
|
|
||||||
th:text="${#calendars.format(p.startDate, 'dd.MM.yyyy') + ' - ' + #calendars.format(p.endDate, 'dd.MM.yyyy')}">
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col col-md-4">
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-outline-dark">Применить</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Таблица рейтинга -->
|
|
||||||
<table class="table table-bordered table-striped mt-3">
|
|
||||||
<thead class="table-dark">
|
|
||||||
<tr>
|
|
||||||
<th scope="col">ФИО</th>
|
|
||||||
<th scope="col">Балл</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr th:each="r : ${rating}">
|
|
||||||
<td th:text="${r.aspirant.surname + ' '+ r.aspirant.name + ' '+ r.aspirant.patronymic }"></td>
|
|
||||||
<td th:text="${r.score}"></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</html>
|
|
Loading…
x
Reference in New Issue
Block a user