Добавлены студенты и добавление их в группу, осталось добавить добавление предметов
This commit is contained in:
parent
db321f5899
commit
51f3480755
@ -15,7 +15,8 @@ repositories {
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'com.h2database:h2:2.1.210'
|
||||
|
||||
implementation 'jakarta.validation:jakarta.validation-api:3.0.0'
|
||||
implementation 'org.hibernate.validator:hibernate-validator:7.0.1.Final'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
BIN
data.mv.db
BIN
data.mv.db
Binary file not shown.
1035
data.trace.db
1035
data.trace.db
File diff suppressed because it is too large
Load Diff
152
frontend/vue-project/package-lock.json
generated
152
frontend/vue-project/package-lock.json
generated
@ -8,6 +8,7 @@
|
||||
"name": "vue-project",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"vue": "^3.2.47",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
@ -499,11 +500,45 @@
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz",
|
||||
"integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ=="
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "2.6.21",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
|
||||
"integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.17.17",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz",
|
||||
@ -546,6 +581,38 @@
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
@ -568,6 +635,25 @@
|
||||
"sourcemap-codec": "^1.4.8"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
@ -617,6 +703,11 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "3.20.7",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.7.tgz",
|
||||
@ -1001,11 +1092,39 @@
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz",
|
||||
"integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ=="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
"version": "2.6.21",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
|
||||
"integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.17.17",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz",
|
||||
@ -1041,6 +1160,21 @@
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
@ -1056,6 +1190,19 @@
|
||||
"sourcemap-codec": "^1.4.8"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
@ -1076,6 +1223,11 @@
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"rollup": {
|
||||
"version": "3.20.7",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.7.tgz",
|
||||
|
@ -8,6 +8,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"vue": "^3.2.47",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
|
@ -7,7 +7,9 @@
|
||||
|
||||
<template>
|
||||
<Header></Header>
|
||||
<div class="container-fluid">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
6
frontend/vue-project/src/models/Group.js
Normal file
6
frontend/vue-project/src/models/Group.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default class Group{
|
||||
constructor(data) {
|
||||
this.id = data?.id;
|
||||
this.name = data?.name;
|
||||
}
|
||||
}
|
8
frontend/vue-project/src/models/Student.js
Normal file
8
frontend/vue-project/src/models/Student.js
Normal file
@ -0,0 +1,8 @@
|
||||
export default class Student{
|
||||
constructor(data) {
|
||||
this.id = data?.id;
|
||||
this.name = data?.name;
|
||||
this.birthDate = data?.birthDate;
|
||||
this.group = data?.group;
|
||||
}
|
||||
}
|
6
frontend/vue-project/src/models/Subject.js
Normal file
6
frontend/vue-project/src/models/Subject.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default class Subject{
|
||||
constructor(data) {
|
||||
this.id = data?.id;
|
||||
this.name = data?.name;
|
||||
}
|
||||
}
|
@ -1,8 +1,114 @@
|
||||
<template>
|
||||
|
||||
<div class="container mt-4">
|
||||
<h1 class="text-center mb-4">Group Table</h1>
|
||||
<button class="btn btn-primary mr-2" @click="openModal(); group.status = `create`">Добавить</button>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Имя</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="grp in groups" :key="grp.id">
|
||||
<td>{{ grp.name }}</td>
|
||||
<td>
|
||||
<button class="btn btn-primary mr-2" @click="openModal(); group = grp; group.status = `edit`">Изменить</button>
|
||||
<button class="btn btn-danger" @click="deleteGroup(grp.id)">Удалить</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal" tabindex="-1" id="editModal">
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="editModal" @click="closeModal()">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-if="group.status === `create`"
|
||||
@click="addGroup">Создать</button>
|
||||
<button type="button" class="btn btn-primary" v-else
|
||||
@click="editGroup(group)">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import 'axios';
|
||||
import axios from "axios";
|
||||
import Group from "@/models/Group";
|
||||
export default {
|
||||
created() {
|
||||
this.getGroups();
|
||||
},
|
||||
mounted() {
|
||||
const addModal = document.getElementById('editModal');
|
||||
addModal.addEventListener('shown.bs.modal', function () {
|
||||
})
|
||||
},
|
||||
|
||||
data() {
|
||||
return{
|
||||
groups: [],
|
||||
URL: "http://localhost:8080/",
|
||||
group: new Group(),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getGroups(){
|
||||
axios.get(this.URL + "group")
|
||||
.then(response => {
|
||||
this.groups = response.data;
|
||||
console.log(response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
addGroup(){
|
||||
console.log(this.group);
|
||||
axios.post(this.URL + "group", this.group)
|
||||
.then(() => {
|
||||
this.getGroups();
|
||||
this.closeModal();
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
deleteGroup(id){
|
||||
axios.delete(this.URL + `group/${id}`)
|
||||
.then(() =>{
|
||||
this.getGroups();
|
||||
})
|
||||
},
|
||||
editGroup(group){
|
||||
this.group = group;
|
||||
axios.put(this.URL + `group/${group.id}`, this.group)
|
||||
.then(() =>{
|
||||
this.getGroups();
|
||||
})
|
||||
this.closeModal();
|
||||
},
|
||||
openModal() {
|
||||
document.getElementById("editModal").style.display = "block";
|
||||
},
|
||||
closeModal() {
|
||||
document.getElementById("editModal").style.display = "none";
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
@ -1,68 +1,142 @@
|
||||
<template>
|
||||
<div class="add_student_button">
|
||||
<button id="add_btn" type="submit" data-bs-toggle="modal" data-bs-target="#addModal">Добавить студента</button>
|
||||
</div>
|
||||
<table class="table table-striped table-bordered table-hover">
|
||||
<div class="container mt-4">
|
||||
<h1 class="text-center mb-4">Student Table</h1>
|
||||
<button class="btn btn-primary mr-2" @click="openModal(); student.status = `create`">Добавить</button>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ФИО</th>
|
||||
<th>Имя</th>
|
||||
<th>Дата рождения</th>
|
||||
<th>Группа</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(student, index) in students" :key="index">
|
||||
<td>{{ student.name }}</td>
|
||||
<td>{{ student.birthDate }}</td>
|
||||
<td><button class="buttonUpdate" @click="openModal(student)" data-bs-toggle="modal" data-bs-target="#exampleModal"></button></td>
|
||||
<td><button class="buttonRemove" @click="deleteUser(student)"></button></td>
|
||||
<tr v-for="stud in students" :key="stud.id">
|
||||
<td>{{ stud.name }}</td>
|
||||
<td>{{ stud.birthDate }}</td>
|
||||
<td>{{ stud.groupName }}</td>
|
||||
<td>
|
||||
<button class="btn btn-primary mr-2" @click="openModal(); student = stud; student.status = `edit`">Изменить</button>
|
||||
<button class="btn btn-danger" @click="deleteStudent(stud.id)">Удалить</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="modal" ref="addModal" id="addModal" tabindex="-1">
|
||||
</div>
|
||||
<div class="modal" tabindex="-1" id="editModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Добавить студента</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<h5 class="modal-title">Студент</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Имя</label>
|
||||
<input type="text" class="form-control" id="name">
|
||||
<div class="form-group">
|
||||
<label for="name">Имя:</label>
|
||||
<input type="text" class="form-control" id="name" name="name" v-model="student.name">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="birthDate" class="form-label">Дата рождения</label>
|
||||
<input type="date" class="form-control" id="birthDate">
|
||||
<div class="form-group">
|
||||
<label for="birthdate">Дата рождения:</label>
|
||||
<input type="date" class="form-control" id="birthdate" name="birthdate" v-model="student.birthDate">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="group" class="form-label">Группа</label>
|
||||
<input type="text" class="form-control" id="group">
|
||||
<div class="form-group">
|
||||
<label for="group">Группа:</label>
|
||||
<select v-model="student.groupId" class="form-control">
|
||||
<option v-for="(group, index) in groups" :key="index" :value="group.id">
|
||||
{{group.name}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Сохранить</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="editModal" @click="closeModal()">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-if="student.status === `create`"
|
||||
@click="addStudent">Создать</button>
|
||||
<button type="button" class="btn btn-primary" v-else
|
||||
@click="editStudent(student)">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import 'axios';
|
||||
import axios from "axios";
|
||||
import Student from "@/models/Student";
|
||||
export default {
|
||||
data(){
|
||||
created() {
|
||||
this.getStudents();
|
||||
this.getGroups();
|
||||
},
|
||||
mounted() {
|
||||
const addModal = document.getElementById('editModal');
|
||||
addModal.addEventListener('shown.bs.modal', function () {
|
||||
})
|
||||
},
|
||||
|
||||
data() {
|
||||
return{
|
||||
name: "",
|
||||
birthDate: ""
|
||||
students: [],
|
||||
groups: [],
|
||||
URL: "http://localhost:8080/",
|
||||
student: new Student(),
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
addUser(){
|
||||
fetch('')
|
||||
.then(response => response.text())
|
||||
}
|
||||
methods: {
|
||||
getStudents(){
|
||||
axios.get(this.URL + "student")
|
||||
.then(response => {
|
||||
this.students = response.data;
|
||||
console.log(response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
getGroups(){
|
||||
axios.get(this.URL + "group")
|
||||
.then(response => {
|
||||
this.groups = response.data;
|
||||
console.log(response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
addStudent(){
|
||||
console.log(this.student);
|
||||
axios.post(this.URL + "student", this.student)
|
||||
.then(() => {
|
||||
this.getStudents();
|
||||
this.closeModal();
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
deleteStudent(id){
|
||||
axios.delete(this.URL + `student/${id}`)
|
||||
.then(() =>{
|
||||
this.getStudents();
|
||||
})
|
||||
},
|
||||
editStudent(student){
|
||||
this.student = student;
|
||||
axios.put(this.URL + `student/${student.id}`, this.student)
|
||||
.then(() =>{
|
||||
this.getStudents();
|
||||
})
|
||||
this.closeModal();
|
||||
},
|
||||
openModal() {
|
||||
document.getElementById("editModal").style.display = "block";
|
||||
},
|
||||
closeModal() {
|
||||
document.getElementById("editModal").style.display = "none";
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,55 +1,114 @@
|
||||
<template>
|
||||
<div class="add_student_button">
|
||||
<button id="add_btn" type="submit" data-bs-toggle="modal" data-bs-target="#addModal">Добавить предмет</button>
|
||||
</div>
|
||||
<table class="table table-striped table-bordered table-hover">
|
||||
<div class="container mt-4">
|
||||
<h1 class="text-center mb-4">Subject Table</h1>
|
||||
<button class="btn btn-primary mr-2" @click="openModal(); subject.status = `create`">Добавить</button>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Название предмета</th>
|
||||
<th>Имя</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(subject, index) in subjects" :key="index">
|
||||
<td>{{ subject.name }}</td>
|
||||
<td><button class="buttonUpdate" @click="openModal(subject)" data-bs-toggle="modal" data-bs-target="#exampleModal"></button></td>
|
||||
<td><button class="buttonRemove" @click="deleteUser(subject)"></button></td>
|
||||
<tr v-for="sbjct in subjects" :key="sbjct.id">
|
||||
<td>{{ sbjct.name }}</td>
|
||||
<td>
|
||||
<button class="btn btn-primary mr-2" @click="openModal(); subject = sbjct; subject.status = `edit`">Изменить</button>
|
||||
<button class="btn btn-danger" @click="deleteSubject(sbjct.id)">Удалить</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="modal" ref="addModal" id="addModal" tabindex="-1">
|
||||
</div>
|
||||
<div class="modal" tabindex="-1" id="editModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Добавить пердмет</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<h5 class="modal-title">Предмет</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Название</label>
|
||||
<input type="text" class="form-control" id="name">
|
||||
<div class="form-group">
|
||||
<label for="name">Имя:</label>
|
||||
<input type="text" class="form-control" id="name" name="name" v-model="subject.name">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Сохранить</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="editModal" @click="closeModal()">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-if="subject.status === `create`"
|
||||
@click="addSubject">Создать</button>
|
||||
<button type="button" class="btn btn-primary" v-else
|
||||
@click="editSubject(subject)">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import 'axios';
|
||||
import axios from "axios";
|
||||
import Subject from "@/models/Subject";
|
||||
export default {
|
||||
data(){
|
||||
created() {
|
||||
this.getSubjects();
|
||||
},
|
||||
mounted() {
|
||||
const addModal = document.getElementById('editModal');
|
||||
addModal.addEventListener('shown.bs.modal', function () {
|
||||
})
|
||||
},
|
||||
|
||||
data() {
|
||||
return{
|
||||
name: ""
|
||||
subjects: [],
|
||||
URL: "http://localhost:8080/",
|
||||
subject: new Subject(),
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
methods: {
|
||||
getSubjects(){
|
||||
axios.get(this.URL + "subject")
|
||||
.then(response => {
|
||||
this.subjects = response.data;
|
||||
console.log(response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
addSubject(){
|
||||
|
||||
}
|
||||
console.log(this.subjects);
|
||||
axios.post(this.URL + "subject", this.subject)
|
||||
.then(() => {
|
||||
this.getSubjects();
|
||||
this.closeModal();
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
this.subject = new Subject();
|
||||
},
|
||||
deleteSubject(id){
|
||||
axios.delete(this.URL + `subject/${id}`)
|
||||
.then(() =>{
|
||||
this.getSubjects();
|
||||
})
|
||||
},
|
||||
editSubject(subject){
|
||||
this.subject = subject;
|
||||
axios.put(this.URL + `subject/${subject.id}`, this.subject)
|
||||
.then(() =>{
|
||||
this.getSubjects();
|
||||
})
|
||||
this.closeModal();
|
||||
},
|
||||
openModal() {
|
||||
document.getElementById("editModal").style.display = "block";
|
||||
},
|
||||
closeModal() {
|
||||
document.getElementById("editModal").style.display = "none";
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -5,7 +5,7 @@ import subjects from "../pages/subjects.vue"
|
||||
import {createRouter, createWebHistory} from "vue-router"
|
||||
|
||||
const routes = [
|
||||
{path: '/', component: students},
|
||||
{path: '/students', component: students},
|
||||
{path: '/groups', component: groups},
|
||||
{path: '/subjects', component: subjects},
|
||||
]
|
||||
|
@ -3,9 +3,12 @@ package ru.IP_LabWorks.IP.University.Contoller.DTO;
|
||||
import ru.IP_LabWorks.IP.University.Model.Group;
|
||||
|
||||
public class GroupDTO {
|
||||
private final long id;
|
||||
private final String name;
|
||||
private long id;
|
||||
private String name;
|
||||
|
||||
public GroupDTO(){
|
||||
|
||||
}
|
||||
public GroupDTO(Group group){
|
||||
this.id = group.getId();
|
||||
this.name = group.getName();
|
||||
@ -18,4 +21,12 @@ public class GroupDTO {
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setId(long id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setName(String name){
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,32 @@
|
||||
package ru.IP_LabWorks.IP.University.Contoller.DTO;
|
||||
|
||||
import ru.IP_LabWorks.IP.University.Model.Group;
|
||||
import ru.IP_LabWorks.IP.University.Model.Student;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class StudentDTO {
|
||||
private final long id;
|
||||
private final String name;
|
||||
private final LocalDate birthDate;
|
||||
private long id;
|
||||
private String name;
|
||||
private LocalDate birthDate;
|
||||
|
||||
private long groupId;
|
||||
private String groupName;
|
||||
|
||||
public StudentDTO() {
|
||||
}
|
||||
public StudentDTO(Student student) {
|
||||
this.id = student.getId();
|
||||
this.name = student.getName();
|
||||
this.birthDate = student.getBirthDate();
|
||||
this.groupName = student.getGroup().getName();
|
||||
this.groupId = student.getGroup().getId();
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
public Long getId(){
|
||||
return id;
|
||||
}
|
||||
@ -26,4 +38,24 @@ public class StudentDTO {
|
||||
public LocalDate getBirthDate(){
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public Long getGroupId(){
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(long id){
|
||||
this.groupId = id;
|
||||
}
|
||||
|
||||
public void setId(long id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setName(String name){
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setBirthDate(String birthDate){
|
||||
this.birthDate = LocalDate.parse(birthDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,12 @@ package ru.IP_LabWorks.IP.University.Contoller.DTO;
|
||||
import ru.IP_LabWorks.IP.University.Model.Subject;
|
||||
|
||||
public class SubjectDTO {
|
||||
private final long id;
|
||||
private final String name;
|
||||
private long id;
|
||||
private String name;
|
||||
|
||||
public SubjectDTO(){
|
||||
|
||||
}
|
||||
public SubjectDTO(Subject subject){
|
||||
this.id = subject.getId();
|
||||
this.name = subject.getName();
|
||||
|
@ -1,7 +1,9 @@
|
||||
package ru.IP_LabWorks.IP.University.Contoller.REST;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
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.Service.GroupService;
|
||||
|
||||
import java.util.List;
|
||||
@ -28,18 +30,23 @@ public class GroupController {
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public GroupDTO createGroup(@RequestParam("name") String name){
|
||||
return new GroupDTO(groupService.addGroup(name));
|
||||
public GroupDTO createGroup(@RequestBody @Valid GroupDTO groupDTO){
|
||||
return new GroupDTO(groupService.addGroup(groupDTO.getName()));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public GroupDTO updateGroup(@PathVariable Long id,
|
||||
@RequestParam("name") String name){
|
||||
return new GroupDTO(groupService.updateGroup(id, name));
|
||||
public GroupDTO updateGroup(@PathVariable Long id, @RequestBody @Valid GroupDTO groupDTO){
|
||||
return new GroupDTO(groupService.updateGroup(id, groupDTO.getName()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public GroupDTO deleteGroup(@PathVariable Long id){
|
||||
return new GroupDTO(groupService.deleteGroup(id));
|
||||
}
|
||||
|
||||
// @PostMapping("/{id}/student")
|
||||
// public StudentDTO setStudentToGroup(@PathVariable Long id,
|
||||
// @RequestParam("studentId") Long studentId) {
|
||||
// return new StudentDTO(groupService.addStudentToGroup(id, studentId));
|
||||
// }
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import ru.IP_LabWorks.IP.University.Contoller.DTO.StudentDTO;
|
||||
import ru.IP_LabWorks.IP.University.Service.StudentService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@ -29,16 +30,13 @@ public class StudentController {
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public StudentDTO createStudent(@RequestParam("name") String name,
|
||||
@RequestParam("birthDate")LocalDate birthDate){
|
||||
return new StudentDTO(studentService.addStudent(name, birthDate));
|
||||
public StudentDTO createStudent(@RequestBody @Valid StudentDTO studentDTO){
|
||||
return new StudentDTO(studentService.addStudent(studentDTO.getName(), studentDTO.getBirthDate(), studentDTO.getGroupId()));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public StudentDTO updateStudent(@PathVariable Long id,
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam("birthDate") LocalDate birthDate){
|
||||
return new StudentDTO(studentService.updateStudent(id, name, birthDate));
|
||||
public StudentDTO updateStudent(@PathVariable Long id, @RequestBody @Valid StudentDTO studentDTO) {
|
||||
return new StudentDTO(studentService.updateStudent(id, studentDTO.getName(), studentDTO.getBirthDate(), studentDTO.getGroupId()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.IP_LabWorks.IP.University.Contoller.REST;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.IP_LabWorks.IP.University.Contoller.DTO.GroupDTO;
|
||||
import ru.IP_LabWorks.IP.University.Contoller.DTO.SubjectDTO;
|
||||
@ -30,14 +31,13 @@ public class SubjectController {
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public SubjectDTO createSubject(@RequestParam("name") String name){
|
||||
return new SubjectDTO(subjectService.addSubject(name));
|
||||
public SubjectDTO createSubject(@RequestBody @Valid SubjectDTO subjectDTO){
|
||||
return new SubjectDTO(subjectService.addSubject(subjectDTO.getName()));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public SubjectDTO updateSubject(@PathVariable Long id,
|
||||
@RequestParam("name") String name){
|
||||
return new SubjectDTO(subjectService.updateSubject(id, name));
|
||||
public SubjectDTO updateSubject(@PathVariable Long id, @RequestBody @Valid SubjectDTO subjectDTO){
|
||||
return new SubjectDTO(subjectService.updateSubject(id,subjectDTO.getName()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.IP_LabWorks.IP.University.Model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonManagedReference;
|
||||
import jakarta.persistence.*;
|
||||
import org.hibernate.annotations.Cascade;
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
@ -18,6 +19,7 @@ public class Group {
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
@JsonManagedReference
|
||||
@OneToMany(orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "group")
|
||||
@OnDelete(action = OnDeleteAction.CASCADE)
|
||||
private List<Student> students;
|
||||
|
@ -1,4 +1,5 @@
|
||||
package ru.IP_LabWorks.IP.University.Model;
|
||||
import com.fasterxml.jackson.annotation.JsonBackReference;
|
||||
import jakarta.persistence.*;
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
@ -16,6 +17,7 @@ public class Student {
|
||||
private String name;
|
||||
private LocalDate birthDate;
|
||||
|
||||
@JsonBackReference
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "group_id")
|
||||
private Group group;
|
||||
@ -23,9 +25,10 @@ public class Student {
|
||||
public Student() {
|
||||
}
|
||||
|
||||
public Student(String name, LocalDate birthDate) {
|
||||
public Student(String name, LocalDate birthDate, Group group) {
|
||||
this.name = name;
|
||||
this.birthDate = birthDate;
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public Long getId() { return id; }
|
||||
@ -69,9 +72,14 @@ public class Student {
|
||||
}
|
||||
|
||||
public void setGroup(Group group) {
|
||||
if (this.group != group) {
|
||||
if (this.group != null) {
|
||||
this.group.getStudents().remove(this);
|
||||
}
|
||||
this.group = group;
|
||||
if(!group.getStudents().contains(this)){
|
||||
if (group != null && !group.getStudents().contains(this)) {
|
||||
group.getStudents().add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import org.springframework.util.StringUtils;
|
||||
import ru.IP_LabWorks.IP.University.Model.Group;
|
||||
import ru.IP_LabWorks.IP.University.Model.Student;
|
||||
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 java.awt.desktop.OpenFilesEvent;
|
||||
@ -63,16 +64,16 @@ public class GroupService {
|
||||
groupRepository.deleteAll();
|
||||
}
|
||||
|
||||
// @Transactional
|
||||
// public void addStudentToGroup(Long groupId, Long studentId) {
|
||||
// Group group = findGroup(groupId);
|
||||
// Student student = em.find(Student.class, studentId);
|
||||
// if (group == null || student == null) {
|
||||
// throw new EntityNotFoundException("Group or Student not found");
|
||||
// }
|
||||
// student.setGroup(group);
|
||||
// em.merge(student);
|
||||
// }
|
||||
/* @Transactional
|
||||
public Group addStudentToGroup(Long groupId, Long studentId) {
|
||||
Group group = findGroup(groupId);
|
||||
Student student = studentService.findStudent(studentId);
|
||||
if (group == null || student == null) {
|
||||
throw new EntityNotFoundException("Group or Student not found");
|
||||
}
|
||||
group.setStudent(student);
|
||||
return group;
|
||||
}*/
|
||||
//
|
||||
// @Transactional
|
||||
// public void removeStudentFromGroup(Long groupId, Long studentId) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ru.IP_LabWorks.IP.University.Service;
|
||||
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
@ -16,17 +15,19 @@ import java.util.Optional;
|
||||
@Service
|
||||
public class StudentService {
|
||||
private final StudentRepository studentRepository;
|
||||
private final GroupService groupService;
|
||||
|
||||
public StudentService(StudentRepository studentRepository) {
|
||||
public StudentService(StudentRepository studentRepository, GroupService groupService) {
|
||||
this.studentRepository = studentRepository;
|
||||
this.groupService = groupService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Student addStudent(String name, LocalDate date){
|
||||
if (!StringUtils.hasText(name) || !StringUtils.hasText(String.valueOf(date))) {
|
||||
public Student addStudent(String name, LocalDate birthDate, Long groupId){
|
||||
if (!StringUtils.hasText(name) || !StringUtils.hasText(String.valueOf(birthDate))) {
|
||||
throw new IllegalArgumentException("Student name or date is null or empty");
|
||||
}
|
||||
final Student student = new Student(name, date);
|
||||
final Student student = new Student(name, birthDate, groupService.findGroup(groupId));
|
||||
return studentRepository.save(student);
|
||||
}
|
||||
|
||||
@ -42,13 +43,14 @@ public class StudentService {
|
||||
}
|
||||
|
||||
@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))) {
|
||||
throw new IllegalArgumentException("Student name or date is null or empty");
|
||||
}
|
||||
final Student currentStudent = findStudent(id);
|
||||
currentStudent.setName(name);
|
||||
currentStudent.setBirthDate(date);
|
||||
currentStudent.setGroup(groupService.findGroup(groupId));
|
||||
return studentRepository.save(currentStudent);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user