Compare commits

..

No commits in common. "b489ac954761279bf03b21994b77a9402dc89fa9" and "02e24932d46e474e1b1994a59d8ac91465b303f2" have entirely different histories.

22 changed files with 217 additions and 484 deletions

Binary file not shown.

View File

@ -2,6 +2,5 @@ export default class Group{
constructor(data) { constructor(data) {
this.id = data?.id; this.id = data?.id;
this.name = data?.name; this.name = data?.name;
this.subjectIds = data?.subjectIds;
} }
} }

View File

@ -2,142 +2,34 @@
<div class="container mt-4"> <div class="container mt-4">
<h1 class="text-center mb-4">Group Table</h1> <h1 class="text-center mb-4">Group Table</h1>
<button class="btn btn-primary mr-2" @click="openModal('create')">Добавить</button> <button class="btn btn-primary mr-2" @click="openModal('create')">Добавить</button>
<button class="btn btn-primary mr-2" @click="openReport()">Отчет</button>
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th>Имя</th> <th>Имя</th>
<th>Действия</th> <th></th>
<th>Работа с группой</th>
<th>Работа с предметами</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="grp in groups" :key="grp.id"> <tr v-for="grp in groups" :key="grp.id">
<td>{{ grp.name }}</td> <td>{{ grp.name }}</td>
<td> <td>
<div class="d-flex flex-column"> <td>
<button class="btn btn-primary mb-2" @click="openModal('edit', grp)">Изменить</button> <button class="btn btn-primary mr-2" @click="openModal('edit', grp)">Изменить</button>
<button class="btn btn-danger mb-2" @click="deleteGroup(grp.id)">Удалить</button>
</div>
</td> </td>
<td> <td>
<div class="d-flex flex-column"> <button class="btn btn-danger" @click="deleteGroup(grp.id)">Удалить</button>
<button class="btn btn-primary mb-2" @click="OpenModelForStudents(); getStudentsFromGroup(grp.id)">Просмотр студентов</button>
<button class="btn btn-primary mb-2" @click="OpenModelForAddStudents(grp); getStudentsFromUndefinedGroup()">Добавление студентов в группу</button>
</div>
</td> </td>
<td> <td>
<div class="d-flex flex-column"> <button class="btn btn-primary mr-2" @click="OpenModelForStudents();getStudentsFromGroup(grp.id)">Просмотр студентов</button>
<button class="btn btn-primary mb-2" @click="OpenModelForSubjects(); getSubjectsInGroup(grp.id)">Просмотр предметов</button> </td>
<button class="btn btn-primary mb-2" @click="OpenModelForAddSubjects('edit', grp);">Добавление предметов в группу</button> <td>
</div> <button class="btn btn-primary mr-2" @click="OpenModelForSubjects();getSubjects(grp.id)">Просмотр предметов</button>
</td>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<!--Форма для отчета -->
<div class="modal" tabindex="-1" id="openReport">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Отчет</h5>
</div>
<div class="modal-body">
<form>
<table class="table table-striped">
<thead>
<tr>
<th>Группа</th>
<th>Студенты</th>
</tr>
</thead>
<tbody>
<tr v-for="[key, value] in Object.entries(getAllInfo)" :key="key">
<td>{{ key }}</td>
<td>
<ul>
<li v-for="book in value" :key="book">{{ book }}</li>
</ul>
</td>
</tr>
</tbody>
</table>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="editModal" @click="closeReport()">Закрыть</button>
</div>
</div>
</div>
</div>
<!--Форма для привязки предмета и групп -->
<div class="modal" tabindex="-1" id="openModalForAddSubjects">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Добавление предметов</h5>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="name">Имя:</label>
<input readonly type="text" class="form-control" id="name" name="name" v-model="group.name">
</div>
<div class="form-group">
<label for="name">Выберите предметы для добавления:</label>
<ul class="list-group">
<li class="list-group-item" v-for="subject in subjects" :key="subject.id">
<div class="form-check">
<input class="form-check-input" type="checkbox" v-model="selectedSubjects" :value="subject.id" v-bind:checked="open.includes(subject.id)" id="groupCheck{{ subject.id }}">
<label class="form-check-label" for="groupCheck{{ subject.id }}">{{ subject.name }}</label>
</div>
</li>
</ul>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="editModal" @click="closeModalForAddSubjects()">Закрыть</button>
<button type="button" class="btn btn-primary" @click="addSubjectToGroup(group.id, selectedSubjects)">Добавить</button>
</div>
</div>
</div>
</div>
<!-- Модальное окно для добавления студентов в группу-->
<div class="modal" tabindex="-1" id="ModalForAddStudents">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Добавление студентов в группу</h5>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="name">Имя:</label>
<input type="text" class="form-control" id="name" name="name" v-model="group.name">
</div>
<div class="form-group">
<label for="name">Выберите студентов для добавления:</label>
<ul class="list-group">
<li class="list-group-item" v-for="student in students" :key="student.id">
<div class="form-check">
<input class="form-check-input" type="checkbox" :id="'studentCheck' + student.id" :value="student.id" v-model="selectedStudents">
<label class="form-check-label" :for="'studentCheck' + student.id">{{ student.name }}</label>
</div>
</li>
</ul>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="editModal" @click="CloseModalForAddStudents()">Закрыть</button>
<button type="button" class="btn btn-primary" @click="saveStudents(group.id)">Сохранить</button>
</div>
</div>
</div>
</div>
<!-- Модальное окно для добавления и изменения--> <!-- Модальное окно для добавления и изменения-->
<div class="modal" tabindex="-1" id="editModal"> <div class="modal" tabindex="-1" id="editModal">
<div class="modal-dialog"> <div class="modal-dialog">
@ -176,18 +68,12 @@
<tr> <tr>
<th>Имя</th> <th>Имя</th>
<th>Дата рождения</th> <th>Дата рождения</th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="stud in students" :key="stud.id"> <tr v-for="stud in students" :key="stud.id">
<td>{{ stud.name }}</td> <td>{{ stud.name }}</td>
<td>{{ stud.birthDate }}</td> <td>{{ stud.birthDate }}</td>
<td>
<td>
<button class="btn btn-danger mr-2" @click="deleteStudentFromGroup(stud.id)">Удалить</button>
</td>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -217,7 +103,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="sbjct in subjectsInGroup" :key="sbjct.id"> <tr v-for="sbjct in subjects" :key="sbjct.id">
<td>{{ sbjct.name }}</td> <td>{{ sbjct.name }}</td>
</tr> </tr>
</tbody> </tbody>
@ -237,12 +123,9 @@ import 'axios';
import axios from "axios"; import axios from "axios";
import Group from "@/models/Group"; import Group from "@/models/Group";
import Student from "@/models/Student"; import Student from "@/models/Student";
import Subject from "@/models/Subject";
export default { export default {
created() { created() {
this.getGroups(); this.getGroups();
this.getSubjects();
this.getAll();
}, },
data() { data() {
return{ return{
@ -251,29 +134,13 @@ export default {
group: new Group(), group: new Group(),
students: [], students: [],
subjects: [], subjects: [],
selectedStudents: [],
open: [],
groupId: undefined,
selectedSubjects: [],
subjectsInGroup: [],
getAllInfo: new Object() ,
} }
}, },
methods: { methods: {
getAll(){ getSubjects(id){
axios.get(this.URL + "group/getAll")
.then(response => {
this.getAllInfo = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
getSubjectsInGroup(id){
axios.get(this.URL + `group/${id}/getAllSubjects`) axios.get(this.URL + `group/${id}/getAllSubjects`)
.then(response => { .then(response => {
this.subjectsInGroup = response.data; this.subjects = response.data;
console.log(response.data); console.log(response.data);
}) })
.catch(error => { .catch(error => {
@ -333,7 +200,6 @@ export default {
document.getElementById("editModal").style.display = "none"; document.getElementById("editModal").style.display = "none";
}, },
getStudentsFromGroup(groupId){ getStudentsFromGroup(groupId){
this.selectedStudents = [];
axios.get(this.URL + `group/${groupId}/students`) axios.get(this.URL + `group/${groupId}/students`)
.then(response => { .then(response => {
this.students = response.data; this.students = response.data;
@ -355,93 +221,6 @@ export default {
closeModelForSubjects() { closeModelForSubjects() {
document.getElementById("ModelForSubjects").style.display = "none"; document.getElementById("ModelForSubjects").style.display = "none";
}, },
OpenModelForAddStudents(group) {
this.group = { ...group };
document.getElementById("ModalForAddStudents").style.display = "block";
},
CloseModalForAddStudents() {
document.getElementById("ModalForAddStudents").style.display = "none";
},
openReport() {
document.getElementById("openReport").style.display = "block";
},
closeReport() {
document.getElementById("openReport").style.display = "none";
},
saveStudents(id) {
axios.post(this.URL + `group/${id}/addStudents`, this.selectedStudents)
.then(() => {
this.getStudentsFromGroup(id);
this.CloseModalForAddStudents();
console.log(this.students);
})
.catch(error => {
console.log(error);
});
},
getStudentsFromUndefinedGroup(){
axios.get(this.URL + `group/getStudentsUndefined`)
.then(response => {
this.students = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
deleteStudentFromGroup(id){
axios.delete(this.URL + `group/deleteStudentFromGroup/${id}`)
.then(() =>{
this.getStudentsFromGroup();
})
.catch(error => {
console.log(error);
});
},
OpenModelForAddSubjects(status, group = null) {
if (status === "create") {
this.group = new Group();
this.group.status = "create";
} else if (status === "edit" && group) {
this.group = { ...group };
this.group.status = "edit";
}
this.open = this.group.subjectIds ? [...this.group.subjectIds] : []; // Создаём новый массив, чтобы избежать проблем с ссылками
this.loadSelectedSubjects(); // Загрузка выбранных групп при открытии модального окна
document.getElementById("openModalForAddSubjects").style.display = "block";
},
closeModalForAddSubjects() {
document.getElementById("openModalForAddSubjects").style.display = "none";
this.open = [...this.selectedSubjects]; // Обновление массива open значениями из selectedGroups
this.selectedSubjects = []; // Сброс выбранных групп
this.group = new Group(); // Сброс текущего предмета при закрытии модального окна
},
loadSelectedSubjects() {
// Загрузка выбранных групп из массива open
this.selectedSubjects = [...this.open];
},
addSubjectToGroup(id, list) {
axios
.post(this.URL + `group/${id}/addSubjectToGroup`, list)
.then(() => {
this.closeModalForAddSubjects();
this.getGroups(); // Обновляем список предметов после успешного добавления
this.open = [...this.selectedSubjects]; // Обновляем массив выбранных групп
})
.catch((error) => {
console.log(error);
});
},
getSubjects(){
axios.get(this.URL + "subject")
.then(response => {
this.subjects = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
} }
} }
</script> </script>

View File

@ -15,7 +15,7 @@
<tr v-for="stud in students" :key="stud.id"> <tr v-for="stud in students" :key="stud.id">
<td>{{ stud.name }}</td> <td>{{ stud.name }}</td>
<td>{{ stud.birthDate }}</td> <td>{{ stud.birthDate }}</td>
<td>{{stud.groupName || 'No Group'}}</td> <td>{{ stud.groupName }}</td>
<td> <td>
<td> <td>
<button class="btn btn-primary mr-2" @click="openModal('edit', stud)">Изменить</button> <button class="btn btn-primary mr-2" @click="openModal('edit', stud)">Изменить</button>
@ -44,6 +44,14 @@
<label for="birthdate">Дата рождения:</label> <label for="birthdate">Дата рождения:</label>
<input type="date" class="form-control" id="birthdate" name="birthdate" v-model="editedStudent.birthDate"> <input type="date" class="form-control" id="birthdate" name="birthdate" v-model="editedStudent.birthDate">
</div> </div>
<div class="form-group">
<label for="group">Группа:</label>
<select v-model="editedStudent.groupId" class="form-control">
<option v-for="(group, index) in groups" :key="index" :value="group.id">
{{ group.name }}
</option>
</select>
</div>
</form> </form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -90,8 +98,8 @@ export default {
console.log(error); console.log(error);
}); });
}, },
getGroups() { getGroups(){
axios.get(this.URL + "student/groups") axios.get(this.URL + "group")
.then(response => { .then(response => {
this.groups = response.data; this.groups = response.data;
console.log(response.data); console.log(response.data);
@ -101,8 +109,6 @@ export default {
}); });
}, },
addStudent(student) { addStudent(student) {
console.log(student);
student.group = null;
console.log(student); console.log(student);
axios axios
.post(this.URL + "student", student) .post(this.URL + "student", student)

View File

@ -19,6 +19,9 @@
<td> <td>
<button class="btn btn-danger" @click="deleteSubject(sbjct.id)">Удалить</button> <button class="btn btn-danger" @click="deleteSubject(sbjct.id)">Удалить</button>
</td> </td>
<td>
<button class="btn btn-primary mr-2" @click="openModalForAdd('edit', sbjct);">Добавить предметы в группы</button>
</td>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -47,6 +50,39 @@
</div> </div>
</div> </div>
</div> </div>
<!--Форма для привязки предмета и групп -->
<div class="modal" tabindex="-1" id="openModalForAdd">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Добавление групп</h5>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="name">Имя:</label>
<input readonly type="text" class="form-control" id="name" name="name" v-model="subject.name">
</div>
<div class="form-group">
<label for="name">Выберите группы для добавления:</label>
<ul class="list-group">
<li class="list-group-item" v-for="group in groups" :key="group.id">
<div class="form-check">
<input class="form-check-input" type="checkbox" v-model="selectedGroups" :value="group.id" v-bind:checked="open.includes(group.id)" id="groupCheck{{ group.id }}">
<label class="form-check-label" for="groupCheck{{ group.id }}">{{ group.name }}</label>
</div>
</li>
</ul>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="editModal" @click="closeModalForAdd()">Закрыть</button>
<button type="button" class="btn btn-primary" @click="addSubjectToGroup(subject.id, selectedGroups)">Добавить</button>
</div>
</div>
</div>
</div>
</template> </template>
<script> <script>
import 'axios'; import 'axios';
@ -56,15 +92,40 @@ import Group from "@/models/Group";
export default { export default {
created() { created() {
this.getSubjects(); this.getSubjects();
this.getGroups();
this.getAllSubjectGroup();
}, },
mounted() {
const addModal = document.getElementById('editModal');
addModal.addEventListener('shown.bs.modal', function () {
})
const openModalForAdd = document.getElementById('openModalForAdd');
openModalForAdd.addEventListener('shown.bs.modal', function () {
})
},
data() { data() {
return{ return{
subjects: [], subjects: [],
URL: "http://localhost:8080/", URL: "http://localhost:8080/",
subject: new Subject(), subject: new Subject(),
groups: [],
selectedGroups: [],
AllSubjectGroup: [],
open: [],
} }
}, },
methods: { methods: {
getAllSubjectGroup(){
axios.get(this.URL + "subject/getAllSubjectGroup")
.then(response => {
this.AllSubjectGroup = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
getSubjects(){ getSubjects(){
axios.get(this.URL + "subject") axios.get(this.URL + "subject")
.then(response => { .then(response => {
@ -103,6 +164,27 @@ export default {
}) })
this.closeModal(); this.closeModal();
}, },
openModalForAdd(status, subject = null) {
if (status === "create") {
this.subject = new Subject();
this.subject.status = "create";
} else if (status === "edit" && subject) {
this.subject = { ...subject };
this.subject.status = "edit";
}
this.open = this.subject.groupIds ? [...this.subject.groupIds] : []; // Создаём новый массив, чтобы избежать проблем с ссылками
this.loadSelectedGroups(); // Загрузка выбранных групп при открытии модального окна
document.getElementById("openModalForAdd").style.display = "block";
},
closeModalForAdd() {
document.getElementById("openModalForAdd").style.display = "none";
this.open = [...this.selectedGroups]; // Обновление массива open значениями из selectedGroups
this.selectedGroups = []; // Сброс выбранных групп
this.subject = new Subject(); // Сброс текущего предмета при закрытии модального окна
},
openModal(status, subject = null) { openModal(status, subject = null) {
if (status === "create") { if (status === "create") {
this.subject = new Subject(); this.subject = new Subject();
@ -116,6 +198,38 @@ export default {
closeModal() { closeModal() {
document.getElementById("editModal").style.display = "none"; document.getElementById("editModal").style.display = "none";
}, },
getGroups(){
axios.get(this.URL + "group")
.then(response => {
this.groups = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
saveSelectedGroups() {
// Сохранение выбранных групп в массив open
this.open = [...this.selectedGroups];
},
loadSelectedGroups() {
// Загрузка выбранных групп из массива open
this.selectedGroups = [...this.open];
},
addSubjectToGroup(id, list) {
axios
.post(this.URL + `subject/${id}/addSubjectToGroup`, list)
.then(() => {
this.closeModalForAdd();
this.getSubjects(); // Обновляем список предметов после успешного добавления
this.open = [...this.selectedGroups]; // Обновляем массив выбранных групп
})
.catch((error) => {
console.log(error);
});
},
} }
} }
</script> </script>

View File

@ -2,21 +2,16 @@ package ru.IP_LabWorks.IP.University.Contoller.DTO;
import ru.IP_LabWorks.IP.University.Model.Group; import ru.IP_LabWorks.IP.University.Model.Group;
import java.util.List;
public class GroupDTO { public class GroupDTO {
private long id; private long id;
private String name; private String name;
private List<Long> subjectIds;
public GroupDTO(){ public GroupDTO(){
} }
public GroupDTO(Group group){ public GroupDTO(Group group){
this.id = group.getId(); this.id = group.getId();
this.name = group.getName(); this.name = group.getName();
this.subjectIds = group.getSubjectIds();
} }
public Long getId(){ public Long getId(){
@ -34,8 +29,4 @@ public class GroupDTO {
public void setName(String name){ public void setName(String name){
this.name = name; this.name = name;
} }
public List<Long> getSubjectIds(){
return subjectIds;
}
} }

View File

@ -20,9 +20,8 @@ public class StudentDTO {
this.id = student.getId(); this.id = student.getId();
this.name = student.getName(); this.name = student.getName();
this.birthDate = student.getBirthDate(); this.birthDate = student.getBirthDate();
if(student.getGroup() != null){
this.groupName = student.getGroup().getName(); this.groupName = student.getGroup().getName();
} this.groupId = student.getGroup().getId();
} }
public String getGroupName() { public String getGroupName() {

View File

@ -1,29 +1,28 @@
package ru.IP_LabWorks.IP.University.Contoller.MVC; package ru.IP_LabWorks.IP.University.Contoller.MVC;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.IP_LabWorks.IP.University.Contoller.DTO.GroupDTO; import ru.IP_LabWorks.IP.University.Contoller.DTO.GroupDTO;
import ru.IP_LabWorks.IP.University.Contoller.DTO.StudentDTO;
import ru.IP_LabWorks.IP.University.Model.Student; import ru.IP_LabWorks.IP.University.Model.Student;
import ru.IP_LabWorks.IP.University.Model.Subject; import ru.IP_LabWorks.IP.University.Model.Subject;
import ru.IP_LabWorks.IP.University.Service.GroupService; import ru.IP_LabWorks.IP.University.Service.GroupService;
import ru.IP_LabWorks.IP.University.Service.SubjectService; import ru.IP_LabWorks.IP.University.Service.StudentService;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@Controller @Controller
@RequestMapping("/group") @RequestMapping("/group")
public class GroupMvcController { public class GroupMvcController {
private final GroupService groupService; private final GroupService groupService;
private final SubjectService subjectService;
public GroupMvcController(GroupService groupService, SubjectService subjectService) public GroupMvcController(GroupService groupService)
{ {
this.groupService = groupService; this.groupService = groupService;
this.subjectService = subjectService;
} }
@GetMapping @GetMapping
@ -70,7 +69,6 @@ public class GroupMvcController {
return "redirect:/group"; return "redirect:/group";
} }
@GetMapping("/students/{id}") @GetMapping("/students/{id}")
public String getStudentsFromGroup(@PathVariable Long id, Model model) { public String getStudentsFromGroup(@PathVariable Long id, Model model) {
List<Student> students = groupService.getStudentFromGroup(id); List<Student> students = groupService.getStudentFromGroup(id);
@ -84,45 +82,4 @@ public class GroupMvcController {
model.addAttribute("subjects", subjects); model.addAttribute("subjects", subjects);
return "view-subjects"; return "view-subjects";
} }
@GetMapping("/getStudentsUndefined/{id}")
public String getStudentsFromUndefinedGroup(@PathVariable Long id, Model model){
List<Student> students = groupService.getStudentsUndefined();
model.addAttribute("undefinedStudents", students);
model.addAttribute("groupId", id);
model.addAttribute("groupDTO", new GroupDTO(groupService.findGroup(id)));
return "add-students-to-group";
}
@PostMapping("/addStudents/{id}")
public String addStudentToGroup(@PathVariable Long id,
@RequestParam("studentId") List<String> studentsIds){
List<Long> studentIdsAsLong = studentsIds.stream()
.map(Long::parseLong)
.collect(Collectors.toList());
groupService.addStudentToGroup(id, studentIdsAsLong);
return "redirect:/group";
}
@PostMapping("/deleteStudentFromGroup/{id}")
public String deleteStudentFromGroup(@PathVariable Long id) {
groupService.deleteStudentFromGroup(id);
return "redirect:/group";
}
@GetMapping("/addSubjectToGroup/{id}")
public String addSubjectToGroupForm(@PathVariable Long id, Model model) {
model.addAttribute("groupDTO", new GroupDTO(groupService.findGroup(id)));
model.addAttribute("groupId", id);
model.addAttribute("subjects", subjectService.findAllSubjects());
return "add-subject-to-group";
}
@PostMapping("/addSubjectToGroup/{id}")
public String addSubjectToGroup(@PathVariable Long id,
@RequestParam("subjectId") List<Long> subjectIds) {
groupService.addSubjectToGroup(id, subjectIds);
return "redirect:/group";
}
} }

View File

@ -57,9 +57,9 @@ public class StudentMvcController {
return "student-edit"; return "student-edit";
} }
if (id == null || id <= 0) { if (id == null || id <= 0) {
studentService.addStudent(studentDTO.getName(), studentDTO.getBirthDate()); studentService.addStudent(studentDTO.getName(), studentDTO.getBirthDate(), studentDTO.getGroupId());
} else { } else {
studentService.updateStudent(id, studentDTO.getName(), studentDTO.getBirthDate()); studentService.updateStudent(id, studentDTO.getName(), studentDTO.getBirthDate(), studentDTO.getGroupId());
} }
return "redirect:/student"; return "redirect:/student";
} }

View File

@ -11,7 +11,6 @@ import ru.IP_LabWorks.IP.University.Service.GroupService;
import ru.IP_LabWorks.IP.WebConfiguration; import ru.IP_LabWorks.IP.WebConfiguration;
import java.util.List; import java.util.List;
import java.util.Map;
@RestController @RestController
@RequestMapping(WebConfiguration.REST_API + "/group") @RequestMapping(WebConfiguration.REST_API + "/group")
@ -61,28 +60,9 @@ public class GroupController {
return ResponseEntity.ok(subjects); return ResponseEntity.ok(subjects);
} }
@GetMapping("/getStudentsUndefined") // @PostMapping("/{id}/student")
public ResponseEntity<List<Student>> getStudentsFromUndefinedGroup(){ // public StudentDTO setStudentToGroup(@PathVariable Long id,
List<Student> students = groupService.getStudentsUndefined(); // @RequestParam("studentId") Long studentId) {
return ResponseEntity.ok(students); // return new StudentDTO(groupService.addStudentToGroup(id, studentId));
} // }
@PostMapping("/{id}/addStudents")
public void addStudentToGroup(@PathVariable Long id, @RequestBody @Valid List<Long> studentsIds){
groupService.addStudentToGroup(id, studentsIds);
}
@DeleteMapping("deleteStudentFromGroup/{id}")
public void deleteStudentFromGroup(@PathVariable Long id){
groupService.deleteStudentFromGroup(id);
}
@PostMapping("/{id}/addSubjectToGroup")
public void addSubjectToGroup(@PathVariable Long id, @RequestBody @Valid List<Long> subjectIds){
groupService.addSubjectToGroup(id, subjectIds);
}
@GetMapping("/getAll")
public Map<String, List<String>> getAll(){
return groupService.getAll();
}
} }

View File

@ -1,9 +1,7 @@
package ru.IP_LabWorks.IP.University.Contoller.REST; package ru.IP_LabWorks.IP.University.Contoller.REST;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ru.IP_LabWorks.IP.University.Contoller.DTO.GroupDTO;
import ru.IP_LabWorks.IP.University.Contoller.DTO.StudentDTO; import ru.IP_LabWorks.IP.University.Contoller.DTO.StudentDTO;
import ru.IP_LabWorks.IP.University.Service.GroupService;
import ru.IP_LabWorks.IP.University.Service.StudentService; import ru.IP_LabWorks.IP.University.Service.StudentService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@ -16,11 +14,9 @@ import java.util.List;
@RequestMapping(WebConfiguration.REST_API + "/student") @RequestMapping(WebConfiguration.REST_API + "/student")
public class StudentController { public class StudentController {
private final StudentService studentService; private final StudentService studentService;
private final GroupService groupService;
public StudentController(StudentService studentService, GroupService groupService) { public StudentController(StudentService studentService) {
this.studentService = studentService; this.studentService = studentService;
this.groupService = groupService;
} }
@GetMapping("/{id}") @GetMapping("/{id}")
@ -37,12 +33,12 @@ public class StudentController {
@PostMapping @PostMapping
public StudentDTO createStudent(@RequestBody @Valid StudentDTO studentDTO){ public StudentDTO createStudent(@RequestBody @Valid StudentDTO studentDTO){
return new StudentDTO(studentService.addStudent(studentDTO.getName(), studentDTO.getBirthDate())); return new StudentDTO(studentService.addStudent(studentDTO.getName(), studentDTO.getBirthDate(), studentDTO.getGroupId()));
} }
@PutMapping("/{id}") @PutMapping("/{id}")
public StudentDTO updateStudent(@PathVariable Long id, @RequestBody @Valid StudentDTO studentDTO) { public StudentDTO updateStudent(@PathVariable Long id, @RequestBody @Valid StudentDTO studentDTO) {
return new StudentDTO(studentService.updateStudent(id, studentDTO.getName(), studentDTO.getBirthDate())); return new StudentDTO(studentService.updateStudent(id, studentDTO.getName(), studentDTO.getBirthDate(), studentDTO.getGroupId()));
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@ -50,11 +46,4 @@ public class StudentController {
return new StudentDTO(studentService.deleteStudent(id)); return new StudentDTO(studentService.deleteStudent(id));
} }
@GetMapping("/groups")
public List<GroupDTO> getGroups() {
return groupService.findAllGroups().stream()
.map(GroupDTO::new)
.toList();
}
} }

View File

@ -8,7 +8,6 @@ import org.hibernate.annotations.OnDeleteAction;
import javax.swing.*; import javax.swing.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -90,18 +89,4 @@ public class Group {
subjects.add(subject); subjects.add(subject);
subject.getGroups().add(this); subject.getGroups().add(this);
} }
public List<Long> getSubjectIds() {
if (subjects.isEmpty()) {
return Collections.emptyList();
} else {
List<Long> subjectIds = new ArrayList<>();
for (Subject subject : subjects) {
if (!subjectIds.contains(subject.getId())) {
subjectIds.add(subject.getId());
}
}
return subjectIds;
}
}
} }

View File

@ -25,9 +25,10 @@ public class Student {
public Student() { public Student() {
} }
public Student(String name, LocalDate birthDate) { public Student(String name, LocalDate birthDate, Group group) {
this.name = name; this.name = name;
this.birthDate = birthDate; this.birthDate = birthDate;
this.group = group;
} }
public Long getId() { return id; } public Long getId() { return id; }
@ -58,13 +59,11 @@ public class Student {
@Override @Override
public String toString() { public String toString() {
String groupStr = (group != null) ? group.getName() : "No Group";
return "Student{" + return "Student{" +
"id=" + id + "id=" + id +
", name='" + name + '\'' + ", name='" + name + '\'' +
", birthDate='" + birthDate + '\'' + ", birthDate='" + birthDate + '\'' +
", age='" + getAge() + '\'' + ", age='" + getAge() + '\'' +
", group='" + groupStr + '\'' +
'}'; '}';
} }

View File

@ -1,15 +1,7 @@
package ru.IP_LabWorks.IP.University.Repository; package ru.IP_LabWorks.IP.University.Repository;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import ru.IP_LabWorks.IP.University.Model.Group; import ru.IP_LabWorks.IP.University.Model.Group;
import java.util.List;
public interface GroupRepository extends JpaRepository<Group, Long> { public interface GroupRepository extends JpaRepository<Group, Long> {
@Query("select g.name as group, s.name as students " +
"from Group g " +
"join g.students s " +
"group by g.id, g.name, s.name")
List<Object[]> getAll();
} }

View File

@ -1,6 +1,6 @@
package ru.IP_LabWorks.IP.University.Service; package ru.IP_LabWorks.IP.University.Service;
import org.springframework.context.annotation.Lazy; import jakarta.persistence.EntityNotFoundException;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -8,25 +8,19 @@ import ru.IP_LabWorks.IP.University.Model.Group;
import ru.IP_LabWorks.IP.University.Model.Student; import ru.IP_LabWorks.IP.University.Model.Student;
import ru.IP_LabWorks.IP.University.Model.Subject; import ru.IP_LabWorks.IP.University.Model.Subject;
import ru.IP_LabWorks.IP.University.Repository.GroupRepository; import ru.IP_LabWorks.IP.University.Repository.GroupRepository;
import ru.IP_LabWorks.IP.University.Repository.StudentRepository;
import ru.IP_LabWorks.IP.University.Service.NotFoundException.GroupNotFoundException; import ru.IP_LabWorks.IP.University.Service.NotFoundException.GroupNotFoundException;
import java.util.ArrayList; import java.awt.desktop.OpenFilesEvent;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
@Service @Service
public class GroupService { public class GroupService {
private final GroupRepository groupRepository; private final GroupRepository groupRepository;
private final StudentService studentService; public GroupService(GroupRepository groupRepository) {
private final SubjectService subjectService;
public GroupService(GroupRepository groupRepository, StudentService studentService, @Lazy SubjectService subjectService) {
this.groupRepository = groupRepository; this.groupRepository = groupRepository;
this.studentService = studentService;
this.subjectService = subjectService;
} }
@Transactional @Transactional
@ -93,49 +87,30 @@ public class GroupService {
} }
} }
@Transactional /* @Transactional
public List<Student> getStudentsUndefined(){ public Group addStudentToGroup(Long groupId, Long studentId) {
List<Student> students = new ArrayList<>(); Group group = findGroup(groupId);
for(Student student : studentService.findAllStudents()){ Student student = studentService.findStudent(studentId);
if(student.getGroup() == null){ if (group == null || student == null) {
students.add(student); throw new EntityNotFoundException("Group or Student not found");
}
}
return students;
}
@Transactional
public void addStudentToGroup(Long groupId, List<Long> studentIds){
final Group currentGroup = findGroup(groupId);
for(Long studentId : studentIds) {
studentService.findStudent(studentId).setGroup(currentGroup);
}
groupRepository.save(currentGroup);
}
@Transactional
public void deleteStudentFromGroup(Long id){
studentService.findStudent(id).setGroup(null);
}
@Transactional
public void addSubjectToGroup(Long groupId, List<Long> subjectIds){
final Group currentGroup = findGroup(groupId);
currentGroup.setSubjects(new ArrayList<>());
for(Long subjectId : subjectIds) {
currentGroup.getSubjects().add(subjectService.findSubject(subjectId));
}
groupRepository.save(currentGroup);
}
@Transactional
public Map<String, List<String>> getAll(){
return groupRepository.getAll().stream()
.collect(
Collectors.groupingBy(
o -> (String) o[0],
Collectors.mapping( o -> (String) o[1], Collectors.toList() )
)
);
} }
group.setStudent(student);
return group;
}*/
//
// @Transactional
// public void removeStudentFromGroup(Long groupId, Long studentId) {
// Group group = findGroup(groupId);
// Student student = em.find(Student.class, studentId);
// group.getStudents().remove(student);
// }
//
// @Transactional(readOnly = true)
// public List<Student> findStudentsInGroup(Long groupId) {
// Group group = findGroup(groupId);
// if (group == null) {
// throw new EntityNotFoundException("Group not found");
// }
// return group.getStudents();
// }
} }

View File

@ -1,7 +1,5 @@
package ru.IP_LabWorks.IP.University.Service; package ru.IP_LabWorks.IP.University.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -19,17 +17,23 @@ public class StudentService {
private final StudentRepository studentRepository; private final StudentRepository studentRepository;
private final GroupService groupService; private final GroupService groupService;
public StudentService(StudentRepository studentRepository,@Lazy GroupService groupService) { public StudentService(StudentRepository studentRepository, GroupService groupService) {
this.studentRepository = studentRepository; this.studentRepository = studentRepository;
this.groupService = groupService; this.groupService = groupService;
} }
@Transactional @Transactional
public Student addStudent(String name, LocalDate birthDate){ public Student addStudent(String name, LocalDate birthDate, Long groupId){
if (!StringUtils.hasText(name) || !StringUtils.hasText(String.valueOf(birthDate))) { if (!StringUtils.hasText(name) || !StringUtils.hasText(String.valueOf(birthDate))) {
throw new IllegalArgumentException("Student name or date is null or empty"); throw new IllegalArgumentException("Student name or date is null or empty");
} }
final Student student = new Student(name, birthDate); Group group = null;
try{
group = groupService.findGroup(groupId);
}catch (Exception ex){
group = null;
}
final Student student = new Student(name, birthDate,group);
return studentRepository.save(student); return studentRepository.save(student);
} }
@ -45,13 +49,14 @@ public class StudentService {
} }
@Transactional @Transactional
public Student updateStudent(Long id, String name, LocalDate date) { public Student updateStudent(Long id, String name, LocalDate date, Long groupId) {
if (!StringUtils.hasText(name) || !StringUtils.hasText(String.valueOf(date))) { if (!StringUtils.hasText(name) || !StringUtils.hasText(String.valueOf(date))) {
throw new IllegalArgumentException("Student name or date is null or empty"); throw new IllegalArgumentException("Student name or date is null or empty");
} }
final Student currentStudent = findStudent(id); final Student currentStudent = findStudent(id);
currentStudent.setName(name); currentStudent.setName(name);
currentStudent.setBirthDate(date); currentStudent.setBirthDate(date);
currentStudent.setGroup(groupService.findGroup(groupId));
return studentRepository.save(currentStudent); return studentRepository.save(currentStudent);
} }

View File

@ -1,37 +0,0 @@
<!DOCTYPE html>
<html lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head>
</head>
<body>
<div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/group/addStudents/{id}(id=${groupId})}" method="post">
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${groupDTO.name}" readonly>
</div>
<div class="form-group">
<label for="name">Выберите студентов:</label>
<ul class="list-group">
<li class="list-group-item" th:each="student, iterator: ${undefinedStudents}">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="studentId" th:value="${student.id}">
<label class="form-check-label" th:text="${student.name}"></label>
</div>
</li>
</ul>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span>Добавить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/group}">
Назад
</a>
</div>
</form>
</div>
</body>
</html>

View File

@ -7,19 +7,19 @@
<body> <body>
<div layout:fragment="content"> <div layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div> <div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form action="#" th:action="@{/group/addSubjectToGroup/{id}(id=${groupId})}" method="post"> <form action="#" th:action="@{/subject/addSubjectToGroup/{id}(id=${subjectId})}" method="post">
<div class="mb-3"> <div class="mb-3">
<label for="name" class="form-label">Название</label> <label for="name" class="form-label">Название</label>
<input type="text" class="form-control" id="name" th:field="${groupDTO.name}" readonly> <input type="text" class="form-control" id="name" th:field="${subjectDTO.name}" readonly>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="name">Выберите предметы для добавления:</label> <label for="name">Выберите группы для добавления:</label>
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item" th:each="subject, iterator: ${subjects}"> <li class="list-group-item" th:each="group, iterator: ${groups}">
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" th:id="'subjectId-' + ${subject.id}" <input class="form-check-input" type="checkbox" th:id="'groupId-' + ${group.id}"
th:value="${subject.id}" th:checked="${groupDTO.subjectIds.contains(subject.id)}" name="subjectId"> th:value="${group.id}" th:checked="${subjectDTO.groupIds.contains(group.id)}" name="groupId">
<label class="form-check-label" th:for="'subjectId-' + ${subject.id}" th:text="${subject.name}"></label> <label class="form-check-label" th:for="'groupId-' + ${group.id}" th:text="${group.name}"></label>
</div> </div>
</li> </li>
</ul> </ul>
@ -28,7 +28,7 @@
<button type="submit" class="btn btn-primary button-fixed"> <button type="submit" class="btn btn-primary button-fixed">
<span>Добавить</span> <span>Добавить</span>
</button> </button>
<a class="btn btn-secondary button-fixed" th:href="@{/group}"> <a class="btn btn-secondary button-fixed" th:href="@{/subject}">
Назад Назад
</a> </a>
</div> </div>

View File

@ -34,10 +34,6 @@
</button> </button>
<a class="btn btn-primary button-fixed button-sm" <a class="btn btn-primary button-fixed button-sm"
th:href="@{/group/students/{id}(id=${group.id})}">Посмотреть студентов</a> th:href="@{/group/students/{id}(id=${group.id})}">Посмотреть студентов</a>
<a class="btn btn-primary button-fixed button-sm"
th:href="@{/group/getStudentsUndefined/{id}(id=${group.id})}">Добавить студентов</a>
<a class="btn btn-primary button-fixed button-sm"
th:href="@{/group/addSubjectToGroup/{id}(id=${group.id})}"> Добавить предметы</a>
<a class="btn btn-primary button-fixed button-sm" <a class="btn btn-primary button-fixed button-sm"
th:href="@{/group/subjects/{id}(id=${group.id})}">Посмотреть предметы</a> th:href="@{/group/subjects/{id}(id=${group.id})}">Посмотреть предметы</a>
</div> </div>

View File

@ -16,6 +16,12 @@
<label for="birthDate" class="form-label">Дата рождения</label> <label for="birthDate" class="form-label">Дата рождения</label>
<input type="date" class="form-control" id="birthDate" th:field="${studentDTO.birthDate}" required="true"> <input type="date" class="form-control" id="birthDate" th:field="${studentDTO.birthDate}" required="true">
</div> </div>
<div class="mb-3">
<label for="group" class="form-label">Группа</label>
<select id="group" class="form-control" th:field="${studentDTO.groupId}">
<option th:each="group : ${Groups}" th:value="${group.id}" th:text="${group.name}"></option>
</select>
</div>
<div class="mb-3"> <div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed"> <button type="submit" class="btn btn-primary button-fixed">
<span th:if="${studentId == null}">Добавить</span> <span th:if="${studentId == null}">Добавить</span>

View File

@ -32,6 +32,10 @@
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${subject.id}').click()|"> th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${subject.id}').click()|">
<i class="fa fa-trash" aria-hidden="true"></i> Удалить <i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button> </button>
<a class="btn btn-primary button-fixed button-sm"
th:href="@{/subject/addSubjectToGroup/{id}(id=${subject.id})}">
<i class="fa fa-pencil" aria-hidden="true"></i> Добавить предметы в группы
</a>
</div> </div>
<form th:action="@{/subject/delete/{id}(id=${subject.id})}" method="post"> <form th:action="@{/subject/delete/{id}(id=${subject.id})}" method="post">
<button th:id="'remove-' + ${subject.id}" type="submit" style="display: none"> <button th:id="'remove-' + ${subject.id}" type="submit" style="display: none">

View File

@ -12,18 +12,12 @@
<tr> <tr>
<th scope="col">ФИО</th> <th scope="col">ФИО</th>
<th scope="col">Дата рождения</th> <th scope="col">Дата рождения</th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr th:each="student, iterator: ${students}"> <tr th:each="student, iterator: ${students}">
<td th:text="${student.name}"></td> <td th:text="${student.name}"></td>
<td th:text="${student.birthDate}"></td> <td th:text="${student.birthDate}"></td>
<td>
<form method="post" th:action="@{/group/deleteStudentFromGroup/{id}(id=${student.id})}">
<button type="submit" class="btn btn-danger button-fixed button-sm">Удалить</button>
</form>
</td>
</tr> </tr>
</tbody> </tbody>
<a class="btn btn-secondary button-fixed" th:href="@{/group}"> <a class="btn btn-secondary button-fixed" th:href="@{/group}">