Compare commits
58 Commits
Author | SHA1 | Date | |
---|---|---|---|
8e74e8911c | |||
a9c51790ea | |||
3791f10b8e | |||
7d63899fb2 | |||
faa081f828 | |||
27755c2d4a | |||
3d69996091 | |||
82823d6245 | |||
7d40a52f19 | |||
0ec47113d1 | |||
0fee0ab9ce | |||
3546e016e1 | |||
6e4218fe74 | |||
c62774aebb | |||
6770d1645c | |||
732ffc3441 | |||
36d6f44378 | |||
fcdd90924c | |||
e7ef4099fa | |||
07fcbce47b | |||
a8912f8d8c | |||
54647813ab | |||
48c614a9ca | |||
a4978fd2af | |||
a630df317c | |||
|
10b6835a31 | ||
04b3b311a9 | |||
55ff385407 | |||
d36bdf6eca | |||
fc480dd559 | |||
1ac50fdd54 | |||
5155da2542 | |||
290bec8f88 | |||
d4a797cfc3 | |||
ebb29d49d3 | |||
d04c61b683 | |||
32d8779fd4 | |||
85936721aa | |||
f15a658f56 | |||
4d1844d256 | |||
a503a36e8b | |||
3b877050b7 | |||
232dc68db4 | |||
da65669c90 | |||
6ad4ea0083 | |||
10f65e11a2 | |||
a64c2772bd | |||
ec97b15c39 | |||
779ae11861 | |||
bf57c20b96 | |||
8b8d64bd00 | |||
2ef33f1b68 | |||
5a4a968015 | |||
405060152a | |||
7320f287c6 | |||
595eb12607 | |||
1e13c57938 | |||
b31dc27e7b |
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,7 @@
|
||||
.gradle
|
||||
out
|
||||
build
|
||||
data
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"java.compile.nullAnalysis.mode": "automatic"
|
||||
}
|
21
README.md
21
README.md
@ -1,9 +1,20 @@
|
||||
# seminar
|
||||
# Портал для аспирантов
|
||||
|
||||
JDK: https://download.oracle.com/java/17/archive/jdk-17.0.6_windows-x64_bin.exe
|
||||
Порядок развертывания проекта разработчиками:
|
||||
|
||||
IDE: IntelliJIDEA community version https://www.jetbrains.com/ru-ru/idea/download/#section=windows
|
||||
1. Скачать и установить JDK (используется 21 LTS
|
||||
JDK): https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe
|
||||
|
||||
To run: run project and open http://localhost:8080/
|
||||
2. Проверить установку, набрав в консоли команду "java -version"
|
||||
|
||||
Demo: http://seminar.athene.tech
|
||||
3. Скачать и установить IDE: IntelliJIDEA Сommunity
|
||||
version https://www.jetbrains.com/ru-ru/idea/download/#section=windows
|
||||
|
||||
4. Скачать и открыть проект в IDE:
|
||||
|
||||

|
||||
5. Сформировать конфигурацию для запуска:
|
||||

