Добавлены студенты и добавление их в группу, осталось добавить добавление предметов

This commit is contained in:
ArtemEmelyanov 2023-05-11 21:01:05 +04:00
parent db321f5899
commit 51f3480755
24 changed files with 1658 additions and 144 deletions

View File

@ -15,7 +15,8 @@ repositories {
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2:2.1.210' 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' implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
} }

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@
"name": "vue-project", "name": "vue-project",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"axios": "^1.4.0",
"vue": "^3.2.47", "vue": "^3.2.47",
"vue-router": "^4.1.6" "vue-router": "^4.1.6"
}, },
@ -499,11 +500,45 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz",
"integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" "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": { "node_modules/csstype": {
"version": "2.6.21", "version": "2.6.21",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
"integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" "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": { "node_modules/esbuild": {
"version": "0.17.17", "version": "0.17.17",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz", "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", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" "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": { "node_modules/fsevents": {
"version": "2.3.2", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@ -568,6 +635,25 @@
"sourcemap-codec": "^1.4.8" "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": { "node_modules/nanoid": {
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
@ -617,6 +703,11 @@
"node": "^10 || ^12 || >=14" "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": { "node_modules/rollup": {
"version": "3.20.7", "version": "3.20.7",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.7.tgz", "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", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz",
"integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" "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": { "csstype": {
"version": "2.6.21", "version": "2.6.21",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
"integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" "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": { "esbuild": {
"version": "0.17.17", "version": "0.17.17",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz", "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", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" "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": { "fsevents": {
"version": "2.3.2", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@ -1056,6 +1190,19 @@
"sourcemap-codec": "^1.4.8" "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": { "nanoid": {
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
@ -1076,6 +1223,11 @@
"source-map-js": "^1.0.2" "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": { "rollup": {
"version": "3.20.7", "version": "3.20.7",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.7.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.7.tgz",

View File

@ -8,6 +8,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"axios": "^1.4.0",
"vue": "^3.2.47", "vue": "^3.2.47",
"vue-router": "^4.1.6" "vue-router": "^4.1.6"
}, },

View File

@ -7,7 +7,9 @@
<template> <template>
<Header></Header> <Header></Header>
<div class="container-fluid">
<router-view></router-view> <router-view></router-view>
</div>
</template> </template>
<style> <style>

View File

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

View 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;
}
}

View File

@ -0,0 +1,6 @@
export default class Subject{
constructor(data) {
this.id = data?.id;
this.name = data?.name;
}
}

View File

@ -1,8 +1,114 @@
<template> <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> </template>
<script> <script>
import 'axios';
import axios from "axios";
import Group from "@/models/Group";
export default { 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> </script>
<style> <style>

View File

@ -1,68 +1,142 @@
<template> <template>
<div class="add_student_button"> <div class="container mt-4">
<button id="add_btn" type="submit" data-bs-toggle="modal" data-bs-target="#addModal">Добавить студента</button> <h1 class="text-center mb-4">Student Table</h1>
</div> <button class="btn btn-primary mr-2" @click="openModal(); student.status = `create`">Добавить</button>
<table class="table table-striped table-bordered table-hover"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th>ФИО</th> <th>Имя</th>
<th>Дата рождения</th> <th>Дата рождения</th>
<th>Группа</th> <th>Группа</th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(student, index) in students" :key="index"> <tr v-for="stud in students" :key="stud.id">
<td>{{ student.name }}</td> <td>{{ stud.name }}</td>
<td>{{ student.birthDate }}</td> <td>{{ stud.birthDate }}</td>
<td><button class="buttonUpdate" @click="openModal(student)" data-bs-toggle="modal" data-bs-target="#exampleModal"></button></td> <td>{{ stud.groupName }}</td>
<td><button class="buttonRemove" @click="deleteUser(student)"></button></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> </tr>
</tbody> </tbody>
</table> </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-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title">Добавить студента</h5> <h5 class="modal-title">Студент</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form> <form>
<div class="mb-3"> <div class="form-group">
<label for="name" class="form-label">Имя</label> <label for="name">Имя:</label>
<input type="text" class="form-control" id="name"> <input type="text" class="form-control" id="name" name="name" v-model="student.name">
</div> </div>
<div class="mb-3"> <div class="form-group">
<label for="birthDate" class="form-label">Дата рождения</label> <label for="birthdate">Дата рождения:</label>
<input type="date" class="form-control" id="birthDate"> <input type="date" class="form-control" id="birthdate" name="birthdate" v-model="student.birthDate">
</div> </div>
<div class="mb-3"> <div class="form-group">
<label for="group" class="form-label">Группа</label> <label for="group">Группа:</label>
<input type="text" class="form-control" id="group"> <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> </div>
</form> </form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" 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" data-bs-dismiss="modal">Сохранить</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>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import 'axios';
import axios from "axios";
import Student from "@/models/Student";
export default { export default {
data(){ created() {
this.getStudents();
this.getGroups();
},
mounted() {
const addModal = document.getElementById('editModal');
addModal.addEventListener('shown.bs.modal', function () {
})
},
data() {
return{ return{
name: "", students: [],
birthDate: "" groups: [],
URL: "http://localhost:8080/",
student: new Student(),
} }
}, },
methods:{ methods: {
addUser(){ getStudents(){
fetch('') axios.get(this.URL + "student")
.then(response => response.text()) .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> </script>

View File

@ -1,55 +1,114 @@
<template> <template>
<div class="add_student_button"> <div class="container mt-4">
<button id="add_btn" type="submit" data-bs-toggle="modal" data-bs-target="#addModal">Добавить предмет</button> <h1 class="text-center mb-4">Subject Table</h1>
</div> <button class="btn btn-primary mr-2" @click="openModal(); subject.status = `create`">Добавить</button>
<table class="table table-striped table-bordered table-hover"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
<th>Название предмета</th> <th>Имя</th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(subject, index) in subjects" :key="index"> <tr v-for="sbjct in subjects" :key="sbjct.id">
<td>{{ subject.name }}</td> <td>{{ sbjct.name }}</td>
<td><button class="buttonUpdate" @click="openModal(subject)" data-bs-toggle="modal" data-bs-target="#exampleModal"></button></td> <td>
<td><button class="buttonRemove" @click="deleteUser(subject)"></button></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> </tr>
</tbody> </tbody>
</table> </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-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title">Добавить пердмет</h5> <h5 class="modal-title">Предмет</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form> <form>
<div class="mb-3"> <div class="form-group">
<label for="name" class="form-label">Название</label> <label for="name">Имя:</label>
<input type="text" class="form-control" id="name"> <input type="text" class="form-control" id="name" name="name" v-model="subject.name">
</div> </div>
</form> </form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" 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" data-bs-dismiss="modal">Сохранить</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>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import 'axios';
import axios from "axios";
import Subject from "@/models/Subject";
export default { export default {
data(){ created() {
this.getSubjects();
},
mounted() {
const addModal = document.getElementById('editModal');
addModal.addEventListener('shown.bs.modal', function () {
})
},
data() {
return{ 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(){ 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> </script>

View File

@ -5,7 +5,7 @@ import subjects from "../pages/subjects.vue"
import {createRouter, createWebHistory} from "vue-router" import {createRouter, createWebHistory} from "vue-router"
const routes = [ const routes = [
{path: '/', component: students}, {path: '/students', component: students},
{path: '/groups', component: groups}, {path: '/groups', component: groups},
{path: '/subjects', component: subjects}, {path: '/subjects', component: subjects},
] ]

View File

@ -3,9 +3,12 @@ package ru.IP_LabWorks.IP.University.Contoller.DTO;
import ru.IP_LabWorks.IP.University.Model.Group; import ru.IP_LabWorks.IP.University.Model.Group;
public class GroupDTO { public class GroupDTO {
private final long id; private long id;
private final String name; private String name;
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();
@ -18,4 +21,12 @@ public class GroupDTO {
public String getName(){ public String getName(){
return name; return name;
} }
public void setId(long id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
} }

View File

@ -1,20 +1,32 @@
package ru.IP_LabWorks.IP.University.Contoller.DTO; 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 ru.IP_LabWorks.IP.University.Model.Student;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class StudentDTO { public class StudentDTO {
private final long id; private long id;
private final String name; private String name;
private final LocalDate birthDate; private LocalDate birthDate;
private long groupId;
private String groupName;
public StudentDTO() {
}
public StudentDTO(Student student) { public StudentDTO(Student student) {
this.id = student.getId(); this.id = student.getId();
this.name = student.getName(); this.name = student.getName();
this.birthDate = student.getBirthDate(); this.birthDate = student.getBirthDate();
this.groupName = student.getGroup().getName();
this.groupId = student.getGroup().getId();
} }
public String getGroupName() {
return groupName;
}
public Long getId(){ public Long getId(){
return id; return id;
} }
@ -26,4 +38,24 @@ public class StudentDTO {
public LocalDate getBirthDate(){ public LocalDate getBirthDate(){
return birthDate; 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"));
}
} }

View File

@ -3,9 +3,12 @@ package ru.IP_LabWorks.IP.University.Contoller.DTO;
import ru.IP_LabWorks.IP.University.Model.Subject; import ru.IP_LabWorks.IP.University.Model.Subject;
public class SubjectDTO { public class SubjectDTO {
private final long id; private long id;
private final String name; private String name;
public SubjectDTO(){
}
public SubjectDTO(Subject subject){ public SubjectDTO(Subject subject){
this.id = subject.getId(); this.id = subject.getId();
this.name = subject.getName(); this.name = subject.getName();

View File

@ -1,7 +1,9 @@
package ru.IP_LabWorks.IP.University.Contoller.REST; package ru.IP_LabWorks.IP.University.Contoller.REST;
import jakarta.validation.Valid;
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.Service.GroupService; import ru.IP_LabWorks.IP.University.Service.GroupService;
import java.util.List; import java.util.List;
@ -28,18 +30,23 @@ public class GroupController {
} }
@PostMapping @PostMapping
public GroupDTO createGroup(@RequestParam("name") String name){ public GroupDTO createGroup(@RequestBody @Valid GroupDTO groupDTO){
return new GroupDTO(groupService.addGroup(name)); return new GroupDTO(groupService.addGroup(groupDTO.getName()));
} }
@PutMapping("/{id}") @PutMapping("/{id}")
public GroupDTO updateGroup(@PathVariable Long id, public GroupDTO updateGroup(@PathVariable Long id, @RequestBody @Valid GroupDTO groupDTO){
@RequestParam("name") String name){ return new GroupDTO(groupService.updateGroup(id, groupDTO.getName()));
return new GroupDTO(groupService.updateGroup(id, name));
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public GroupDTO deleteGroup(@PathVariable Long id){ public GroupDTO deleteGroup(@PathVariable Long id){
return new GroupDTO(groupService.deleteGroup(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));
// }
} }

View File

@ -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.Contoller.DTO.StudentDTO;
import ru.IP_LabWorks.IP.University.Service.StudentService; import ru.IP_LabWorks.IP.University.Service.StudentService;
import jakarta.validation.Valid;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
@ -29,16 +30,13 @@ public class StudentController {
} }
@PostMapping @PostMapping
public StudentDTO createStudent(@RequestParam("name") String name, public StudentDTO createStudent(@RequestBody @Valid StudentDTO studentDTO){
@RequestParam("birthDate")LocalDate birthDate){ return new StudentDTO(studentService.addStudent(studentDTO.getName(), studentDTO.getBirthDate(), studentDTO.getGroupId()));
return new StudentDTO(studentService.addStudent(name, birthDate));
} }
@PutMapping("/{id}") @PutMapping("/{id}")
public StudentDTO updateStudent(@PathVariable Long id, public StudentDTO updateStudent(@PathVariable Long id, @RequestBody @Valid StudentDTO studentDTO) {
@RequestParam("name") String name, return new StudentDTO(studentService.updateStudent(id, studentDTO.getName(), studentDTO.getBirthDate(), studentDTO.getGroupId()));
@RequestParam("birthDate") LocalDate birthDate){
return new StudentDTO(studentService.updateStudent(id, name, birthDate));
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -1,5 +1,6 @@
package ru.IP_LabWorks.IP.University.Contoller.REST; package ru.IP_LabWorks.IP.University.Contoller.REST;
import jakarta.validation.Valid;
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.SubjectDTO; import ru.IP_LabWorks.IP.University.Contoller.DTO.SubjectDTO;
@ -30,14 +31,13 @@ public class SubjectController {
} }
@PostMapping @PostMapping
public SubjectDTO createSubject(@RequestParam("name") String name){ public SubjectDTO createSubject(@RequestBody @Valid SubjectDTO subjectDTO){
return new SubjectDTO(subjectService.addSubject(name)); return new SubjectDTO(subjectService.addSubject(subjectDTO.getName()));
} }
@PutMapping("/{id}") @PutMapping("/{id}")
public SubjectDTO updateSubject(@PathVariable Long id, public SubjectDTO updateSubject(@PathVariable Long id, @RequestBody @Valid SubjectDTO subjectDTO){
@RequestParam("name") String name){ return new SubjectDTO(subjectService.updateSubject(id,subjectDTO.getName()));
return new SubjectDTO(subjectService.updateSubject(id, name));
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View File

@ -1,5 +1,6 @@
package ru.IP_LabWorks.IP.University.Model; package ru.IP_LabWorks.IP.University.Model;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.Cascade; import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDelete;
@ -18,6 +19,7 @@ public class Group {
private Long id; private Long id;
private String name; private String name;
@JsonManagedReference
@OneToMany(orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "group") @OneToMany(orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "group")
@OnDelete(action = OnDeleteAction.CASCADE) @OnDelete(action = OnDeleteAction.CASCADE)
private List<Student> students; private List<Student> students;

View File

@ -1,4 +1,5 @@
package ru.IP_LabWorks.IP.University.Model; package ru.IP_LabWorks.IP.University.Model;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.OnDeleteAction;
@ -16,6 +17,7 @@ public class Student {
private String name; private String name;
private LocalDate birthDate; private LocalDate birthDate;
@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "group_id") @JoinColumn(name = "group_id")
private Group group; private Group group;
@ -23,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; }
@ -69,9 +72,14 @@ public class Student {
} }
public void setGroup(Group group) { public void setGroup(Group group) {
if (this.group != group) {
if (this.group != null) {
this.group.getStudents().remove(this);
}
this.group = group; this.group = group;
if(!group.getStudents().contains(this)){ if (group != null && !group.getStudents().contains(this)) {
group.getStudents().add(this); group.getStudents().add(this);
} }
} }
}
} }

View File

@ -7,6 +7,7 @@ import org.springframework.util.StringUtils;
import ru.IP_LabWorks.IP.University.Model.Group; 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.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.awt.desktop.OpenFilesEvent; import java.awt.desktop.OpenFilesEvent;
@ -63,16 +64,16 @@ public class GroupService {
groupRepository.deleteAll(); groupRepository.deleteAll();
} }
// @Transactional /* @Transactional
// public void addStudentToGroup(Long groupId, Long studentId) { public Group addStudentToGroup(Long groupId, Long studentId) {
// Group group = findGroup(groupId); Group group = findGroup(groupId);
// Student student = em.find(Student.class, studentId); Student student = studentService.findStudent(studentId);
// if (group == null || student == null) { if (group == null || student == null) {
// throw new EntityNotFoundException("Group or Student not found"); throw new EntityNotFoundException("Group or Student not found");
// } }
// student.setGroup(group); group.setStudent(student);
// em.merge(student); return group;
// } }*/
// //
// @Transactional // @Transactional
// public void removeStudentFromGroup(Long groupId, Long studentId) { // public void removeStudentFromGroup(Long groupId, Long studentId) {

View File

@ -1,6 +1,5 @@
package ru.IP_LabWorks.IP.University.Service; package ru.IP_LabWorks.IP.University.Service;
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;
@ -16,17 +15,19 @@ import java.util.Optional;
@Service @Service
public class StudentService { public class StudentService {
private final StudentRepository studentRepository; private final StudentRepository studentRepository;
private final GroupService groupService;
public StudentService(StudentRepository studentRepository) { public StudentService(StudentRepository studentRepository, GroupService groupService) {
this.studentRepository = studentRepository; this.studentRepository = studentRepository;
this.groupService = groupService;
} }
@Transactional @Transactional
public Student addStudent(String name, LocalDate date){ public Student addStudent(String name, LocalDate birthDate, Long groupId){
if (!StringUtils.hasText(name) || !StringUtils.hasText(String.valueOf(date))) { 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, date); final Student student = new Student(name, birthDate, groupService.findGroup(groupId));
return studentRepository.save(student); return studentRepository.save(student);
} }
@ -42,13 +43,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);
} }