diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..05b076f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // 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" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0ca4d0b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.compile.nullAnalysis.mode": "automatic" +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index a8574e4..eb41045 100644 --- a/build.gradle +++ b/build.gradle @@ -33,8 +33,8 @@ dependencies { implementation group: 'com.h2database', name:'h2' 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: 'com.fasterxml.jackson.module', name: 'jackson-module-blackbird' - implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.13.2' + + implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.8.4' implementation group: 'org.eclipse.jetty', name: 'jetty-servlets', version: '11.0.24' diff --git a/src/main/java/ru/ulstu/admin/controller/AdminReportController.java b/src/main/java/ru/ulstu/admin/controller/AdminReportController.java deleted file mode 100644 index 3018ca4..0000000 --- a/src/main/java/ru/ulstu/admin/controller/AdminReportController.java +++ /dev/null @@ -1,52 +0,0 @@ -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 files) { - // Сохраняем отчет - adminReportService.saveReport(reportForm); - - // Обработка загруженных файлов - if (!files.isEmpty()) { - for (MultipartFile file : files) { - System.out.println("Файл: " + file.getOriginalFilename()); - // Здесь можно добавить логику сохранения файла на сервере - } - } - - return "redirect:/admin/aspirants"; // Перенаправление на список аспирантов - } -} \ No newline at end of file diff --git a/src/main/java/ru/ulstu/admin/service/AdminAspirantService.java b/src/main/java/ru/ulstu/admin/service/AdminAspirantService.java index a0d35e7..fa1c35c 100644 --- a/src/main/java/ru/ulstu/admin/service/AdminAspirantService.java +++ b/src/main/java/ru/ulstu/admin/service/AdminAspirantService.java @@ -7,6 +7,9 @@ import ru.ulstu.aspirant.service.AspirantService; import ru.ulstu.manager.model.Manager; import ru.ulstu.manager.service.ManagerService; 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 java.util.List; @@ -16,13 +19,16 @@ public class AdminAspirantService { private final AspirantService aspirantService; private final ManagerService managerService; private final UserService userService; + private final UserRoleRepository userRoleRepository; public AdminAspirantService(AspirantService aspirantService, ManagerService managerService, - UserService userService) { + UserService userService, + UserRoleRepository userRoleRepository) { this.aspirantService = aspirantService; this.managerService = managerService; this.userService = userService; + this.userRoleRepository = userRoleRepository; } public List getAspirants() { @@ -46,10 +52,18 @@ public class AdminAspirantService { aspirant.setBirthDate(aspirantForm.getBirthDate()); aspirant.setSpeciality(aspirantForm.getSpeciality()); aspirant.setTheme(aspirantForm.getTheme()); - User user = userService.getUserById(aspirantForm.getUserId()); - if (!user.getLogin().equals(aspirantForm.getEmail())) { - user.setLogin(aspirantForm.getEmail()); - userService.createUser(user); + User user; + if (aspirantForm.getUserId() != null) { + user = userService.getUserById(aspirantForm.getUserId()); + if (!user.getLogin().equals(aspirantForm.getEmail())) { + 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); diff --git a/src/main/java/ru/ulstu/aspirant/controller/AspirantController.java b/src/main/java/ru/ulstu/aspirant/controller/AspirantController.java deleted file mode 100644 index f87162b..0000000 --- a/src/main/java/ru/ulstu/aspirant/controller/AspirantController.java +++ /dev/null @@ -1,50 +0,0 @@ -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 page, - @RequestParam Optional size) { - int currentPage = page.orElse(DEFAULT_PAGE_NUMBER); - int pageSize = size.orElse(DEFAULT_PAGE_SIZE); - - Page indicators = aspirantService.getIndicatorsByCourse(new OffsetablePageRequest(currentPage - 1, pageSize)); - model.addAttribute("indicators", indicators); - int totalPages = indicators.getTotalPages(); - if (totalPages > 0) { - List pageNumbers = IntStream.rangeClosed(1, totalPages) - .boxed() - .collect(Collectors.toList()); - model.addAttribute("pageNumbers", pageNumbers); - } - - model.addAttribute("report", new Report()); - return "aspirant/editReport"; - } -} diff --git a/src/main/java/ru/ulstu/aspirant/model/Report.java b/src/main/java/ru/ulstu/aspirant/model/Report.java deleted file mode 100644 index 8bb1771..0000000 --- a/src/main/java/ru/ulstu/aspirant/model/Report.java +++ /dev/null @@ -1,36 +0,0 @@ -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 values = new ArrayList<>(); - - public List getValues() { - return values; - } - - public void setValues(List values) { - this.values = values; - } - - public Date getCreateDate() { - return createDate; - } - - public void setCreateDate(Date createDate) { - this.createDate = createDate; - } -} diff --git a/src/main/java/ru/ulstu/aspirant/model/ReportValue.java b/src/main/java/ru/ulstu/aspirant/model/ReportValue.java deleted file mode 100644 index 37b10da..0000000 --- a/src/main/java/ru/ulstu/aspirant/model/ReportValue.java +++ /dev/null @@ -1,30 +0,0 @@ -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; - } -} diff --git a/src/main/java/ru/ulstu/aspirant/repository/AspirantRepository.java b/src/main/java/ru/ulstu/aspirant/repository/AspirantRepository.java index 4c3f55b..d29b562 100644 --- a/src/main/java/ru/ulstu/aspirant/repository/AspirantRepository.java +++ b/src/main/java/ru/ulstu/aspirant/repository/AspirantRepository.java @@ -2,6 +2,8 @@ package ru.ulstu.aspirant.repository; import org.springframework.data.jpa.repository.JpaRepository; import ru.ulstu.aspirant.model.Aspirant; +import ru.ulstu.model.User; public interface AspirantRepository extends JpaRepository { + Aspirant findByUser(User user); } diff --git a/src/main/java/ru/ulstu/aspirant/service/AspirantService.java b/src/main/java/ru/ulstu/aspirant/service/AspirantService.java index 2b6014a..1d1bba2 100644 --- a/src/main/java/ru/ulstu/aspirant/service/AspirantService.java +++ b/src/main/java/ru/ulstu/aspirant/service/AspirantService.java @@ -6,10 +6,10 @@ import org.springframework.stereotype.Service; import ru.ulstu.admin.model.AspirantForm; import ru.ulstu.aspirant.model.Aspirant; import ru.ulstu.aspirant.repository.AspirantRepository; -import ru.ulstu.indicator.model.Course; import ru.ulstu.indicator.model.Indicator; import ru.ulstu.indicator.service.IndicatorService; -import ru.ulstu.user.UserUtils; +import ru.ulstu.model.User; +import ru.ulstu.user.UserService; import java.util.List; @@ -17,11 +17,14 @@ import java.util.List; public class AspirantService { private final AspirantRepository aspirantRepository; private final IndicatorService indicatorService; + private final UserService userService; public AspirantService(AspirantRepository aspirantRepository, - IndicatorService indicatorService) { + IndicatorService indicatorService, + UserService userService) { this.aspirantRepository = aspirantRepository; this.indicatorService = indicatorService; + this.userService = userService; } public List getAspirants() { @@ -40,14 +43,12 @@ public class AspirantService { aspirantRepository.deleteById(aspirantForm.getId()); } - public Aspirant getAspirantByUser(String currentUserLogin) { - //return aspirantRepository.getAspirantByLogin(); - //TODO: read aspirant - return aspirantRepository.findAll().stream().findAny().orElse(new Aspirant("default", Course.FIRST)); + public Aspirant getAspirantByUser(User user) { + return aspirantRepository.findByUser(user); } - public List getIndicatorsByCourse() { - Aspirant aspirant = getAspirantByUser(UserUtils.getCurrentUserLogin()); + public List getCurrentAspirantIndicators() { + Aspirant aspirant = getAspirantByUser(userService.getCurrentUser()); return indicatorService.getIndicatorsByCourse(aspirant.getCourse()); } diff --git a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java index 97d2cc7..824d4fb 100644 --- a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java +++ b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java @@ -30,12 +30,12 @@ public class SecurityConfiguration { log.debug("Security enabled"); http - .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) + .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth.requestMatchers("/").permitAll() .requestMatchers(permittedUrls).permitAll() - .requestMatchers("/swagger-ui.html").hasAuthority(UserRoleConstants.ADMIN) + .requestMatchers("/swagger-ui/*").hasAuthority(UserRoleConstants.ADMIN) .anyRequest().authenticated()) .formLogin(form -> form.loginPage("/login") diff --git a/src/main/java/ru/ulstu/file/controller/FileController.java b/src/main/java/ru/ulstu/file/controller/FileController.java new file mode 100644 index 0000000..7705425 --- /dev/null +++ b/src/main/java/ru/ulstu/file/controller/FileController.java @@ -0,0 +1,54 @@ +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 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 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 upload(@RequestParam("file") MultipartFile multipartFile) throws IOException { + return new Response<>(fileService.createFromMultipartFile(multipartFile)); + } +} diff --git a/src/main/java/ru/ulstu/file/model/FileData.java b/src/main/java/ru/ulstu/file/model/FileData.java new file mode 100644 index 0000000..f5ee9fe --- /dev/null +++ b/src/main/java/ru/ulstu/file/model/FileData.java @@ -0,0 +1,55 @@ +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; + } +} diff --git a/src/main/java/ru/ulstu/file/model/FileDataDto.java b/src/main/java/ru/ulstu/file/model/FileDataDto.java new file mode 100644 index 0000000..31f538d --- /dev/null +++ b/src/main/java/ru/ulstu/file/model/FileDataDto.java @@ -0,0 +1,76 @@ +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; + } +} diff --git a/src/main/java/ru/ulstu/file/repository/FileRepository.java b/src/main/java/ru/ulstu/file/repository/FileRepository.java new file mode 100644 index 0000000..509cc1b --- /dev/null +++ b/src/main/java/ru/ulstu/file/repository/FileRepository.java @@ -0,0 +1,7 @@ +package ru.ulstu.file.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.file.model.FileData; + +public interface FileRepository extends JpaRepository { +} diff --git a/src/main/java/ru/ulstu/file/service/FileService.java b/src/main/java/ru/ulstu/file/service/FileService.java new file mode 100644 index 0000000..b26f694 --- /dev/null +++ b/src/main/java/ru/ulstu/file/service/FileService.java @@ -0,0 +1,122 @@ +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 saveOrCreate(List fileDtos) throws IOException { + List 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)); + } +} diff --git a/src/main/java/ru/ulstu/files/FileSystemStorageService.java b/src/main/java/ru/ulstu/files/FileSystemStorageService.java deleted file mode 100644 index 805aa2f..0000000 --- a/src/main/java/ru/ulstu/files/FileSystemStorageService.java +++ /dev/null @@ -1,80 +0,0 @@ -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 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); - } - } -} diff --git a/src/main/java/ru/ulstu/files/FileUtil.java b/src/main/java/ru/ulstu/files/FileUtil.java deleted file mode 100644 index e2ccfc2..0000000 --- a/src/main/java/ru/ulstu/files/FileUtil.java +++ /dev/null @@ -1,29 +0,0 @@ -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); - } - } -} diff --git a/src/main/java/ru/ulstu/files/FilesController.java b/src/main/java/ru/ulstu/files/FilesController.java deleted file mode 100644 index 5df8814..0000000 --- a/src/main/java/ru/ulstu/files/FilesController.java +++ /dev/null @@ -1,28 +0,0 @@ -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 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); - } -} diff --git a/src/main/java/ru/ulstu/files/StorageException.java b/src/main/java/ru/ulstu/files/StorageException.java deleted file mode 100644 index eb7da9f..0000000 --- a/src/main/java/ru/ulstu/files/StorageException.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.ulstu.files; - -public class StorageException extends RuntimeException { - - public StorageException(String message) { - super(message); - } - - public StorageException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/ru/ulstu/files/StorageFileNotFoundException.java b/src/main/java/ru/ulstu/files/StorageFileNotFoundException.java deleted file mode 100644 index 085c94d..0000000 --- a/src/main/java/ru/ulstu/files/StorageFileNotFoundException.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.ulstu.files; - -public class StorageFileNotFoundException extends StorageException { - - public StorageFileNotFoundException(String message) { - super(message); - } - - public StorageFileNotFoundException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/ru/ulstu/files/StorageService.java b/src/main/java/ru/ulstu/files/StorageService.java deleted file mode 100644 index 48e3461..0000000 --- a/src/main/java/ru/ulstu/files/StorageService.java +++ /dev/null @@ -1,23 +0,0 @@ -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 loadAll(); - - Path load(String filename); - - Resource loadAsResource(String filename); - - void deleteAll(); - -} diff --git a/src/main/java/ru/ulstu/model/ErrorConstants.java b/src/main/java/ru/ulstu/model/ErrorConstants.java new file mode 100644 index 0000000..89c5483 --- /dev/null +++ b/src/main/java/ru/ulstu/model/ErrorConstants.java @@ -0,0 +1,39 @@ +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); + } +} diff --git a/src/main/java/ru/ulstu/model/response/ControllerResponse.java b/src/main/java/ru/ulstu/model/response/ControllerResponse.java new file mode 100644 index 0000000..09ffab1 --- /dev/null +++ b/src/main/java/ru/ulstu/model/response/ControllerResponse.java @@ -0,0 +1,24 @@ +package ru.ulstu.model.response; + +class ControllerResponse { + private final D data; + private final ControllerResponseError error; + + ControllerResponse(D data) { + this.data = data; + this.error = null; + } + + ControllerResponse(ControllerResponseError error) { + this.data = null; + this.error = error; + } + + public D getData() { + return data; + } + + public ControllerResponseError getError() { + return error; + } +} diff --git a/src/main/java/ru/ulstu/model/response/ControllerResponseError.java b/src/main/java/ru/ulstu/model/response/ControllerResponseError.java new file mode 100644 index 0000000..7bd5c12 --- /dev/null +++ b/src/main/java/ru/ulstu/model/response/ControllerResponseError.java @@ -0,0 +1,26 @@ +package ru.ulstu.model.response; + + +import ru.ulstu.model.ErrorConstants; + +class ControllerResponseError { + 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; + } +} diff --git a/src/main/java/ru/ulstu/model/response/PageableItems.java b/src/main/java/ru/ulstu/model/response/PageableItems.java new file mode 100644 index 0000000..7256c81 --- /dev/null +++ b/src/main/java/ru/ulstu/model/response/PageableItems.java @@ -0,0 +1,21 @@ +package ru.ulstu.model.response; + +import java.util.Collection; + +public class PageableItems { + private final long count; + private final Collection items; + + public PageableItems(long count, Collection items) { + this.count = count; + this.items = items; + } + + public long getCount() { + return count; + } + + public Collection getItems() { + return items; + } +} diff --git a/src/main/java/ru/ulstu/model/response/Response.java b/src/main/java/ru/ulstu/model/response/Response.java new file mode 100644 index 0000000..ec81423 --- /dev/null +++ b/src/main/java/ru/ulstu/model/response/Response.java @@ -0,0 +1,17 @@ +package ru.ulstu.model.response; + + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import ru.ulstu.model.ErrorConstants; + +public class Response extends ResponseEntity { + + public Response(D data) { + super(new ControllerResponse(data), HttpStatus.OK); + } + + public Response(ErrorConstants error) { + super(new ControllerResponse(new ControllerResponseError<>(error, null)), HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/ru/ulstu/model/response/ResponseExtended.java b/src/main/java/ru/ulstu/model/response/ResponseExtended.java new file mode 100644 index 0000000..4bb93f0 --- /dev/null +++ b/src/main/java/ru/ulstu/model/response/ResponseExtended.java @@ -0,0 +1,13 @@ +package ru.ulstu.model.response; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import ru.ulstu.model.ErrorConstants; + + +public class ResponseExtended extends ResponseEntity { + + public ResponseExtended(ErrorConstants error, E errorData) { + super(new ControllerResponse(new ControllerResponseError(error, errorData)), HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/ru/ulstu/report/controller/ReportController.java b/src/main/java/ru/ulstu/report/controller/ReportController.java new file mode 100644 index 0000000..04bf9ce --- /dev/null +++ b/src/main/java/ru/ulstu/report/controller/ReportController.java @@ -0,0 +1,85 @@ +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 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 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 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 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"; + } +} diff --git a/src/main/java/ru/ulstu/report/controller/ReportPeriodController.java b/src/main/java/ru/ulstu/report/controller/ReportPeriodController.java new file mode 100644 index 0000000..550a4a5 --- /dev/null +++ b/src/main/java/ru/ulstu/report/controller/ReportPeriodController.java @@ -0,0 +1,47 @@ +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"; + } +} diff --git a/src/main/java/ru/ulstu/report/controller/ReportValueController.java b/src/main/java/ru/ulstu/report/controller/ReportValueController.java new file mode 100644 index 0000000..0721028 --- /dev/null +++ b/src/main/java/ru/ulstu/report/controller/ReportValueController.java @@ -0,0 +1,39 @@ +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(); + } +} diff --git a/src/main/java/ru/ulstu/report/model/Report.java b/src/main/java/ru/ulstu/report/model/Report.java new file mode 100644 index 0000000..bb8c329 --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/Report.java @@ -0,0 +1,82 @@ +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 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 getValues() { + return values; + } + + public void setValues(List 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; + } +} diff --git a/src/main/java/ru/ulstu/report/model/ReportListForm.java b/src/main/java/ru/ulstu/report/model/ReportListForm.java new file mode 100644 index 0000000..d2f5df3 --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/ReportListForm.java @@ -0,0 +1,20 @@ +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; + } +} diff --git a/src/main/java/ru/ulstu/report/model/ReportPeriod.java b/src/main/java/ru/ulstu/report/model/ReportPeriod.java new file mode 100644 index 0000000..bc2f144 --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/ReportPeriod.java @@ -0,0 +1,36 @@ +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; + } +} diff --git a/src/main/java/ru/ulstu/report/model/ReportStatus.java b/src/main/java/ru/ulstu/report/model/ReportStatus.java new file mode 100644 index 0000000..494059f --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/ReportStatus.java @@ -0,0 +1,18 @@ +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; + } +} diff --git a/src/main/java/ru/ulstu/report/model/ReportValue.java b/src/main/java/ru/ulstu/report/model/ReportValue.java new file mode 100644 index 0000000..9ae1e0e --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/ReportValue.java @@ -0,0 +1,60 @@ +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 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 getFiles() { + return files; + } + + public void setFiles(List files) { + this.files = files; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/src/main/java/ru/ulstu/report/model/dto/ReportDto.java b/src/main/java/ru/ulstu/report/model/dto/ReportDto.java new file mode 100644 index 0000000..cae0461 --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/dto/ReportDto.java @@ -0,0 +1,76 @@ +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 reportValues = new ArrayList<>(); + private ReportStatus status; + + public ReportDto() { + } + + public ReportDto(Integer reportPeriodId, List indicators) { + this.reportPeriodId = reportPeriodId; + this.reportValues = indicators.stream().map(ReportValueDto::new).toList(); + this.status = ReportStatus.NEW; + } + + public ReportDto(Report report, List 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 getReportValues() { + return reportValues; + } + + public void setReportValues(List 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; + } +} diff --git a/src/main/java/ru/ulstu/report/model/dto/ReportValueDto.java b/src/main/java/ru/ulstu/report/model/dto/ReportValueDto.java new file mode 100644 index 0000000..19e776e --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/dto/ReportValueDto.java @@ -0,0 +1,87 @@ +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 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 getFiles() { + return files; + } + + public void setFiles(List 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; + } +} diff --git a/src/main/java/ru/ulstu/report/repository/ReportPeriodRepository.java b/src/main/java/ru/ulstu/report/repository/ReportPeriodRepository.java new file mode 100644 index 0000000..ef989e4 --- /dev/null +++ b/src/main/java/ru/ulstu/report/repository/ReportPeriodRepository.java @@ -0,0 +1,10 @@ +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 { + List findAllByOrderByStartDateDesc(); +} diff --git a/src/main/java/ru/ulstu/report/repository/ReportRepository.java b/src/main/java/ru/ulstu/report/repository/ReportRepository.java new file mode 100644 index 0000000..3b6fe43 --- /dev/null +++ b/src/main/java/ru/ulstu/report/repository/ReportRepository.java @@ -0,0 +1,25 @@ +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 { + + List 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 getRating(@Param("reportPeriodId") Integer reportPeriodId); + + @Query("SELECT DISTINCT v.indicator FROM Report r JOIN r.values v WHERE r.id = :reportId") + List getIndicatorsById(@Param("reportId") Integer reportId); +} diff --git a/src/main/java/ru/ulstu/report/repository/ReportValueRepository.java b/src/main/java/ru/ulstu/report/repository/ReportValueRepository.java new file mode 100644 index 0000000..c4a0eba --- /dev/null +++ b/src/main/java/ru/ulstu/report/repository/ReportValueRepository.java @@ -0,0 +1,11 @@ +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 { + @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); +} diff --git a/src/main/java/ru/ulstu/report/service/ReportPeriodService.java b/src/main/java/ru/ulstu/report/service/ReportPeriodService.java new file mode 100644 index 0000000..7c3bdc9 --- /dev/null +++ b/src/main/java/ru/ulstu/report/service/ReportPeriodService.java @@ -0,0 +1,42 @@ +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 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")); + } +} diff --git a/src/main/java/ru/ulstu/report/service/ReportService.java b/src/main/java/ru/ulstu/report/service/ReportService.java new file mode 100644 index 0000000..0341a26 --- /dev/null +++ b/src/main/java/ru/ulstu/report/service/ReportService.java @@ -0,0 +1,77 @@ +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 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 getIndicators(Integer reportId) { + return reportRepository.getIndicatorsById(reportId); + } +} diff --git a/src/main/java/ru/ulstu/report/service/ReportValueService.java b/src/main/java/ru/ulstu/report/service/ReportValueService.java new file mode 100644 index 0000000..9d8e9ba --- /dev/null +++ b/src/main/java/ru/ulstu/report/service/ReportValueService.java @@ -0,0 +1,81 @@ +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 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(); + } +} diff --git a/src/main/java/ru/ulstu/statistic/controller/StatisticController.java b/src/main/java/ru/ulstu/statistic/controller/StatisticController.java new file mode 100644 index 0000000..77259e7 --- /dev/null +++ b/src/main/java/ru/ulstu/statistic/controller/StatisticController.java @@ -0,0 +1,38 @@ +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"; + } +} \ No newline at end of file diff --git a/src/main/java/ru/ulstu/statistic/model/RatingItem.java b/src/main/java/ru/ulstu/statistic/model/RatingItem.java new file mode 100644 index 0000000..8765028 --- /dev/null +++ b/src/main/java/ru/ulstu/statistic/model/RatingItem.java @@ -0,0 +1,32 @@ +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; + } +} diff --git a/src/main/java/ru/ulstu/statistic/model/StatisticForm.java b/src/main/java/ru/ulstu/statistic/model/StatisticForm.java new file mode 100644 index 0000000..670eeae --- /dev/null +++ b/src/main/java/ru/ulstu/statistic/model/StatisticForm.java @@ -0,0 +1,15 @@ +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; + } +} diff --git a/src/main/java/ru/ulstu/statistic/service/StatisticService.java b/src/main/java/ru/ulstu/statistic/service/StatisticService.java new file mode 100644 index 0000000..d7a4335 --- /dev/null +++ b/src/main/java/ru/ulstu/statistic/service/StatisticService.java @@ -0,0 +1,20 @@ +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 getRating(Integer reportPeriodId) { + return reportRepository.getRating(reportPeriodId); + } +} diff --git a/src/main/java/ru/ulstu/user/UserService.java b/src/main/java/ru/ulstu/user/UserService.java index 9634e54..219511d 100644 --- a/src/main/java/ru/ulstu/user/UserService.java +++ b/src/main/java/ru/ulstu/user/UserService.java @@ -72,11 +72,16 @@ public class UserService implements UserDetailsService { return userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found by id")); } - private void createDefaultUser(String login, String userRole) { + private User createDefaultUser(String login, String userRole) { if (getUserByLogin(login) == null) { UserRole role = userRoleRepository.save(new UserRole(userRole.toString())); - createUser(new User(login, login.equals("admin") ? adminPassword : login, Set.of(role))); + return 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() { @@ -94,4 +99,8 @@ public class UserService implements UserDetailsService { public void initDefaultHead() { createDefaultUser("head", UserRoleConstants.HEAD); } + + public User getCurrentUser() { + return getUserByLogin(UserUtils.getCurrentUserLogin()); + } } diff --git a/src/main/resources/public/js/core.js b/src/main/resources/public/js/core.js new file mode 100644 index 0000000..ca773c8 --- /dev/null +++ b/src/main/resources/public/js/core.js @@ -0,0 +1,236 @@ +// 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 = $( + "
  • " + + "" + message + "" + + "
  • " + ); + 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("") >= 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( + "" + ); + }); +} + +/* 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) + } + }) +} \ No newline at end of file diff --git a/src/main/resources/public/js/file-loader.js b/src/main/resources/public/js/file-loader.js new file mode 100644 index 0000000..1ba467b --- /dev/null +++ b/src/main/resources/public/js/file-loader.js @@ -0,0 +1,134 @@ +// 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 = $("") + .attr("type", "text") + .attr("placeholder", CHOOSE_FILE_TEXT) + .attr("disabled", true) + .addClass("form-control"); + div.append(fileLabel); + var fileInput = $("") + .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 = $("
    ") + .addClass("input-group-btn"); + div.append(buttonGroup); + + var chooseButton = $(" + + Отмена + + + +
    + diff --git a/src/main/resources/templates/admin/reportPeriodList.html b/src/main/resources/templates/admin/reportPeriodList.html new file mode 100644 index 0000000..9f341c4 --- /dev/null +++ b/src/main/resources/templates/admin/reportPeriodList.html @@ -0,0 +1,32 @@ + + +
    + + + + + + + + + + + + + + + + + + + + +
    Дата началаДата окончания
    + + + Редактировать + +
    +
    + \ No newline at end of file diff --git a/src/main/resources/templates/aspirant/editReport.html b/src/main/resources/templates/aspirant/editReport.html deleted file mode 100644 index 045392e..0000000 --- a/src/main/resources/templates/aspirant/editReport.html +++ /dev/null @@ -1,114 +0,0 @@ - - -
    -

    -
    - - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    - - - - - - - - Отмена -
    - - - - -
    - diff --git a/src/main/resources/templates/default.html b/src/main/resources/templates/default.html index ed43437..62bcc1c 100644 --- a/src/main/resources/templates/default.html +++ b/src/main/resources/templates/default.html @@ -7,6 +7,7 @@ app-name + @@ -36,8 +37,7 @@