|
||||
6. Запустить проект.
|
||||
7. Открыть страницу в браузере http://localhost:8080/
|
||||
8. Enjoy.
|
||||
|
@ -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'
|
||||
|
||||
|
@ -24,5 +24,8 @@ public class SeminarApplication {
|
||||
public void doSomethingAfterStartup() {
|
||||
System.out.println("hello world, I have just started up");
|
||||
userService.initDefaultAdmin();
|
||||
userService.initDefaultAspirant();
|
||||
userService.initDefaultHead();
|
||||
userService.initDefaultManager();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
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.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import ru.ulstu.admin.model.AspirantForm;
|
||||
import ru.ulstu.admin.service.AdminAspirantService;
|
||||
import ru.ulstu.aspirant.model.Aspirant;
|
||||
import ru.ulstu.indicator.model.Course;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("admin")
|
||||
public class AdminAspirantController {
|
||||
private final AdminAspirantService adminAspirantService;
|
||||
|
||||
public AdminAspirantController(AdminAspirantService adminAspirantService) {
|
||||
this.adminAspirantService = adminAspirantService;
|
||||
}
|
||||
|
||||
@GetMapping("aspirants")
|
||||
public String getListOfAspirants(Model model) {
|
||||
model.addAttribute("aspirants", adminAspirantService.getAspirants());
|
||||
return "admin/aspirantsList";
|
||||
}
|
||||
|
||||
@GetMapping("/editAspirant/{aspirantId}")
|
||||
public String editAspirant(@PathVariable(value = "aspirantId") Integer id, Model model) {
|
||||
model.addAttribute("aspirant",
|
||||
new AspirantForm((id != null && id != 0)
|
||||
? adminAspirantService.getAspirantById(id)
|
||||
: new Aspirant()));
|
||||
model.addAttribute("courses", Course.values());
|
||||
model.addAttribute("managers", adminAspirantService.getManagers());
|
||||
return "admin/editAspirant";
|
||||
}
|
||||
|
||||
@PostMapping(value = "saveAspirant", params = "save")
|
||||
public String saveAspirant(AspirantForm aspirantForm, Model model) {
|
||||
adminAspirantService.saveAspirant(aspirantForm);
|
||||
return "redirect:/admin/aspirants";
|
||||
}
|
||||
|
||||
@PostMapping(value = "saveAspirant", params = "delete")
|
||||
public String deleteIndicator(AspirantForm aspirantForm, Model model) {
|
||||
adminAspirantService.deleteAspirant(aspirantForm);
|
||||
return "redirect:/admin/aspirants";
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package ru.ulstu.admin.controller;
|
||||
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
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.admin.model.IndicatorForm;
|
||||
import ru.ulstu.admin.service.AdminIndicatorService;
|
||||
import ru.ulstu.indicator.model.Course;
|
||||
import ru.ulstu.indicator.model.Indicator;
|
||||
import ru.ulstu.model.UserRoleConstants;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin")
|
||||
@Secured({UserRoleConstants.ADMIN})
|
||||
public class AdminIndicatorController {
|
||||
private final AdminIndicatorService adminIndicatorService;
|
||||
|
||||
public AdminIndicatorController(AdminIndicatorService adminIndicatorService) {
|
||||
this.adminIndicatorService = adminIndicatorService;
|
||||
}
|
||||
|
||||
@GetMapping("indicators")
|
||||
public String getListOfIndicators(Model model) {
|
||||
model.addAttribute("indicators", adminIndicatorService.getIndicators());
|
||||
return "admin/indicatorsList";
|
||||
}
|
||||
|
||||
@GetMapping("/editIndicator/{indicatorId}")
|
||||
public String editIndicator(@PathVariable(value = "indicatorId") Integer id, Model model) {
|
||||
model.addAttribute("indicator",
|
||||
(id != null && id != 0)
|
||||
? adminIndicatorService.getIndicatorById(id)
|
||||
: new Indicator());
|
||||
model.addAttribute("courses", Course.values());
|
||||
return "admin/editIndicator";
|
||||
}
|
||||
|
||||
@PostMapping(value = "saveIndicator", params = "save")
|
||||
public String saveIndicator(IndicatorForm indicatorForm, Model model) {
|
||||
adminIndicatorService.saveIndicator(indicatorForm);
|
||||
return "redirect:/admin/indicators";
|
||||
}
|
||||
|
||||
@PostMapping(value = "saveIndicator", params = "delete")
|
||||
public String deleteIndicator(IndicatorForm indicatorForm, Model model) {
|
||||
adminIndicatorService.deleteIndicator(indicatorForm);
|
||||
return "redirect:/admin/indicators";
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
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.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import ru.ulstu.admin.model.ManagerForm;
|
||||
import ru.ulstu.admin.service.AdminManagerService;
|
||||
import ru.ulstu.manager.model.Manager;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("admin")
|
||||
public class AdminManagerController {
|
||||
private final AdminManagerService adminManagerService;
|
||||
|
||||
public AdminManagerController(AdminManagerService adminManagerService) {
|
||||
this.adminManagerService = adminManagerService;
|
||||
}
|
||||
|
||||
@GetMapping("managers")
|
||||
public String getListOfManagers(Model model) {
|
||||
model.addAttribute("managers", adminManagerService.getManagers());
|
||||
return "admin/managersList";
|
||||
}
|
||||
|
||||
@GetMapping("/editManager/{managerId}")
|
||||
public String editManager(@PathVariable(value = "managerId") Integer id, Model model) {
|
||||
model.addAttribute("manager",
|
||||
(id != null && id != 0)
|
||||
? adminManagerService.getManagerById(id)
|
||||
: new Manager());
|
||||
return "admin/editManager";
|
||||
}
|
||||
|
||||
@PostMapping(value = "saveManager", params = "save")
|
||||
public String saveManager(ManagerForm managerForm, Model model) {
|
||||
adminManagerService.saveManager(managerForm);
|
||||
return "redirect:/admin/managers";
|
||||
}
|
||||
|
||||
@PostMapping(value = "saveManager", params = "delete")
|
||||
public String deleteIndicator(ManagerForm managerForm, Model model) {
|
||||
adminManagerService.deleteManager(managerForm);
|
||||
return "redirect:/admin/managers";
|
||||
}
|
||||
}
|
137
src/main/java/ru/ulstu/admin/model/AspirantForm.java
Normal file
137
src/main/java/ru/ulstu/admin/model/AspirantForm.java
Normal file
@ -0,0 +1,137 @@
|
||||
package ru.ulstu.admin.model;
|
||||
|
||||
import ru.ulstu.aspirant.model.Aspirant;
|
||||
import ru.ulstu.aspirant.model.Base;
|
||||
import ru.ulstu.aspirant.model.Speciality;
|
||||
import ru.ulstu.indicator.model.Course;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class AspirantForm {
|
||||
private Integer id;
|
||||
private String surname;
|
||||
private String name;
|
||||
private String patronymic;
|
||||
private Course course;
|
||||
private Integer managerId;
|
||||
private Date birthDate;
|
||||
private Speciality speciality;
|
||||
private String theme;
|
||||
private Base base;
|
||||
private Integer userId;
|
||||
private String email;
|
||||
|
||||
public AspirantForm() {
|
||||
}
|
||||
|
||||
public AspirantForm(Aspirant aspirant) {
|
||||
this.id = aspirant.getId();
|
||||
this.name = aspirant.getName();
|
||||
this.surname = aspirant.getSurname();
|
||||
this.patronymic = aspirant.getPatronymic();
|
||||
this.base = aspirant.getBase();
|
||||
this.course = aspirant.getCourse();
|
||||
this.managerId = aspirant.getManager() == null ? null : aspirant.getManager().getId();
|
||||
this.birthDate = aspirant.getBirthDate();
|
||||
this.speciality = aspirant.getSpeciality();
|
||||
this.theme = aspirant.getTheme();
|
||||
this.userId = aspirant.getUser() == null ? null : aspirant.getUser().getId();
|
||||
this.email = aspirant.getUser() == null ? null : aspirant.getUser().getLogin();
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getSurname() {
|
||||
return surname;
|
||||
}
|
||||
|
||||
public void setSurname(String surname) {
|
||||
this.surname = surname;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPatronymic() {
|
||||
return patronymic;
|
||||
}
|
||||
|
||||
public void setPatronymic(String patronymic) {
|
||||
this.patronymic = patronymic;
|
||||
}
|
||||
|
||||
public Course getCourse() {
|
||||
return course;
|
||||
}
|
||||
|
||||
public void setCourse(Course course) {
|
||||
this.course = course;
|
||||
}
|
||||
|
||||
public Integer getManagerId() {
|
||||
return managerId;
|
||||
}
|
||||
|
||||
public void setManagerId(Integer managerId) {
|
||||
this.managerId = managerId;
|
||||
}
|
||||
|
||||
public Date getBirthDate() {
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(Date birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public Speciality getSpeciality() {
|
||||
return speciality;
|
||||
}
|
||||
|
||||
public void setSpeciality(Speciality speciality) {
|
||||
this.speciality = speciality;
|
||||
}
|
||||
|
||||
public String getTheme() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
public void setTheme(String theme) {
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
public Base getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public void setBase(Base base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public Integer getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Integer userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
}
|
69
src/main/java/ru/ulstu/admin/model/IndicatorForm.java
Normal file
69
src/main/java/ru/ulstu/admin/model/IndicatorForm.java
Normal file
@ -0,0 +1,69 @@
|
||||
package ru.ulstu.admin.model;
|
||||
|
||||
import ru.ulstu.indicator.model.Course;
|
||||
import ru.ulstu.indicator.model.Indicator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IndicatorForm {
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
private int max;
|
||||
|
||||
private String proofDocuments;
|
||||
|
||||
private List<Course> courses = new ArrayList<>();
|
||||
|
||||
public IndicatorForm() {
|
||||
}
|
||||
|
||||
public IndicatorForm(Indicator indicator) {
|
||||
this.name = indicator.getName();
|
||||
this.max = indicator.getMax();
|
||||
this.proofDocuments = indicator.getProofDocuments();
|
||||
this.courses = indicator.getCourses();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public void setMax(int max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public String getProofDocuments() {
|
||||
return proofDocuments;
|
||||
}
|
||||
|
||||
public void setProofDocuments(String proofDocuments) {
|
||||
this.proofDocuments = proofDocuments;
|
||||
}
|
||||
|
||||
public List<Course> getCourses() {
|
||||
return courses;
|
||||
}
|
||||
|
||||
public void setCourses(List<Course> courses) {
|
||||
this.courses = courses;
|
||||
}
|
||||
}
|
32
src/main/java/ru/ulstu/admin/model/ManagerForm.java
Normal file
32
src/main/java/ru/ulstu/admin/model/ManagerForm.java
Normal file
@ -0,0 +1,32 @@
|
||||
package ru.ulstu.admin.model;
|
||||
|
||||
import ru.ulstu.manager.model.Manager;
|
||||
|
||||
public class ManagerForm {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
public ManagerForm() {
|
||||
}
|
||||
|
||||
public ManagerForm(Manager manager) {
|
||||
this.id = manager.getId();
|
||||
this.name = manager.getName();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
51
src/main/java/ru/ulstu/admin/model/ReportForm.java
Normal file
51
src/main/java/ru/ulstu/admin/model/ReportForm.java
Normal file
@ -0,0 +1,51 @@
|
||||
package ru.ulstu.admin.model;
|
||||
|
||||
public class ReportForm {
|
||||
private Integer id; // ID отчета
|
||||
private Integer aspirantId; // ID аспиранта
|
||||
private Integer courseWorkScore; // Баллы за курсовую работу
|
||||
private Integer researchScore; // Баллы за научные исследования
|
||||
private Integer publicationsScore; // Баллы за публикации
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
// Геттер и сеттер для aspirantId
|
||||
public Integer getAspirantId() {
|
||||
return aspirantId;
|
||||
}
|
||||
|
||||
public void setAspirantId(Integer aspirantId) {
|
||||
this.aspirantId = aspirantId;
|
||||
}
|
||||
|
||||
// Геттеры и сеттеры для других полей (если их нет)
|
||||
public Integer getCourseWorkScore() {
|
||||
return courseWorkScore;
|
||||
}
|
||||
|
||||
public void setCourseWorkScore(Integer courseWorkScore) {
|
||||
this.courseWorkScore = courseWorkScore;
|
||||
}
|
||||
|
||||
public Integer getResearchScore() {
|
||||
return researchScore;
|
||||
}
|
||||
|
||||
public void setResearchScore(Integer researchScore) {
|
||||
this.researchScore = researchScore;
|
||||
}
|
||||
|
||||
public Integer getPublicationsScore() {
|
||||
return publicationsScore;
|
||||
}
|
||||
|
||||
public void setPublicationsScore(Integer publicationsScore) {
|
||||
this.publicationsScore = publicationsScore;
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package ru.ulstu.admin.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.admin.model.AspirantForm;
|
||||
import ru.ulstu.aspirant.model.Aspirant;
|
||||
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;
|
||||
|
||||
@Service
|
||||
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,
|
||||
UserRoleRepository userRoleRepository) {
|
||||
this.aspirantService = aspirantService;
|
||||
this.managerService = managerService;
|
||||
this.userService = userService;
|
||||
this.userRoleRepository = userRoleRepository;
|
||||
}
|
||||
|
||||
public List<Aspirant> getAspirants() {
|
||||
return aspirantService.getAspirants();
|
||||
}
|
||||
|
||||
public Aspirant getAspirantById(Integer id) {
|
||||
return aspirantService.getAspirantById(id);
|
||||
}
|
||||
|
||||
public void saveAspirant(AspirantForm aspirantForm) {
|
||||
Aspirant aspirant = aspirantForm.getId() == null
|
||||
? new Aspirant()
|
||||
: aspirantService.getAspirantById(aspirantForm.getId());
|
||||
aspirant.setName(aspirantForm.getName());
|
||||
aspirant.setSurname(aspirantForm.getSurname());
|
||||
aspirant.setPatronymic(aspirantForm.getPatronymic());
|
||||
aspirant.setBase(aspirantForm.getBase());
|
||||
aspirant.setCourse(aspirantForm.getCourse());
|
||||
aspirant.setManager(managerService.getManagerById(aspirantForm.getManagerId()));
|
||||
aspirant.setBirthDate(aspirantForm.getBirthDate());
|
||||
aspirant.setSpeciality(aspirantForm.getSpeciality());
|
||||
aspirant.setTheme(aspirantForm.getTheme());
|
||||
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);
|
||||
|
||||
aspirantService.save(aspirant);
|
||||
}
|
||||
|
||||
public void deleteAspirant(AspirantForm aspirantForm) {
|
||||
aspirantService.deleteAspirant(aspirantForm);
|
||||
}
|
||||
|
||||
public List<Manager> getManagers() {
|
||||
return managerService.getManagers();
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package ru.ulstu.admin.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.admin.model.IndicatorForm;
|
||||
import ru.ulstu.indicator.model.Indicator;
|
||||
import ru.ulstu.indicator.service.IndicatorService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AdminIndicatorService {
|
||||
private final IndicatorService indicatorService;
|
||||
|
||||
public AdminIndicatorService(IndicatorService indicatorService) {
|
||||
this.indicatorService = indicatorService;
|
||||
}
|
||||
|
||||
public List<Indicator> getIndicators() {
|
||||
return indicatorService.getIndicatorList();
|
||||
}
|
||||
|
||||
public void saveIndicator(IndicatorForm indicatorForm) {
|
||||
Indicator indicator = indicatorForm.getId() == null
|
||||
? new Indicator()
|
||||
: indicatorService.getIndicatorById(indicatorForm.getId());
|
||||
indicator.setName(indicatorForm.getName());
|
||||
indicator.setMax(indicatorForm.getMax());
|
||||
indicator.setProofDocuments(indicatorForm.getProofDocuments());
|
||||
indicator.setCourses(indicatorForm.getCourses());
|
||||
indicatorService.save(indicator);
|
||||
}
|
||||
|
||||
public Indicator getIndicatorById(Integer id) {
|
||||
return indicatorService.getIndicatorById(id);
|
||||
}
|
||||
|
||||
public void deleteIndicator(IndicatorForm indicatorForm) {
|
||||
indicatorService.deleteIndicator(indicatorForm);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package ru.ulstu.admin.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.admin.model.ManagerForm;
|
||||
import ru.ulstu.manager.model.Manager;
|
||||
import ru.ulstu.manager.service.ManagerService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AdminManagerService {
|
||||
private final ManagerService managerService;
|
||||
|
||||
public AdminManagerService(ManagerService managerService) {
|
||||
this.managerService = managerService;
|
||||
}
|
||||
|
||||
public List<Manager> getManagers() {
|
||||
return managerService.getManagers();
|
||||
}
|
||||
|
||||
public Manager getManagerById(Integer id) {
|
||||
return managerService.getManagerById(id);
|
||||
}
|
||||
|
||||
public void saveManager(ManagerForm managerForm) {
|
||||
Manager manager = managerForm.getId() == null
|
||||
? new Manager(managerForm)
|
||||
: managerService.getManagerById(managerForm.getId());
|
||||
manager.setName(managerForm.getName());
|
||||
managerService.save(manager);
|
||||
}
|
||||
|
||||
public void deleteManager(ManagerForm managerForm) {
|
||||
managerService.deleteManager(managerForm);
|
||||
}
|
||||
}
|
17
src/main/java/ru/ulstu/admin/service/AdminReportService.java
Normal file
17
src/main/java/ru/ulstu/admin/service/AdminReportService.java
Normal file
@ -0,0 +1,17 @@
|
||||
package ru.ulstu.admin.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.admin.model.ReportForm;
|
||||
|
||||
@Service
|
||||
public class AdminReportService {
|
||||
|
||||
// Здесь можно добавить дополнительную логику для работы с отчетами
|
||||
public void saveReport(ReportForm reportForm) {
|
||||
// Логика сохранения отчета
|
||||
System.out.println("Аспирант ID: " + reportForm.getAspirantId());
|
||||
System.out.println("Курсовая работа: " + reportForm.getCourseWorkScore());
|
||||
System.out.println("Научные исследования: " + reportForm.getResearchScore());
|
||||
System.out.println("Публикации: " + reportForm.getPublicationsScore());
|
||||
}
|
||||
}
|
135
src/main/java/ru/ulstu/aspirant/model/Aspirant.java
Normal file
135
src/main/java/ru/ulstu/aspirant/model/Aspirant.java
Normal file
@ -0,0 +1,135 @@
|
||||
package ru.ulstu.aspirant.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import ru.ulstu.indicator.model.Course;
|
||||
import ru.ulstu.manager.model.Manager;
|
||||
import ru.ulstu.model.BaseEntity;
|
||||
import ru.ulstu.model.User;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
public class Aspirant extends BaseEntity {
|
||||
@NotEmpty
|
||||
private String surname;
|
||||
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
private String patronymic;
|
||||
|
||||
@NotNull
|
||||
private Course course;
|
||||
|
||||
@ManyToOne
|
||||
private Manager manager;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date birthDate;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Speciality speciality;
|
||||
|
||||
private String theme;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Base base;
|
||||
|
||||
@ManyToOne
|
||||
private User user;
|
||||
|
||||
public Aspirant() {
|
||||
}
|
||||
|
||||
public Aspirant(String name, Course course) {
|
||||
this.name = name;
|
||||
this.course = course;
|
||||
}
|
||||
|
||||
public String getSurname() {
|
||||
return surname;
|
||||
}
|
||||
|
||||
public void setSurname(String surname) {
|
||||
this.surname = surname;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPatronymic() {
|
||||
return patronymic;
|
||||
}
|
||||
|
||||
public void setPatronymic(String patronymic) {
|
||||
this.patronymic = patronymic;
|
||||
}
|
||||
|
||||
public Course getCourse() {
|
||||
return course;
|
||||
}
|
||||
|
||||
public void setCourse(Course course) {
|
||||
this.course = course;
|
||||
}
|
||||
|
||||
public Manager getManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
public void setManager(Manager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public Date getBirthDate() {
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(Date birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public Speciality getSpeciality() {
|
||||
return speciality;
|
||||
}
|
||||
|
||||
public void setSpeciality(Speciality speciality) {
|
||||
this.speciality = speciality;
|
||||
}
|
||||
|
||||
public String getTheme() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
public void setTheme(String theme) {
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
public Base getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public void setBase(Base base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
15
src/main/java/ru/ulstu/aspirant/model/Base.java
Normal file
15
src/main/java/ru/ulstu/aspirant/model/Base.java
Normal file
@ -0,0 +1,15 @@
|
||||
package ru.ulstu.aspirant.model;
|
||||
|
||||
public enum Base {
|
||||
BUDGET("бюджет"), COMMERCE("коммерческая");
|
||||
|
||||
private final String name;
|
||||
|
||||
Base(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
22
src/main/java/ru/ulstu/aspirant/model/Speciality.java
Normal file
22
src/main/java/ru/ulstu/aspirant/model/Speciality.java
Normal file
@ -0,0 +1,22 @@
|
||||
package ru.ulstu.aspirant.model;
|
||||
|
||||
public enum Speciality {
|
||||
S_2_3_7("2.3.7", "Системный анализ"),
|
||||
S_2_3_1("2.3.1", "Автоматизация проектирования");
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
Speciality(String code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
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, Integer> {
|
||||
Aspirant findByUser(User user);
|
||||
}
|
58
src/main/java/ru/ulstu/aspirant/service/AspirantService.java
Normal file
58
src/main/java/ru/ulstu/aspirant/service/AspirantService.java
Normal file
@ -0,0 +1,58 @@
|
||||
package ru.ulstu.aspirant.service;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
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.Indicator;
|
||||
import ru.ulstu.indicator.service.IndicatorService;
|
||||
import ru.ulstu.model.User;
|
||||
import ru.ulstu.user.UserService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AspirantService {
|
||||
private final AspirantRepository aspirantRepository;
|
||||
private final IndicatorService indicatorService;
|
||||
private final UserService userService;
|
||||
|
||||
public AspirantService(AspirantRepository aspirantRepository,
|
||||
IndicatorService indicatorService,
|
||||
UserService userService) {
|
||||
this.aspirantRepository = aspirantRepository;
|
||||
this.indicatorService = indicatorService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
public List<Aspirant> getAspirants() {
|
||||
return aspirantRepository.findAll();
|
||||
}
|
||||
|
||||
public Aspirant getAspirantById(Integer id) {
|
||||
return aspirantRepository.findById(id).orElseThrow(() -> new RuntimeException("Aspirant not found by id"));
|
||||
}
|
||||
|
||||
public void save(Aspirant aspirant) {
|
||||
aspirantRepository.save(aspirant);
|
||||
}
|
||||
|
||||
public void deleteAspirant(AspirantForm aspirantForm) {
|
||||
aspirantRepository.deleteById(aspirantForm.getId());
|
||||
}
|
||||
|
||||
public Aspirant getAspirantByUser(User user) {
|
||||
return aspirantRepository.findByUser(user);
|
||||
}
|
||||
|
||||
public List<Indicator> getCurrentAspirantIndicators() {
|
||||
Aspirant aspirant = getAspirantByUser(userService.getCurrentUser());
|
||||
return indicatorService.getIndicatorsByCourse(aspirant.getCourse());
|
||||
}
|
||||
|
||||
public Page<Indicator> getIndicatorsByCourse(Pageable pageable) {
|
||||
return indicatorService.getIndicatorsByCourse(pageable);
|
||||
}
|
||||
}
|
@ -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")
|
||||
|
@ -9,7 +9,7 @@ package ru.ulstu.controller;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import ru.ulstu.news.NewsService;
|
||||
import ru.ulstu.news.service.NewsService;
|
||||
|
||||
@Controller
|
||||
public class IndexController {
|
||||
|
54
src/main/java/ru/ulstu/file/controller/FileController.java
Normal file
54
src/main/java/ru/ulstu/file/controller/FileController.java
Normal file
@ -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<byte[]> getFile(@PathVariable("tmp-file-name") String tmpFileName) throws IOException {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("Content-Disposition", "attachment; filename='"
|
||||
+ URLEncoder.encode(fileService.getTmpFileName(tmpFileName), UTF_8.toString()) + "'");
|
||||
return new ResponseEntity<>(fileService.getTmpFile(tmpFileName), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/download/{file-id}")
|
||||
public ResponseEntity<byte[]> getFile(@PathVariable("file-id") Integer fileId) throws UnsupportedEncodingException {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
FileData fileData = fileService.getFile(fileId);
|
||||
headers.add("Content-Disposition", "attachment; filename='" +
|
||||
URLEncoder.encode(fileData.getName(), UTF_8.toString()) + "'");
|
||||
return new ResponseEntity<>(fileData.getData(), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/uploadTmpFile")
|
||||
public Response<FileDataDto> upload(@RequestParam("file") MultipartFile multipartFile) throws IOException {
|
||||
return new Response<>(fileService.createFromMultipartFile(multipartFile));
|
||||
}
|
||||
}
|
64
src/main/java/ru/ulstu/file/model/FileData.java
Normal file
64
src/main/java/ru/ulstu/file/model/FileData.java
Normal file
@ -0,0 +1,64 @@
|
||||
package ru.ulstu.file.model;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
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;
|
||||
|
||||
private byte[] data;
|
||||
|
||||
@Column(name = "is_latex_attach")
|
||||
private Boolean isLatexAttach;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public Boolean isLatexAttach() {
|
||||
return isLatexAttach;
|
||||
}
|
||||
|
||||
public void setLatexAttach(Boolean latexAttach) {
|
||||
isLatexAttach = latexAttach;
|
||||
}
|
||||
}
|
76
src/main/java/ru/ulstu/file/model/FileDataDto.java
Normal file
76
src/main/java/ru/ulstu/file/model/FileDataDto.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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<FileData, Integer> {
|
||||
}
|
122
src/main/java/ru/ulstu/file/service/FileService.java
Normal file
122
src/main/java/ru/ulstu/file/service/FileService.java
Normal file
@ -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<FileData> saveOrCreate(List<FileDataDto> fileDtos) throws IOException {
|
||||
List<FileData> files = new ArrayList<>();
|
||||
for (FileDataDto file : fileDtos) {
|
||||
files.add(file.getId() != null ? update(file) : create(file));
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private FileData update(FileDataDto fileDataDto) {
|
||||
FileData file = 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));
|
||||
}
|
||||
}
|
@ -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<Path> loadAll() {
|
||||
try {
|
||||
return Files.walk(this.rootLocation, 1)
|
||||
.filter(path -> !path.equals(this.rootLocation))
|
||||
.map(path -> this.rootLocation.relativize(path));
|
||||
} catch (IOException e) {
|
||||
throw new StorageException("Failed to read stored files", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path load(String filename) {
|
||||
return rootLocation.resolve(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource loadAsResource(String filename) {
|
||||
try {
|
||||
Path file = load(filename);
|
||||
Resource resource = new UrlResource(file.toUri());
|
||||
if (resource.exists() || resource.isReadable()) {
|
||||
return resource;
|
||||
} else {
|
||||
throw new StorageFileNotFoundException("Could not read file: " + filename);
|
||||
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new StorageFileNotFoundException("Could not read file: " + filename, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
FileSystemUtils.deleteRecursively(rootLocation.toFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
Files.createDirectory(rootLocation);
|
||||
} catch (IOException e) {
|
||||
throw new StorageException("Could not initialize storage", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<Resource> serveFile(@PathVariable String filename) {
|
||||
Resource file = storageService.loadAsResource((filename == null || filename.equals("null") || filename.isEmpty())
|
||||
? "logo.png"
|
||||
: filename);
|
||||
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"filename=\"" + file.getFilename() + "\"").body(file);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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<Path> loadAll();
|
||||
|
||||
Path load(String filename);
|
||||
|
||||
Resource loadAsResource(String filename);
|
||||
|
||||
void deleteAll();
|
||||
|
||||
}
|
18
src/main/java/ru/ulstu/indicator/model/Course.java
Normal file
18
src/main/java/ru/ulstu/indicator/model/Course.java
Normal file
@ -0,0 +1,18 @@
|
||||
package ru.ulstu.indicator.model;
|
||||
|
||||
public enum Course {
|
||||
FIRST("первый"),
|
||||
SECOND("второй"),
|
||||
THIRD("третий"),
|
||||
FOURTH("четвертый");
|
||||
|
||||
private final String name;
|
||||
|
||||
Course(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
70
src/main/java/ru/ulstu/indicator/model/Indicator.java
Normal file
70
src/main/java/ru/ulstu/indicator/model/Indicator.java
Normal file
@ -0,0 +1,70 @@
|
||||
package ru.ulstu.indicator.model;
|
||||
|
||||
import jakarta.persistence.CollectionTable;
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import ru.ulstu.model.BaseEntity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class Indicator extends BaseEntity {
|
||||
|
||||
@NotBlank
|
||||
private String name;
|
||||
|
||||
@Min(0)
|
||||
@Max(30)
|
||||
private int max;
|
||||
|
||||
@NotBlank
|
||||
@Lob
|
||||
private String proofDocuments;
|
||||
|
||||
@ElementCollection(targetClass = Course.class)
|
||||
@CollectionTable
|
||||
@Enumerated(EnumType.STRING)
|
||||
private List<Course> courses = new ArrayList<>();
|
||||
|
||||
public Indicator() {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public void setMax(int max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public String getProofDocuments() {
|
||||
return proofDocuments;
|
||||
}
|
||||
|
||||
public void setProofDocuments(String proofDocuments) {
|
||||
this.proofDocuments = proofDocuments;
|
||||
}
|
||||
|
||||
public List<Course> getCourses() {
|
||||
return courses;
|
||||
}
|
||||
|
||||
public void setCourses(List<Course> courses) {
|
||||
this.courses = courses;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package ru.ulstu.indicator.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.indicator.model.Course;
|
||||
import ru.ulstu.indicator.model.Indicator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IndicatorRepository extends JpaRepository<Indicator, Integer> {
|
||||
Indicator findByName(String name);
|
||||
|
||||
@Query("select i from Indicator i WHERE :course member of i.courses")
|
||||
List<Indicator> findAllByCourse(@Param("course") Course course);
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package ru.ulstu.indicator.service;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.admin.model.IndicatorForm;
|
||||
import ru.ulstu.indicator.model.Course;
|
||||
import ru.ulstu.indicator.model.Indicator;
|
||||
import ru.ulstu.indicator.repository.IndicatorRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class IndicatorService {
|
||||
private final IndicatorRepository indicatorRepository;
|
||||
|
||||
public IndicatorService(IndicatorRepository indicatorRepository) {
|
||||
this.indicatorRepository = indicatorRepository;
|
||||
}
|
||||
|
||||
public List<Indicator> getIndicatorList() {
|
||||
return indicatorRepository.findAll();
|
||||
}
|
||||
|
||||
public void save(Indicator indicator) {
|
||||
indicatorRepository.save(indicator);
|
||||
}
|
||||
|
||||
public Indicator findByName(String name) {
|
||||
return indicatorRepository.findByName(name);
|
||||
}
|
||||
|
||||
public Indicator getIndicatorById(Integer id) {
|
||||
return indicatorRepository.findById(id).orElseThrow(() -> new RuntimeException("Indicator not found"));
|
||||
}
|
||||
|
||||
public void deleteIndicator(IndicatorForm indicatorForm) {
|
||||
indicatorRepository.deleteById(indicatorForm.getId());
|
||||
}
|
||||
|
||||
public List<Indicator> getIndicatorsByCourse(Course course) {
|
||||
return indicatorRepository.findAllByCourse(course);
|
||||
}
|
||||
|
||||
public Page<Indicator> getIndicatorsByCourse(Pageable pageable) {
|
||||
return indicatorRepository.findAll(pageable);
|
||||
}
|
||||
}
|
25
src/main/java/ru/ulstu/manager/model/Manager.java
Normal file
25
src/main/java/ru/ulstu/manager/model/Manager.java
Normal file
@ -0,0 +1,25 @@
|
||||
package ru.ulstu.manager.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import ru.ulstu.admin.model.ManagerForm;
|
||||
import ru.ulstu.model.BaseEntity;
|
||||
|
||||
@Entity
|
||||
public class Manager extends BaseEntity {
|
||||
private String name;
|
||||
|
||||
public Manager() {
|
||||
}
|
||||
|
||||
public Manager(ManagerForm managerForm) {
|
||||
this.name = managerForm.getName();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package ru.ulstu.manager.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import ru.ulstu.manager.model.Manager;
|
||||
|
||||
public interface ManagerRepository extends JpaRepository<Manager, Integer> {
|
||||
}
|
33
src/main/java/ru/ulstu/manager/service/ManagerService.java
Normal file
33
src/main/java/ru/ulstu/manager/service/ManagerService.java
Normal file
@ -0,0 +1,33 @@
|
||||
package ru.ulstu.manager.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.admin.model.ManagerForm;
|
||||
import ru.ulstu.manager.model.Manager;
|
||||
import ru.ulstu.manager.repository.ManagerRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ManagerService {
|
||||
private final ManagerRepository managerRepository;
|
||||
|
||||
public ManagerService(ManagerRepository managerRepository) {
|
||||
this.managerRepository = managerRepository;
|
||||
}
|
||||
|
||||
public List<Manager> getManagers() {
|
||||
return managerRepository.findAll();
|
||||
}
|
||||
|
||||
public Manager getManagerById(Integer id) {
|
||||
return managerRepository.findById(id).orElseThrow(() -> new RuntimeException("Manager not found by id"));
|
||||
}
|
||||
|
||||
public void save(Manager manager) {
|
||||
managerRepository.save(manager);
|
||||
}
|
||||
|
||||
public void deleteManager(ManagerForm managerForm) {
|
||||
managerRepository.deleteById(managerForm.getId());
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import jakarta.persistence.Transient;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import ru.ulstu.model.BaseEntity;
|
||||
import ru.ulstu.news.News;
|
||||
import ru.ulstu.news.model.News;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
@ -5,8 +5,8 @@ import jakarta.validation.constraints.NotNull;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.news.News;
|
||||
import ru.ulstu.news.NewsService;
|
||||
import ru.ulstu.news.model.News;
|
||||
import ru.ulstu.news.service.NewsService;
|
||||
|
||||
@Service
|
||||
public class MeetingService {
|
||||
|
39
src/main/java/ru/ulstu/model/ErrorConstants.java
Normal file
39
src/main/java/ru/ulstu/model/ErrorConstants.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -2,5 +2,7 @@ package ru.ulstu.model;
|
||||
|
||||
public class UserRoleConstants {
|
||||
public static final String ADMIN = "ROLE_ADMIN";
|
||||
public static final String USER = "ROLE_USER";
|
||||
public static final String ASPIRANT = "ROLE_ASPIRANT";
|
||||
public static final String MANAGER = "ROLE_MANAGER";
|
||||
public static final String HEAD = "ROLE_HEAD";
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
package ru.ulstu.model.response;
|
||||
|
||||
class ControllerResponse<D, E> {
|
||||
private final D data;
|
||||
private final ControllerResponseError<E> error;
|
||||
|
||||
ControllerResponse(D data) {
|
||||
this.data = data;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
ControllerResponse(ControllerResponseError<E> error) {
|
||||
this.data = null;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public D getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public ControllerResponseError<E> getError() {
|
||||
return error;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package ru.ulstu.model.response;
|
||||
|
||||
|
||||
import ru.ulstu.model.ErrorConstants;
|
||||
|
||||
class ControllerResponseError<D> {
|
||||
private final ErrorConstants description;
|
||||
private final D data;
|
||||
|
||||
ControllerResponseError(ErrorConstants description, D data) {
|
||||
this.description = description;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return description.getCode();
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return description.getMessage();
|
||||
}
|
||||
|
||||
public D getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
21
src/main/java/ru/ulstu/model/response/PageableItems.java
Normal file
21
src/main/java/ru/ulstu/model/response/PageableItems.java
Normal file
@ -0,0 +1,21 @@
|
||||
package ru.ulstu.model.response;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class PageableItems<T> {
|
||||
private final long count;
|
||||
private final Collection<T> items;
|
||||
|
||||
public PageableItems(long count, Collection<T> items) {
|
||||
this.count = count;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public Collection<T> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
17
src/main/java/ru/ulstu/model/response/Response.java
Normal file
17
src/main/java/ru/ulstu/model/response/Response.java
Normal file
@ -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<D> extends ResponseEntity<Object> {
|
||||
|
||||
public Response(D data) {
|
||||
super(new ControllerResponse<D, Void>(data), HttpStatus.OK);
|
||||
}
|
||||
|
||||
public Response(ErrorConstants error) {
|
||||
super(new ControllerResponse<Void, Void>(new ControllerResponseError<>(error, null)), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
13
src/main/java/ru/ulstu/model/response/ResponseExtended.java
Normal file
13
src/main/java/ru/ulstu/model/response/ResponseExtended.java
Normal file
@ -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<E> extends ResponseEntity<Object> {
|
||||
|
||||
public ResponseExtended(ErrorConstants error, E errorData) {
|
||||
super(new ControllerResponse<Void, E>(new ControllerResponseError<E>(error, errorData)), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package ru.ulstu.news;
|
||||
package ru.ulstu.news.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -20,6 +20,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import ru.ulstu.model.OffsetablePageRequest;
|
||||
import ru.ulstu.model.UserRoleConstants;
|
||||
import ru.ulstu.news.model.News;
|
||||
import ru.ulstu.news.service.NewsService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
@ -1,4 +1,4 @@
|
||||
package ru.ulstu.news;
|
||||
package ru.ulstu.news.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Lob;
|
@ -1,8 +1,9 @@
|
||||
package ru.ulstu.news;
|
||||
package ru.ulstu.news.repository;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import ru.ulstu.news.model.News;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ru.ulstu.news;
|
||||
package ru.ulstu.news.service;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@ -6,6 +6,8 @@ import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.meeting.Meeting;
|
||||
import ru.ulstu.news.model.News;
|
||||
import ru.ulstu.news.repository.NewsRepository;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
@ -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<ReportPeriod> periods = reportPeriodService.getReportPeriods();
|
||||
model.addAttribute("reportPeriods", periods);
|
||||
model.addAttribute("reportListForm", new ReportListForm(periods.isEmpty() ? null : periods.getFirst()));
|
||||
model.addAttribute("reports", reportService.getReports(periods.isEmpty() ? null : periods.getFirst()));
|
||||
model.addAttribute("canCreate", !periods.isEmpty() && reportService.canCreateReport(periods.getFirst()));
|
||||
return "report/reportList";
|
||||
}
|
||||
|
||||
@PostMapping("reportList")
|
||||
public String getReportPeriods(ReportListForm reportListForm, Model model) {
|
||||
model.addAttribute("reportListForm", reportListForm);
|
||||
model.addAttribute("reports", reportService.getReports(reportListForm.getReportPeriod()));
|
||||
List<ReportPeriod> periods = reportPeriodService.getReportPeriods();
|
||||
model.addAttribute("reportPeriods", periods);
|
||||
model.addAttribute("canCreate", !periods.isEmpty() && reportService.canCreateReport(reportListForm.getReportPeriod()));
|
||||
return "report/reportList";
|
||||
}
|
||||
|
||||
@GetMapping("new-report/{reportPeriodId}")
|
||||
public String createReport(@PathVariable("reportPeriodId") Integer reportPeriodId,
|
||||
Model model) {
|
||||
List<Indicator> indicators = aspirantService.getCurrentAspirantIndicators();
|
||||
model.addAttribute("report", new ReportDto(reportPeriodId, indicators));
|
||||
return "report/editReport";
|
||||
}
|
||||
|
||||
@GetMapping("edit-report/{reportId}")
|
||||
public String editReportWithoutReportPeriod(@PathVariable("reportId") Integer reportId, Model model) {
|
||||
List<Indicator> indicators = aspirantService.getCurrentAspirantIndicators();
|
||||
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";
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
80
src/main/java/ru/ulstu/report/model/Report.java
Normal file
80
src/main/java/ru/ulstu/report/model/Report.java
Normal file
@ -0,0 +1,80 @@
|
||||
package ru.ulstu.report.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
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
|
||||
private List<ReportValue> values = new ArrayList<>();
|
||||
|
||||
@ManyToOne
|
||||
private ReportPeriod reportPeriod;
|
||||
|
||||
@ManyToOne
|
||||
private Aspirant aspirant;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private ReportStatus status;
|
||||
|
||||
public Report() {
|
||||
}
|
||||
|
||||
public Report(Integer id) {
|
||||
setId(id);
|
||||
}
|
||||
|
||||
public List<ReportValue> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(List<ReportValue> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public Date getCreateDate() {
|
||||
return createDate;
|
||||
}
|
||||
|
||||
public void setCreateDate(Date createDate) {
|
||||
this.createDate = createDate;
|
||||
}
|
||||
|
||||
public ReportPeriod getReportPeriod() {
|
||||
return reportPeriod;
|
||||
}
|
||||
|
||||
public void setReportPeriod(ReportPeriod reportPeriod) {
|
||||
this.reportPeriod = reportPeriod;
|
||||
}
|
||||
|
||||
public Aspirant getAspirant() {
|
||||
return aspirant;
|
||||
}
|
||||
|
||||
public void setAspirant(Aspirant aspirant) {
|
||||
this.aspirant = aspirant;
|
||||
}
|
||||
|
||||
public ReportStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(ReportStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
20
src/main/java/ru/ulstu/report/model/ReportListForm.java
Normal file
20
src/main/java/ru/ulstu/report/model/ReportListForm.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
36
src/main/java/ru/ulstu/report/model/ReportPeriod.java
Normal file
36
src/main/java/ru/ulstu/report/model/ReportPeriod.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
18
src/main/java/ru/ulstu/report/model/ReportStatus.java
Normal file
18
src/main/java/ru/ulstu/report/model/ReportStatus.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
51
src/main/java/ru/ulstu/report/model/ReportValue.java
Normal file
51
src/main/java/ru/ulstu/report/model/ReportValue.java
Normal file
@ -0,0 +1,51 @@
|
||||
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<FileData> files = new ArrayList<>();
|
||||
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;
|
||||
}
|
||||
|
||||
public List<FileData> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
public void setFiles(List<FileData> files) {
|
||||
this.files = files;
|
||||
}
|
||||
}
|
76
src/main/java/ru/ulstu/report/model/dto/ReportDto.java
Normal file
76
src/main/java/ru/ulstu/report/model/dto/ReportDto.java
Normal file
@ -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<ReportValueDto> reportValues = new ArrayList<>();
|
||||
private ReportStatus status;
|
||||
|
||||
public ReportDto() {
|
||||
}
|
||||
|
||||
public ReportDto(Integer reportPeriodId, List<Indicator> indicators) {
|
||||
this.reportPeriodId = reportPeriodId;
|
||||
this.reportValues = indicators.stream().map(ReportValueDto::new).toList();
|
||||
this.status = ReportStatus.NEW;
|
||||
}
|
||||
|
||||
public ReportDto(Report report, List<Indicator> indicators) {
|
||||
this.id = report.getId();
|
||||
this.reportPeriodId = report.getReportPeriod().getId();
|
||||
this.createDate = report.getCreateDate();
|
||||
this.reportValues = indicators.stream().map(ReportValueDto::new).toList();
|
||||
this.status = report.getStatus();
|
||||
}
|
||||
|
||||
public List<ReportValueDto> getReportValues() {
|
||||
return reportValues;
|
||||
}
|
||||
|
||||
public void setReportValues(List<ReportValueDto> reportValues) {
|
||||
this.reportValues = reportValues;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getReportPeriodId() {
|
||||
return reportPeriodId;
|
||||
}
|
||||
|
||||
public void setReportPeriodId(Integer reportPeriodId) {
|
||||
this.reportPeriodId = reportPeriodId;
|
||||
}
|
||||
|
||||
public Date getCreateDate() {
|
||||
return createDate;
|
||||
}
|
||||
|
||||
public void setCreateDate(Date createDate) {
|
||||
this.createDate = createDate;
|
||||
}
|
||||
|
||||
public ReportStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(ReportStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
44
src/main/java/ru/ulstu/report/model/dto/ReportValueDto.java
Normal file
44
src/main/java/ru/ulstu/report/model/dto/ReportValueDto.java
Normal file
@ -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<FileDataDto> 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<FileDataDto> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
public void setFiles(List<FileDataDto> files) {
|
||||
this.files = files;
|
||||
}
|
||||
}
|
@ -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<ReportPeriod, Integer> {
|
||||
List<ReportPeriod> findAllByOrderByStartDateDesc();
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
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.report.model.Report;
|
||||
import ru.ulstu.report.model.ReportPeriod;
|
||||
import ru.ulstu.statistic.model.RatingItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ReportRepository extends JpaRepository<Report, Integer> {
|
||||
|
||||
List<Report> findAllByReportPeriod(ReportPeriod reportPeriod);
|
||||
|
||||
Report findByReportPeriodAndAspirant(ReportPeriod reportPeriod, Aspirant aspirant);
|
||||
|
||||
@Query("SELECT new ru.ulstu.statistic.model.RatingItem(r.aspirant, (SELECT cast(sum(rv.indicatorValue) AS Integer) FROM ReportValue rv WHERE rv MEMBER OF r.values)) FROM Report r JOIN r.reportPeriod rp WHERE rp.id = :reportPeriodId")
|
||||
List<RatingItem> getRating(@Param("reportPeriodId") Integer reportPeriodId);
|
||||
}
|
@ -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<ReportPeriod> getReportPeriods() {
|
||||
return reportPeriodRepository.findAllByOrderByStartDateDesc();
|
||||
}
|
||||
|
||||
public ReportPeriod save(ReportPeriod reportPeriod) {
|
||||
ReportPeriod dbReportPeriod;
|
||||
if (reportPeriod.getId() != null) {
|
||||
dbReportPeriod = getById(reportPeriod.getId());
|
||||
dbReportPeriod.setStartDate(reportPeriod.getStartDate());
|
||||
dbReportPeriod.setEndDate(reportPeriod.getEndDate());
|
||||
} else {
|
||||
dbReportPeriod = reportPeriod;
|
||||
}
|
||||
return reportPeriodRepository.save(dbReportPeriod);
|
||||
}
|
||||
|
||||
public void delete(ReportPeriod reportPeriod) {
|
||||
reportPeriodRepository.deleteById(reportPeriod.getId());
|
||||
}
|
||||
|
||||
public ReportPeriod getById(Integer reportPeriodId) {
|
||||
return reportPeriodRepository
|
||||
.findById(reportPeriodId)
|
||||
.orElseThrow(() -> new RuntimeException("Report period not found by id"));
|
||||
}
|
||||
}
|
64
src/main/java/ru/ulstu/report/service/ReportService.java
Normal file
64
src/main/java/ru/ulstu/report/service/ReportService.java
Normal file
@ -0,0 +1,64 @@
|
||||
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.report.model.Report;
|
||||
import ru.ulstu.report.model.ReportPeriod;
|
||||
import ru.ulstu.report.model.dto.ReportDto;
|
||||
import ru.ulstu.report.repository.ReportRepository;
|
||||
import ru.ulstu.user.UserService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ReportService {
|
||||
private final ReportRepository reportRepository;
|
||||
private final UserService userService;
|
||||
private final AspirantService aspirantService;
|
||||
private final ReportPeriodService reportPeriodService;
|
||||
|
||||
public ReportService(ReportRepository reportRepository,
|
||||
UserService userService,
|
||||
AspirantService aspirantService, ReportPeriodService reportPeriodService) {
|
||||
this.reportRepository = reportRepository;
|
||||
this.userService = userService;
|
||||
this.aspirantService = aspirantService;
|
||||
this.reportPeriodService = reportPeriodService;
|
||||
}
|
||||
|
||||
public List<Report> getReports(ReportPeriod reportPeriod) {
|
||||
return reportRepository.findAllByReportPeriod(reportPeriod);
|
||||
}
|
||||
|
||||
public boolean canCreateReport(ReportPeriod reportPeriod) {
|
||||
Aspirant currentAspirant = aspirantService.getAspirantByUser(userService.getCurrentUser());
|
||||
return 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);
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
32
src/main/java/ru/ulstu/statistic/model/RatingItem.java
Normal file
32
src/main/java/ru/ulstu/statistic/model/RatingItem.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
15
src/main/java/ru/ulstu/statistic/model/StatisticForm.java
Normal file
15
src/main/java/ru/ulstu/statistic/model/StatisticForm.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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<RatingItem> getRating(Integer reportPeriodId) {
|
||||
return reportRepository.getRating(reportPeriodId);
|
||||
}
|
||||
}
|
@ -57,18 +57,50 @@ public class UserService implements UserDetailsService {
|
||||
if (getUserByLogin(user.getLogin()) != null) {
|
||||
throw new RuntimeException(user.getLogin());
|
||||
}
|
||||
User dbUser = (user.getId() == null)
|
||||
? user
|
||||
: getUserById(user.getId());
|
||||
//user.setRoles(Collections.singleton(new UserRole(UserRoleConstants.USER)));
|
||||
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||
user = userRepository.save(user);
|
||||
log.debug("Created Information for User: {}", user.getLogin());
|
||||
return user;
|
||||
dbUser.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||
dbUser.setLogin(user.getLogin());
|
||||
dbUser = userRepository.save(dbUser);
|
||||
log.debug("Created Information for User: {}", dbUser.getLogin());
|
||||
return dbUser;
|
||||
}
|
||||
|
||||
public User getUserById(Integer id) {
|
||||
return userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found by id"));
|
||||
}
|
||||
|
||||
private User createDefaultUser(String login, String userRole) {
|
||||
if (getUserByLogin(login) == null) {
|
||||
UserRole role = userRoleRepository.save(new UserRole(userRole.toString()));
|
||||
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() {
|
||||
String adminLogin = "admin";
|
||||
if (getUserByLogin(adminLogin) == null) {
|
||||
UserRole adminRole = userRoleRepository.save(new UserRole(UserRoleConstants.ADMIN));
|
||||
createUser(new User(adminLogin, adminPassword, Set.of(adminRole)));
|
||||
}
|
||||
createDefaultUser("admin", UserRoleConstants.ADMIN);
|
||||
}
|
||||
|
||||
public void initDefaultAspirant() {
|
||||
createDefaultUser("aspirant", UserRoleConstants.ASPIRANT);
|
||||
}
|
||||
|
||||
public void initDefaultManager() {
|
||||
createDefaultUser("manager", UserRoleConstants.MANAGER);
|
||||
}
|
||||
|
||||
public void initDefaultHead() {
|
||||
createDefaultUser("head", UserRoleConstants.HEAD);
|
||||
}
|
||||
|
||||
public User getCurrentUser() {
|
||||
return getUserByLogin(UserUtils.getCurrentUserLogin());
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,6 @@
|
||||
# You may use, distribute and modify this code, please write to: romanov73@gmail.com.
|
||||
#
|
||||
#
|
||||
messages.app-name=Cеминар «Анализ данных и процессов». УлГТУ
|
||||
messages.logo-title=Cеминар «Анализ данных и процессов»
|
||||
messages.app-name=БРС аспиранта УлГТУ
|
||||
messages.logo-title=БРС аспиранта УлГТУ
|
||||
messages.menu.home=На главную
|
BIN
src/main/resources/public/docs/polozh.pdf
Normal file
BIN
src/main/resources/public/docs/polozh.pdf
Normal file
Binary file not shown.
24
src/main/resources/public/js/bootstrap.file-input.js
vendored
Normal file
24
src/main/resources/public/js/bootstrap.file-input.js
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
(function($) {
|
||||
$.fn.bootstrapFileInput = function(loadDirectory = false) {
|
||||
var fileInput = $('<input type="file" class="input-ghost" ' + (loadDirectory ? 'webkitdirectory' : '') +' style="visibility:hidden; height:0">');
|
||||
fileInput.change(function() {
|
||||
$('#file-input-list').html('');
|
||||
const files = $(this).prop('files');
|
||||
if (files.length == 0) {
|
||||
return;
|
||||
}
|
||||
var filesList = '';
|
||||
$.each(files, function(index, file){
|
||||
filesList += '<div style="overflow: hidden"><span id="file-' + index + '"><i class="fa fa-circle-o"></i> ' + file.name + '</span></div>';
|
||||
});
|
||||
$('#file-input-list').html(filesList);
|
||||
});
|
||||
$(this).find('button.btn-choose').click(function() {
|
||||
fileInput.click();
|
||||
});
|
||||
$(this).find('input').mousedown(function() {
|
||||
return false;
|
||||
});
|
||||
$(this).append(fileInput);
|
||||
};
|
||||
})(jQuery);
|
236
src/main/resources/public/js/core.js
Normal file
236
src/main/resources/public/js/core.js
Normal file
@ -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 = $(
|
||||
"<li class=\"alert alert-" + type + "\">" +
|
||||
"<span>" + message + "</span>" +
|
||||
"</li>"
|
||||
);
|
||||
li.click(function () {
|
||||
$(this).remove();
|
||||
});
|
||||
messageDiv.append(li);
|
||||
};
|
||||
|
||||
var liveTimeMs = 15000;
|
||||
var messageDiv = $("#messages");
|
||||
if (isEmpty(message)) {
|
||||
messageDiv.html("");
|
||||
return;
|
||||
}
|
||||
drawMessage(message, (isEmpty(type) || isEmpty(MessageTypesEnum[type.toUpperCase()]) ?
|
||||
MessageTypesEnum.INFO : type));
|
||||
setTimeout(function () {
|
||||
messageDiv.find("li").first().remove();
|
||||
}, liveTimeMs);
|
||||
}
|
||||
|
||||
/* exported errorHandler */
|
||||
function errorHandler(response, callBack, errorCallBack) {
|
||||
if (isEmpty(response)) {
|
||||
showFeedbackMessage("Empty response", MessageTypesEnum.DANGER);
|
||||
return;
|
||||
}
|
||||
if (!isEmpty(response.error)) {
|
||||
// TODO: add l10n
|
||||
// showFeedbackMessage(response.error.code + ": " + response.error.message, MessageTypesEnum.DANGER);
|
||||
if (!isEmpty(errorCallBack)) {
|
||||
errorCallBack(response.data);
|
||||
}
|
||||
throw response.error.code + ": " + response.error.message +
|
||||
" / Details: " + response.error.data;
|
||||
}
|
||||
if (!isEmpty(callBack)) {
|
||||
if (isLoginPageResponse(response)) {
|
||||
window.location.href = "/";
|
||||
} else {
|
||||
callBack(response.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isLoginPageResponse(response) {
|
||||
return (typeof response) === 'string' && response.indexOf("<!DOCTYPE html>") >= 0;
|
||||
}
|
||||
|
||||
/* exported getFromRest */
|
||||
function getFromRest(url, callBack, errorCallBack) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
cache: false,
|
||||
success: function (response) {
|
||||
errorHandler(response, callBack, errorCallBack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* exported getFromRestWithVersionAndParams */
|
||||
function getFromRestWithParams(url, params, callBack, errorCallBack) {
|
||||
$.ajax({
|
||||
url: url + "?" + params,
|
||||
cache: false,
|
||||
success: function (response) {
|
||||
errorHandler(response, callBack, errorCallBack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* exported postToRest */
|
||||
function postToRest(url, postData, callBack, completeCallback, errorCallBack) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
cache: false,
|
||||
dataType: "json",
|
||||
data: postData,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
processData: false,
|
||||
method: "POST",
|
||||
success: function (response) {
|
||||
errorHandler(response, callBack, errorCallBack);
|
||||
},
|
||||
complete: function () {
|
||||
if (isEmpty(completeCallback)) {
|
||||
return;
|
||||
}
|
||||
completeCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* exported postToRestWithVersion */
|
||||
function postToRestWithVersion(url, postData, callBack, errorCallBack) {
|
||||
postToRestWithVersionAndParams(url, postData, "", callBack, errorCallBack);
|
||||
}
|
||||
|
||||
/* exported postToRestWithVersionAndParams */
|
||||
function postToRestWithVersionAndParams(url, postData, params, callBack, errorCallBack) {
|
||||
getCurrentVersion(function (version) {
|
||||
$.ajax({
|
||||
url: url + "?versionId=" + version + params,
|
||||
cache: false,
|
||||
dataType: "json",
|
||||
data: postData,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
processData: false,
|
||||
method: "POST",
|
||||
success: function (response) {
|
||||
errorHandler(response, callBack, errorCallBack);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* exported putToRestWithVersion */
|
||||
function putToRestWithVersion(url, putData, callBack, errorCallBack) {
|
||||
putToRestWithVersionAndParams(url, putData, "", callBack, errorCallBack);
|
||||
}
|
||||
|
||||
/* exported putToRestWithVersionAndParams */
|
||||
function putToRestWithVersionAndParams(url, putData, params, callBack, errorCallBack) {
|
||||
getCurrentVersion(function (version) {
|
||||
$.ajax({
|
||||
url: url + "?versionId=" + version + params,
|
||||
cache: false,
|
||||
dataType: "json",
|
||||
data: putData,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
processData: false,
|
||||
method: "PUT",
|
||||
success: function (response) {
|
||||
errorHandler(response, callBack, errorCallBack);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* exported deleteFromRest */
|
||||
function deleteFromRest(url, callBack, completeCallback, errorCallBack) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
cache: false,
|
||||
method: "DELETE",
|
||||
success: function (response) {
|
||||
errorHandler(response, callBack, errorCallBack);
|
||||
},
|
||||
complete: function () {
|
||||
if (isEmpty(completeCallback)) {
|
||||
return;
|
||||
}
|
||||
completeCallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* exported fillSelect */
|
||||
function fillSelect(selectElement, values) {
|
||||
$(selectElement).html("");
|
||||
$.each(values, function (key, value) {
|
||||
$(selectElement).append(
|
||||
"<option value=\"" + value.id + "\">" + value.name + "</option>"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/* exported isUrlVarExists */
|
||||
function isUrlVarExists(key) {
|
||||
var URL = window.location.href;
|
||||
if (URL.indexOf("?" + key + "=") !== -1) {
|
||||
return true;
|
||||
} else if (URL.indexOf("&" + key + "=") !== -1) {
|
||||
return true;
|
||||
} else if (URL.indexOf("?" + key + "&") !== -1) {
|
||||
return true;
|
||||
} else if (URL.indexOf("&" + key + "&") !== -1) {
|
||||
return true;
|
||||
} else if (URL.endsWith("?" + key)) {
|
||||
return true;
|
||||
} else if (URL.endsWith("&" + key)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* exported getUrlVar */
|
||||
function getUrlVar(key) {
|
||||
var result = new RegExp(key + "=([^&]*)", "i").exec(window.location.search);
|
||||
return result && decodeURIComponent(result[1]) || "";
|
||||
}
|
||||
|
||||
function sendPing(field, url) {
|
||||
id = document.getElementById(field).value
|
||||
|
||||
$.ajax({
|
||||
url: url + `?${field}=` + id,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
method: "POST",
|
||||
success: function () {
|
||||
showFeedbackMessage("Ping был отправлен", MessageTypesEnum.SUCCESS)
|
||||
},
|
||||
error: function (errorData) {
|
||||
showFeedbackMessage(errorData.responseJSON.error.message, MessageTypesEnum.WARNING)
|
||||
}
|
||||
})
|
||||
}
|
134
src/main/resources/public/js/file-loader.js
Normal file
134
src/main/resources/public/js/file-loader.js
Normal file
@ -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 = $("<input>")
|
||||
.attr("type", "text")
|
||||
.attr("placeholder", CHOOSE_FILE_TEXT)
|
||||
.attr("disabled", true)
|
||||
.addClass("form-control");
|
||||
div.append(fileLabel);
|
||||
var fileInput = $("<input>")
|
||||
.attr("type", "file")
|
||||
.attr("multiple", '')
|
||||
.hide();
|
||||
fileInput.change(function () {
|
||||
var files = $(this).prop("files");
|
||||
if (isEmpty(files)) {
|
||||
return;
|
||||
}
|
||||
fileLabel.val(files[0].name);
|
||||
});
|
||||
div.append(fileInput);
|
||||
|
||||
var buttonGroup = $("<div>")
|
||||
.addClass("input-group-btn");
|
||||
div.append(buttonGroup);
|
||||
|
||||
var chooseButton = $("<button>")
|
||||
.attr("type", "button")
|
||||
.addClass("btn btn-default")
|
||||
.append($("<i>").addClass("fa fa-ellipsis-h"));
|
||||
chooseButton.click(function () {
|
||||
fileInput.click();
|
||||
});
|
||||
buttonGroup.append(chooseButton);
|
||||
|
||||
var uploadButton = $("<button>")
|
||||
.attr("type", "button")
|
||||
.addClass("btn btn-default")
|
||||
.append($("<i>").addClass("fa fa-upload"));
|
||||
uploadButton.click(function () {
|
||||
var files = fileInput.prop("files");
|
||||
if (isEmpty(files)) {
|
||||
showFeedbackMessage(ALERT_CHOOSE_FILE, MessageTypesEnum.DANGER);
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var currentFile = files[i];
|
||||
if (!isEmpty(fileExtensions) && fileExtensions.indexOf(getFileExt(currentFile)) === -1) {
|
||||
showFeedbackMessage(ALERT_UNKNOWN_FILE_EXT, MessageTypesEnum.DANGER);
|
||||
return;
|
||||
}
|
||||
if (currentFile.size === 0) {
|
||||
showFeedbackMessage(ALERT_EMPTY_FILE, MessageTypesEnum.DANGER);
|
||||
return;
|
||||
}
|
||||
if (MAX_FILE_SIZE_MB != -1 && currentFile.size / SIZE_TO_MB > MAX_FILE_SIZE_MB) {
|
||||
showFeedbackMessage(ALERT_MAX_FILE + " " + MAX_FILE_SIZE_MB + "Mb", MessageTypesEnum.DANGER);
|
||||
return;
|
||||
}
|
||||
upload(currentFile);
|
||||
}
|
||||
});
|
||||
buttonGroup.append(uploadButton);
|
||||
|
||||
var progressDiv = $("<div>")
|
||||
.addClass("progress margined-top-10")
|
||||
.css("background-color", "#FFFFFF");
|
||||
progressDiv.insertAfter(div);
|
||||
var progressBar = $("<div>")
|
||||
.addClass("progress-bar")
|
||||
.attr("role", "progressbar")
|
||||
.css("width", "0%");
|
||||
progressDiv.append(progressBar);
|
||||
|
||||
function getFileExt(file) {
|
||||
return file.name.slice((Math.max(0, file.name.lastIndexOf(".")) || Infinity) + 1);
|
||||
}
|
||||
|
||||
function upload(file) {
|
||||
progressBar.css("width", "0%");
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.upload.onprogress = function (event) {
|
||||
var curProgress = Math.floor(event.loaded / event.total * 100) + "%";
|
||||
progressBar
|
||||
.css("width", curProgress)
|
||||
.text(curProgress);
|
||||
};
|
||||
xhr.onload = xhr.onerror = function () {
|
||||
if (this.status === 200) {
|
||||
errorHandler(JSON.parse(this.responseText), callback);
|
||||
} else {
|
||||
showFeedbackMessage(ERROR, MessageTypesEnum.DANGER);
|
||||
console.error("error " + this.status);
|
||||
}
|
||||
};
|
||||
xhr.open("POST", url, true);
|
||||
var formData = new FormData();
|
||||
formData.append("file", file);
|
||||
xhr.send(formData);
|
||||
}
|
||||
}
|
49
src/main/resources/templates/admin/aspirantReport.html
Normal file
49
src/main/resources/templates/admin/aspirantReport.html
Normal file
@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<h3>Отчетность аспиранта</h3>
|
||||
|
||||
<!-- Форма для отправки данных -->
|
||||
<form action="#" th:action="@{/admin/saveReport}" th:object="${report}" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" th:field="*{aspirantId}">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="courseWork">Курсовая работа (баллы)</label>
|
||||
<input th:field="*{courseWorkScore}" id="courseWork" type="number" required class="form-control"
|
||||
placeholder="Введите баллы">
|
||||
<p th:if="${#fields.hasErrors('courseWorkScore')}"
|
||||
th:class="${#fields.hasErrors('courseWorkScore')}? error">
|
||||
Поле обязательно для заполнения
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="research">Научные исследования (баллы)</label>
|
||||
<input th:field="*{researchScore}" id="research" type="number" required class="form-control"
|
||||
placeholder="Введите баллы">
|
||||
<p th:if="${#fields.hasErrors('researchScore')}" th:class="${#fields.hasErrors('researchScore')}? error">
|
||||
Поле обязательно для заполнения
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="publications">Публикации (баллы)</label>
|
||||
<input th:field="*{publicationsScore}" id="publications" type="number" required class="form-control"
|
||||
placeholder="Введите баллы">
|
||||
<p th:if="${#fields.hasErrors('publicationsScore')}"
|
||||
th:class="${#fields.hasErrors('publicationsScore')}? error">
|
||||
Поле обязательно для заполнения
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="fileUpload">Прикрепить файл</label>
|
||||
<input id="fileUpload" type="file" name="file" multiple class="form-control-file">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-outline-dark">Отправить отчет</button>
|
||||
<a href="/admin/reports" class="btn btn-outline-dark">Отмена</a>
|
||||
</form>
|
||||
</div>
|
||||
</html>
|
42
src/main/resources/templates/admin/aspirantsList.html
Normal file
42
src/main/resources/templates/admin/aspirantsList.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<a href="/admin/editAspirant/0" class="btn btn-outline-dark">
|
||||
<i class="fa fa-plus-square" aria-hidden="true"> Добавить аспиранта</i>
|
||||
</a>
|
||||
|
||||
<!-- Таблица аспирантов -->
|
||||
<table class="table table-bordered table-striped mt-3">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th scope="col">Фамилия</th>
|
||||
<th scope="col">Имя</th>
|
||||
<th scope="col">Отчество</th>
|
||||
<th scope="col">Курс</th>
|
||||
<th scope="col">Тема диссертации</th>
|
||||
<th scope="col">Научный руководитель</th>
|
||||
<th scope="col">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="a : ${aspirants}">
|
||||
<td th:text="${a.surname}"></td>
|
||||
<td th:text="${a.name}"></td>
|
||||
<td th:text="${a.patronymic}"></td>
|
||||
<td th:if="${a.course != null}" th:text="${a.course.name}"></td>
|
||||
<td th:if="${a.course == null}"></td>
|
||||
<td th:text="${a.theme}"></td>
|
||||
<td th:if="${a.manager != null}" th:text="${a.manager.name}"></td>
|
||||
<td th:if="${a.manager == null}"></td>
|
||||
<td>
|
||||
<!-- Ссылка на редактирование -->
|
||||
<a th:href="@{'/admin/editAspirant/' + ${a.id}}" class="btn btn-sm btn-primary">
|
||||
<i class="fa fa-edit" aria-hidden="true"></i> Редактировать
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</html>
|
112
src/main/resources/templates/admin/editAspirant.html
Normal file
112
src/main/resources/templates/admin/editAspirant.html
Normal file
@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<h3>Редактирование аспиранта:</h3>
|
||||
<form action="#" th:action="@{/admin/saveAspirant}"
|
||||
th:object="${aspirant}"
|
||||
method="post">
|
||||
<input type="hidden" th:field="*{id}">
|
||||
<input type="hidden" th:field="*{userId}">
|
||||
<div class="form-group">
|
||||
<label for="surname">Фамилия</label>
|
||||
<input th:field="*{surname}"
|
||||
id="surname"
|
||||
type="text"
|
||||
required
|
||||
class="form-control"
|
||||
placeholder="Фамилия">
|
||||
<p th:if="${#fields.hasErrors('surname')}"
|
||||
th:class="${#fields.hasErrors('surname')}? error">
|
||||
Не может быть пустым
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Имя</label>
|
||||
<input th:field="*{name}"
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
class="form-control"
|
||||
placeholder="Имя">
|
||||
<p th:if="${#fields.hasErrors('name')}"
|
||||
th:class="${#fields.hasErrors('name')}? error">
|
||||
Не может быть пустым
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="patronymic">Отчество</label>
|
||||
<input th:field="*{patronymic}"
|
||||
id="patronymic"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Отчество">
|
||||
<p th:if="${#fields.hasErrors('patronymic')}"
|
||||
th:class="${#fields.hasErrors('patronymic')}? error">
|
||||
Не может быть пустым
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input th:field="*{email}"
|
||||
id="email"
|
||||
required
|
||||
type="email"
|
||||
class="form-control"
|
||||
placeholder="Email">
|
||||
<p th:if="${#fields.hasErrors('email')}"
|
||||
th:class="${#fields.hasErrors('email')}? error">
|
||||
Не может быть пустым
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="course">Курс</label>
|
||||
<select class="form-select form-control"
|
||||
id="course" aria-label="multiple select example"
|
||||
th:field="*{course}">
|
||||
<option th:each="c : ${courses}"
|
||||
th:value="${c}"
|
||||
th:text="${c.name}">
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="theme">Тема</label>
|
||||
<input th:field="*{theme}"
|
||||
id="theme"
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Тема">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="manager">Научный руководитель</label>
|
||||
<select class="form-select form-control"
|
||||
id="manager" aria-label="select example"
|
||||
th:field="*{managerId}">
|
||||
<option th:each="m : ${managers}"
|
||||
th:value="${m.id}"
|
||||
th:text="${m.name}">
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
|
||||
<button name="delete"
|
||||
type="submit"
|
||||
class="btn btn-outline-dark"
|
||||
onclick="return confirm('Удалить запись?')">
|
||||
Удалить
|
||||
</button>
|
||||
<a href="/admin/aspirants" class="btn btn-outline-dark">Отмена</a>
|
||||
</form>
|
||||
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
|
||||
</div>
|
||||
</html>
|
76
src/main/resources/templates/admin/editIndicator.html
Normal file
76
src/main/resources/templates/admin/editIndicator.html
Normal file
@ -0,0 +1,76 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<h3>Редактирование показателя:</h3>
|
||||
<form action="#" th:action="@{/admin/saveIndicator}"
|
||||
th:object="${indicator}"
|
||||
method="post"
|
||||
enctype="multipart/form-data">
|
||||
<input type="hidden" th:field="*{id}">
|
||||
<div class="form-group">
|
||||
<label for="name">Название</label>
|
||||
<input th:field="*{name}"
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
class="form-control"
|
||||
placeholder="Название показателя">
|
||||
<p th:if="${#fields.hasErrors('name')}"
|
||||
th:class="${#fields.hasErrors('name')}? error">
|
||||
Не может быть пустым
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Максимальная сумма баллов</label>
|
||||
<input th:field="*{max}"
|
||||
required
|
||||
id="max"
|
||||
type="number"
|
||||
class="form-control"
|
||||
min="0"
|
||||
max="30">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Описание подтверждающих документов</label>
|
||||
<textarea th:field="*{proofDocuments}"
|
||||
required
|
||||
id="proofDocuments"
|
||||
class="form-control"
|
||||
placeholder="Описание подтверждающих документов"
|
||||
style="height: 100px">
|
||||
</textarea>
|
||||
<p th:if="${#fields.hasErrors('proofDocuments')}"
|
||||
th:class="${#fields.hasErrors('proofDocuments')}? error">
|
||||
Не может быть пустым
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="courses">Для каких курсов применяется</label>
|
||||
|
||||
<select class="form-select form-control" id="courses" multiple aria-label="multiple select example"
|
||||
th:field="*{courses}"
|
||||
>
|
||||
<option th:each="c : ${courses}"
|
||||
th:value="${c}"
|
||||
th:text="${c.name}">
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
|
||||
<button name="delete"
|
||||
type="submit"
|
||||
class="btn btn-outline-dark"
|
||||
onclick="return confirm('Удалить показатель?')">
|
||||
Удалить
|
||||
</button>
|
||||
<a href="/admin/indicators" class="btn btn-outline-dark">Отмена</a>
|
||||
</form>
|
||||
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
|
||||
</div>
|
||||
</html>
|
37
src/main/resources/templates/admin/editManager.html
Normal file
37
src/main/resources/templates/admin/editManager.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<h3>Редактирование научного руководителя:</h3>
|
||||
<form action="#" th:action="@{/admin/saveManager}"
|
||||
th:object="${manager}"
|
||||
method="post">
|
||||
<input type="hidden" th:field="*{id}">
|
||||
<div class="form-group">
|
||||
<label for="name">ФИО</label>
|
||||
<input th:field="*{name}"
|
||||
id="name"
|
||||
type="text"
|
||||
required
|
||||
class="form-control"
|
||||
placeholder="ФИО">
|
||||
<p th:if="${#fields.hasErrors('name')}"
|
||||
th:class="${#fields.hasErrors('name')}? error">
|
||||
Не может быть пустым
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
|
||||
<button name="delete"
|
||||
type="submit"
|
||||
class="btn btn-outline-dark"
|
||||
onclick="return confirm('Удалить запись?')">
|
||||
Удалить
|
||||
</button>
|
||||
<a href="/admin/aspirants" class="btn btn-outline-dark">Отмена</a>
|
||||
</form>
|
||||
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
|
||||
</div>
|
||||
</html>
|
49
src/main/resources/templates/admin/editReportPeriod.html
Normal file
49
src/main/resources/templates/admin/editReportPeriod.html
Normal file
@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<h3>Редактирование отчетного периода:</h3>
|
||||
<form action="#" th:action="@{/admin/saveReportPeriod}"
|
||||
th:object="${reportPeriod}"
|
||||
method="post">
|
||||
<input type="hidden" th:field="*{id}">
|
||||
<div class="form-group">
|
||||
<label for="startDate">Дата начала</label>
|
||||
<input th:field="*{startDate}"
|
||||
id="startDate"
|
||||
type="date"
|
||||
required
|
||||
class="form-control">
|
||||
<p th:if="${#fields.hasErrors('startDate')}"
|
||||
th:class="${#fields.hasErrors('startDate')}? error">
|
||||
Ошибка
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="endDate">Дата окончания</label>
|
||||
<input th:field="*{endDate}"
|
||||
id="endDate"
|
||||
type="date"
|
||||
required
|
||||
class="form-control">
|
||||
<p th:if="${#fields.hasErrors('endDate')}"
|
||||
th:class="${#fields.hasErrors('endDate')}? error">
|
||||
Ошибка
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button name="save" type="submit" class="btn btn-outline-dark">Сохранить</button>
|
||||
<button name="delete"
|
||||
type="submit"
|
||||
class="btn btn-outline-dark"
|
||||
onclick="return confirm('Удалить запись?')">
|
||||
Удалить
|
||||
</button>
|
||||
<a href="/admin/reportPeriodList" class="btn btn-outline-dark">Отмена</a>
|
||||
</form>
|
||||
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap-glyphicons/bdd2cbfba0/css/bootstrap-glyphicons.css"/>
|
||||
</div>
|
||||
</html>
|
15
src/main/resources/templates/admin/indicatorsList.html
Normal file
15
src/main/resources/templates/admin/indicatorsList.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<a href="/admin/editIndicator/0" class="btn btn-outline-dark">
|
||||
<i class="fa fa-plus-square" aria-hidden="true"> Добавить показатель</i>
|
||||
</a>
|
||||
|
||||
<ul>
|
||||
<li th:each="i : ${indicators}">
|
||||
<a th:href="@{'/admin/editIndicator/' + ${i.id}}"><span th:text="${i.name}"></span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</html>
|
43
src/main/resources/templates/admin/managersList.html
Normal file
43
src/main/resources/templates/admin/managersList.html
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<!-- Кнопка добавления нового научного руководителя -->
|
||||
<a href="/admin/editManager/0" class="btn btn-outline-dark mb-3">
|
||||
<i class="fa fa-plus-square" aria-hidden="true"> Добавить научного руководителя</i>
|
||||
</a>
|
||||
|
||||
<!-- Таблица научных руководителей -->
|
||||
<table class="table table-bordered table-striped mt-3">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th scope="col">ФИО</th>
|
||||
<th scope="col">Должность</th>
|
||||
<th scope="col">Степень</th>
|
||||
<th scope="col">Звание</th>
|
||||
<th scope="col">Научные интересы</th>
|
||||
<th scope="col">Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="m : ${managers}">
|
||||
<td th:text="${m.name}"></td>
|
||||
<td th:text="${m.position}"></td>
|
||||
<td th:text="${m.degree}"></td>
|
||||
<td th:text="${m.title}"></td>
|
||||
<td>
|
||||
<ul>
|
||||
<li th:each="interest : ${m.interests}" th:text="${interest}"></li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<!-- Ссылка на редактирование -->
|
||||
<a th:href="@{'/admin/editManager/' + ${m.id}}" class="btn btn-sm btn-primary">
|
||||
<i class="fa fa-edit" aria-hidden="true"></i> Редактировать
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</html>
|
32
src/main/resources/templates/admin/reportPeriodList.html
Normal file
32
src/main/resources/templates/admin/reportPeriodList.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
|
||||
layout:decorate="~{default}">
|
||||
<div class="container" layout:fragment="content">
|
||||
<a href="/admin/editReportPeriod/0" class="btn btn-outline-dark">
|
||||
<i class="fa fa-plus-square" aria-hidden="true"> Добавить отчетный период</i>
|
||||
</a>
|
||||
|
||||
<!-- Таблица периодов отчетности -->
|
||||
<table class="table table-bordered table-striped mt-3">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th scope="col">Дата начала</th>
|
||||
<th scope="col">Дата окончания</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="r : ${reportPeriods}">
|
||||
<td th:text="${#calendars.format(r.startDate, 'dd.MM.yyyy')}"></td>
|
||||
<td th:text="${#calendars.format(r.endDate, 'dd.MM.yyyy')}"></td>
|
||||
<td>
|
||||
<!-- Ссылка на редактирование -->
|
||||
<a th:href="@{'/admin/editReportPeriod/' + ${r.id}}" class="btn btn-sm btn-primary">
|
||||
<i class="fa fa-edit" aria-hidden="true"></i> Редактировать
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</html>
|
33
src/main/resources/templates/aspirant/adminBRS.html
Normal file
33
src/main/resources/templates/aspirant/adminBRS.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Правила расчета БРС</title>
|
||||
<link th:href="@{/webjars/bootstrap/5.3.0-alpha1/css/bootstrap.min.css}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Правила расчета БРС</h2>
|
||||
<form action="#" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="courseWorkWeight" class="form-label">Вес курсовой работы (%)</label>
|
||||
<input type="number" class="form-control" id="courseWorkWeight" name="courseWorkWeight"
|
||||
th:value="${courseWorkWeight}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="researchWeight" class="form-label">Вес научных исследований (%)</label>
|
||||
<input type="number" class="form-control" id="researchWeight" name="researchWeight"
|
||||
th:value="${researchWeight}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="publicationsWeight" class="form-label">Вес публикаций (%)</label>
|
||||
<input type="number" class="form-control" id="publicationsWeight" name="publicationsWeight"
|
||||
th:value="${publicationsWeight}">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Сохранить правила</button>
|
||||
</form>
|
||||
</div>
|
||||
<script th:src="@{/webjars/bootstrap/5.3.0-alpha1/js/bootstrap.bundle.min.js}"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Подтверждение отчета</title>
|
||||
<link th:href="@{/webjars/bootstrap/5.3.0-alpha1/css/bootstrap.min.css}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Подтверждение отчета аспиранта</h2>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header" th:text="'Отчет аспиранта: ' + ${aspirantName}">Отчет аспиранта: Иванов Иван Иванович
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Курсовая работа:</strong> <span th:text="${courseWorkScore}">80</span> баллов</p>
|
||||
<p><strong>Научные исследования:</strong> <span th:text="${researchScore}">70</span> баллов</p>
|
||||
<p><strong>Публикации:</strong> <span th:text="${publicationsScore}">60</span> баллов</p>
|
||||
<button type="button" class="btn btn-success">Подтвердить</button>
|
||||
<button type="button" class="btn btn-danger">Отклонить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script th:src="@{/webjars/bootstrap/5.3.0-alpha1/js/bootstrap.bundle.min.js}"></script>
|
||||
</body>
|
||||
</html>
|
40
src/main/resources/templates/aspirant/aspirantList.html
Normal file
40
src/main/resources/templates/aspirant/aspirantList.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Список аспирантов</title>
|
||||
<link th:href="@{/webjars/bootstrap/5.3.0-alpha1/css/bootstrap.min.css}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Список аспирантов</h2>
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th scope="col">ФИО</th>
|
||||
<th scope="col">Курс</th>
|
||||
<th scope="col">Форма обучения</th>
|
||||
<th scope="col">Основа</th>
|
||||
<th scope="col">Тема диссертации</th>
|
||||
<th scope="col">Руководитель</th>
|
||||
<th scope="col">Активное обучение</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="aspirant : ${aspirants}">
|
||||
<td th:text="${aspirant.fio}">Иванов Иван Иванович</td>
|
||||
<td th:text="${aspirant.course}">1</td>
|
||||
<td th:text="${aspirant.formOfEducation}">Очная</td>
|
||||
<td th:text="${aspirant.basis}">Бюджет</td>
|
||||
<td th:text="${aspirant.dissertationTopic}">Методы машинного обучения</td>
|
||||
<td th:text="${aspirant.supervisor}">Петров Петр Петрович</td>
|
||||
<td th:if="${aspirant.isActive}" th:text="'Да'">Да</td>
|
||||
<td th:unless="${aspirant.isActive}" th:text="'Нет'">Нет</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<script th:src="@{/webjars/bootstrap/5.3.0-alpha1/js/bootstrap.bundle.min.js}"></script>
|
||||
</body>
|
||||
</html>
|
34
src/main/resources/templates/aspirant/aspirantReport.html
Normal file
34
src/main/resources/templates/aspirant/aspirantReport.html
Normal file
@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Отчетность аспиранта</title>
|
||||
<link th:href="@{/webjars/bootstrap/5.3.0-alpha1/css/bootstrap.min.css}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Отчетность аспиранта</h2>
|
||||
<form action="#" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="courseWork" class="form-label">Курсовая работа (баллы)</label>
|
||||
<input type="number" class="form-control" id="courseWork" name="courseWork" placeholder="Введите баллы">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="research" class="form-label">Научные исследования (баллы)</label>
|
||||
<input type="number" class="form-control" id="research" name="research" placeholder="Введите баллы">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="publications" class="form-label">Публикации (баллы)</label>
|
||||
<input type="number" class="form-control" id="publications" name="publications" placeholder="Введите баллы">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="fileUpload" class="form-label">Прикрепить файл</label>
|
||||
<input class="form-control" type="file" id="fileUpload" name="fileUpload">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Отправить отчет</button>
|
||||
</form>
|
||||
</div>
|
||||
<script th:src="@{/webjars/bootstrap/5.3.0-alpha1/js/bootstrap.bundle.min.js}"></script>
|
||||
</body>
|
||||
</html>
|
25
src/main/resources/templates/aspirant/aspirantRukovod.html
Normal file
25
src/main/resources/templates/aspirant/aspirantRukovod.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Список руководителей</title>
|
||||
<link th:href="@{/webjars/bootstrap/5.3.0-alpha1/css/bootstrap.min.css}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Список руководителей</h2>
|
||||
<div th:each="supervisor : ${supervisors}" class="card mb-3">
|
||||
<div class="card-header" th:text="${supervisor.fio}">Петров Петр Петрович</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Должность:</strong> <span th:text="${supervisor.position}">Доцент</span></p>
|
||||
<p><strong>Степень:</strong> <span th:text="${supervisor.degree}">Кандидат технических наук</span></p>
|
||||
<p><strong>Звание:</strong> <span th:text="${supervisor.title}">Доцент</span></p>
|
||||
<p><strong>Научные интересы:</strong> <span th:each="interest : ${supervisor.interests}"
|
||||
th:text="${interest} + ', '"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script th:src="@{/webjars/bootstrap/5.3.0-alpha1/js/bootstrap.bundle.min.js}"></script>
|
||||
</body>
|
||||
</html>
|
31
src/main/resources/templates/aspirant/semesterStat.html
Normal file
31
src/main/resources/templates/aspirant/semesterStat.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Статистика по семестрам</title>
|
||||
<link th:href="@{/webjars/bootstrap/5.3.0-alpha1/css/bootstrap.min.css}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h2 class="mb-4">Статистика по семестрам</h2>
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th scope="col">Семестр</th>
|
||||
<th scope="col">Аспирант</th>
|
||||
<th scope="col">Общий балл</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="stat : ${stats}">
|
||||
<td th:text="${stat.semester}">1</td>
|
||||
<td th:text="${stat.aspirantName}">Иванов Иван Иванович</td>
|
||||
<td th:text="${stat.totalScore}">210</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<script th:src="@{/webjars/bootstrap/5.3.0-alpha1/js/bootstrap.bundle.min.js}"></script>
|
||||
</body>
|
||||
</html>
|
@ -7,6 +7,7 @@
|
||||
<title th:text="#{messages.app-name}">app-name</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/js/core.js"></script>
|
||||
<script type="text/javascript" src="/webjars/bootstrap/4.3.0/js/bootstrap.bundle.min.js"></script>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap/4.3.0/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
|
||||
@ -29,26 +30,65 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/news/news">Новости</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/meetings/meetings">Заседания</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/organizers">Организаторы</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/docs">Документы</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/reports">Отчеты</a>
|
||||
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_ASPIRANT')">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">Аспиранту</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="/report/reportList">Список отчетов</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_MANAGER')">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">Руководителю</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="/aspirantList">Список аспирантов</a>
|
||||
<a class="dropdown-item" href="/report/reportList">Список отчетов</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_HEAD')">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">Аспирантура</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="/admin/reportPeriodList">Список периодов отчетности</a>
|
||||
<a class="dropdown-item" href="/report/reportList">Список отчетов</a>
|
||||
<a class="dropdown-item" href="/statistic/statistic">Статистика по баллам</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown" sec:authorize="hasRole('ROLE_ADMIN')">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">Администратору</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="/admin/indicators">Список показателей</a>
|
||||
<a class="dropdown-item" href="/admin/managers">Список научных руководителей</a>
|
||||
<a class="dropdown-item" href="/admin/aspirants">Список аспирантов</a>
|
||||
<a class="dropdown-item" href="/admin/reportPeriodList">Список периодов отчетности</a>
|
||||
<a class="dropdown-item" href="/admin/rules">Правила БРС</a>
|
||||
<a class="dropdown-item" href="/admin/confirmation">Подтверждение БРС</a>
|
||||
<a class="dropdown-item" href="/report/reportList">Список отчетов</a>
|
||||
<a class="dropdown-item" href="/statistic/statistic">Статистика по баллам</a>
|
||||
<a class="dropdown-item" href="/admin">Новости и заседания</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/admin">Администратору</a>
|
||||
<a class="nav-link disabled" href="#" sec:authorize="hasRole('ROLE_ADMIN')">Личный кабинет
|
||||
администратора</a>
|
||||
<a class="nav-link disabled" href="#" sec:authorize="hasRole('ROLE_ASPIRANT')">Личный кабинет
|
||||
аспиранта</a>
|
||||
<a class="nav-link disabled" href="#" sec:authorize="hasRole('ROLE_MANAGER')">Личный кабинет
|
||||
руководителя аспиранта</a>
|
||||
<a class="nav-link disabled" href="#" sec:authorize="hasRole('ROLE_HEAD')">Личный кабинет
|
||||
представителя аспирантуры</a>
|
||||
</li>
|
||||
<li>
|
||||
<div sec:authorize="isAuthenticated()">
|
||||
<a class="nav-link" href="/logout">Выход</a>
|
||||
</div>
|
||||
|
||||
<div sec:authorize="!isAuthenticated()">
|
||||
<a class="nav-link" href="/login">Личный кабинет</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -91,7 +131,7 @@
|
||||
|
||||
</div>
|
||||
<footer>
|
||||
2022
|
||||
2025
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -3,13 +3,8 @@
|
||||
<div class="container" layout:fragment="content">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<a class="link-dark" href="/docs/polozh.docx">
|
||||
Положение
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<a class="link-dark" href="/docs/plan2022.docx">
|
||||
План заседаний на 2022 год.
|
||||
<a class="link-dark" target="_blank" href="/docs/polozh.pdf">
|
||||
Положение о балльно-рейтинговой системе оценки успеваемости аспирантов
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -45,6 +45,5 @@
|
||||
th:text=${pageNumber}
|
||||
th:class="${pageNumber == news.number+1} ? active"></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</html>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user