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/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/service/AspirantService.java b/src/main/java/ru/ulstu/aspirant/service/AspirantService.java index 7e6d5eb..1d1bba2 100644 --- a/src/main/java/ru/ulstu/aspirant/service/AspirantService.java +++ b/src/main/java/ru/ulstu/aspirant/service/AspirantService.java @@ -47,7 +47,7 @@ public class AspirantService { return aspirantRepository.findByUser(user); } - public List getIndicatorsByCourse() { + 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/FileDataDto.java b/src/main/java/ru/ulstu/file/model/FileDataDto.java index d33e14a..31f538d 100644 --- a/src/main/java/ru/ulstu/file/model/FileDataDto.java +++ b/src/main/java/ru/ulstu/file/model/FileDataDto.java @@ -9,7 +9,6 @@ public class FileDataDto { private String fileName; private String tmpFileName; private boolean deleted; - private Boolean isLatexAttach; public FileDataDto() { } @@ -17,20 +16,17 @@ public class FileDataDto { @JsonCreator public FileDataDto(@JsonProperty("id") Integer id, @JsonProperty("name") String name, - @JsonProperty("isLatexAttach") Boolean isLatexAttach, @JsonProperty("fileName") String fileName, @JsonProperty("tmpFileName") String tmpFileName) { this.id = id; this.name = name; this.fileName = fileName; this.tmpFileName = tmpFileName; - this.isLatexAttach = isLatexAttach; } public FileDataDto(FileData fileData) { this.id = fileData.getId(); this.name = fileData.getName(); - this.isLatexAttach = fileData.isLatexAttach(); } public FileDataDto(String fileName, String tmpFileName) { @@ -77,20 +73,4 @@ public class FileDataDto { public void setDeleted(boolean deleted) { this.deleted = deleted; } - - public Boolean isLatexAttach() { - return isLatexAttach; - } - - public Boolean getIsLatexAttach() { - return isLatexAttach; - } - - public void setLatexAttach(Boolean latexAttach) { - isLatexAttach = latexAttach; - } - - public void setIsLatexAttach(Boolean latexAttach) { - isLatexAttach = latexAttach; - } } diff --git a/src/main/java/ru/ulstu/file/service/FileService.java b/src/main/java/ru/ulstu/file/service/FileService.java index de2bbeb..7195535 100644 --- a/src/main/java/ru/ulstu/file/service/FileService.java +++ b/src/main/java/ru/ulstu/file/service/FileService.java @@ -108,7 +108,6 @@ public class FileService { private FileData copyFromDto(FileData fileData, FileDataDto fileDataDto) { fileData.setName(fileDataDto.getName()); - fileData.setLatexAttach(fileDataDto.isLatexAttach()); return fileData; } 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 index 43174e3..e71f6c7 100644 --- a/src/main/java/ru/ulstu/report/controller/ReportController.java +++ b/src/main/java/ru/ulstu/report/controller/ReportController.java @@ -1,40 +1,35 @@ package ru.ulstu.report.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.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import ru.ulstu.aspirant.service.AspirantService; import ru.ulstu.indicator.model.Indicator; -import ru.ulstu.model.OffsetablePageRequest; -import ru.ulstu.report.model.Report; +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; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.IntStream; @Controller @RequestMapping("report") public class ReportController { - private static final Integer DEFAULT_PAGE_SIZE = 1; - private static final Integer DEFAULT_PAGE_NUMBER = 1; - + private final IndicatorService indicatorService; private final AspirantService aspirantService; private final ReportService reportService; private final ReportPeriodService reportPeriodService; - public ReportController(AspirantService aspirantService, + public ReportController(IndicatorService indicatorService, + AspirantService aspirantService, ReportService reportService, ReportPeriodService reportPeriodService) { + this.indicatorService = indicatorService; this.aspirantService = aspirantService; this.reportService = reportService; this.reportPeriodService = reportPeriodService; @@ -42,9 +37,9 @@ public class ReportController { @GetMapping("reportList") public String getReportPeriods(Model model) { - model.addAttribute("reportListForm", new ReportListForm()); List periods = reportPeriodService.getReportPeriods(); model.addAttribute("reportPeriods", periods); + model.addAttribute("reportListForm", new ReportListForm(periods.isEmpty() ? null : periods.getFirst())); model.addAttribute("canCreate", !periods.isEmpty() && reportService.canCreateReport(periods.getFirst())); return "report/reportList"; } @@ -59,25 +54,12 @@ public class ReportController { return "report/reportList"; } - @GetMapping("editReport/{reportId}") + @GetMapping("editReport/{reportId}/{reportPeriodId}") public String createReport(@PathVariable("reportId") Integer reportId, - 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(0)); + @PathVariable("reportPeriodId") Integer reportPeriodId, + Model model) { + List indicators = aspirantService.getCurrentAspirantIndicators(); + model.addAttribute("report", new ReportDto(reportId, reportPeriodId, indicators)); return "report/editReport"; } } diff --git a/src/main/java/ru/ulstu/report/model/Report.java b/src/main/java/ru/ulstu/report/model/Report.java index b1921a7..4f38096 100644 --- a/src/main/java/ru/ulstu/report/model/Report.java +++ b/src/main/java/ru/ulstu/report/model/Report.java @@ -26,6 +26,9 @@ public class Report extends BaseEntity { @ManyToOne private Aspirant aspirant; + public Report() { + } + public Report(Integer id) { setId(id); } diff --git a/src/main/java/ru/ulstu/report/model/ReportListForm.java b/src/main/java/ru/ulstu/report/model/ReportListForm.java index 3dcde9e..d2f5df3 100644 --- a/src/main/java/ru/ulstu/report/model/ReportListForm.java +++ b/src/main/java/ru/ulstu/report/model/ReportListForm.java @@ -3,6 +3,13 @@ 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; } diff --git a/src/main/java/ru/ulstu/report/model/ReportValue.java b/src/main/java/ru/ulstu/report/model/ReportValue.java index a5f6802..6028520 100644 --- a/src/main/java/ru/ulstu/report/model/ReportValue.java +++ b/src/main/java/ru/ulstu/report/model/ReportValue.java @@ -1,15 +1,28 @@ 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", unique = true) + @Fetch(FetchMode.SUBSELECT) + private List files = new ArrayList<>(); private int indicatorValue; public Indicator getIndicator() { @@ -27,4 +40,12 @@ public class ReportValue extends BaseEntity { public void setIndicatorValue(int indicatorValue) { this.indicatorValue = indicatorValue; } + + public List getFiles() { + return files; + } + + public void setFiles(List files) { + this.files = files; + } } 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..f4798ff --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/dto/ReportDto.java @@ -0,0 +1,52 @@ +package ru.ulstu.report.model.dto; + +import ru.ulstu.indicator.model.Indicator; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class ReportDto { + private Integer id; + private Integer reportPeriodId; + private Date createDate = new Date(); + private List reportValues = new ArrayList<>(); + + public ReportDto(Integer id, Integer reportPeriodId, List indicators) { + this.id = id; + this.reportPeriodId = reportPeriodId; + this.reportValues = indicators.stream().map(ReportValueDto::new).toList(); + } + + 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; + } +} 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..5411ef7 --- /dev/null +++ b/src/main/java/ru/ulstu/report/model/dto/ReportValueDto.java @@ -0,0 +1,44 @@ +package ru.ulstu.report.model.dto; + +import ru.ulstu.file.model.FileDataDto; +import ru.ulstu.indicator.model.Indicator; + +import java.util.ArrayList; +import java.util.List; + +public class ReportValueDto { + private Indicator indicator; + private int indicatorValue; + private List files = new ArrayList<>(); + + public ReportValueDto() { + } + + public ReportValueDto(Indicator indicator) { + this.indicator = indicator; + } + + 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; + } +} diff --git a/src/main/java/ru/ulstu/user/UserService.java b/src/main/java/ru/ulstu/user/UserService.java index 98b419a..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() { 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/report/reportFilesListFragment.html b/src/main/resources/templates/report/reportFilesListFragment.html new file mode 100644 index 0000000..d5e2af5 --- /dev/null +++ b/src/main/resources/templates/report/reportFilesListFragment.html @@ -0,0 +1,43 @@ + + + + + + +
    + + +
    + + + + +
    + + + +
    +
    + + +
    +
    +
    +
    + +
    + +
    +
    +
    + + + \ No newline at end of file diff --git a/src/main/resources/templates/report/reportList.html b/src/main/resources/templates/report/reportList.html index 39f4f43..c88ff70 100644 --- a/src/main/resources/templates/report/reportList.html +++ b/src/main/resources/templates/report/reportList.html @@ -29,7 +29,8 @@ - +