From ec634ba472e8e1d50a62147cf4949ca2c9194797 Mon Sep 17 00:00:00 2001 From: AnnZhimol Date: Mon, 1 May 2023 22:29:41 +0400 Subject: [PATCH] =?UTF-8?q?Lab=204=20-=20=D0=B4=D0=BE=D0=BF.=D0=B7=D0=B0?= =?UTF-8?q?=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/App.js | 3 ++ front/src/components/CatalogForGroup.jsx | 12 +++++ front/src/components/CatalogSC.jsx | 49 +++++++++++++++++++ front/src/components/Categories.jsx | 6 +-- front/src/components/CountStudInCategory.jsx | 37 ++++++++++++++ front/src/components/Students.jsx | 6 +-- .../components/commons/ItemTableForGroup.jsx | 8 +++ front/src/components/commons/ItemTableSC.jsx | 18 +++++++ .../src/components/commons/TableForGroup.jsx | 26 ++++++++++ front/src/components/commons/TableSC.jsx | 35 +++++++++++++ front/src/models/Category.js | 2 +- front/src/models/GroupedStudAndCategoryDto.js | 7 +++ .../controller/CategoryStudentController.java | 26 ++++++++++ .../is/cbapp/dao/CategoryRepository.java | 3 ++ .../dao/StudentCategoriesRepository.java | 19 +++++++ .../cbapp/dto/GroupedStudAndCategoryDto.java | 27 ++++++++++ .../ru/ulstu/is/cbapp/models/Category.java | 10 ++-- .../ru/ulstu/is/cbapp/models/Student.java | 3 ++ .../is/cbapp/models/StudentCategories.java | 36 ++++++++++++++ .../is/cbapp/models/StudentCategoriesId.java | 24 +++++++++ .../is/cbapp/service/CategoryService.java | 2 +- .../cbapp/service/CategoryStudentService.java | 23 +++++++++ 22 files changed, 368 insertions(+), 14 deletions(-) create mode 100644 front/src/components/CatalogForGroup.jsx create mode 100644 front/src/components/CatalogSC.jsx create mode 100644 front/src/components/CountStudInCategory.jsx create mode 100644 front/src/components/commons/ItemTableForGroup.jsx create mode 100644 front/src/components/commons/ItemTableSC.jsx create mode 100644 front/src/components/commons/TableForGroup.jsx create mode 100644 front/src/components/commons/TableSC.jsx create mode 100644 front/src/models/GroupedStudAndCategoryDto.js create mode 100644 src/main/java/ru/ulstu/is/cbapp/controller/CategoryStudentController.java create mode 100644 src/main/java/ru/ulstu/is/cbapp/dao/StudentCategoriesRepository.java create mode 100644 src/main/java/ru/ulstu/is/cbapp/dto/GroupedStudAndCategoryDto.java create mode 100644 src/main/java/ru/ulstu/is/cbapp/models/StudentCategories.java create mode 100644 src/main/java/ru/ulstu/is/cbapp/models/StudentCategoriesId.java create mode 100644 src/main/java/ru/ulstu/is/cbapp/service/CategoryStudentService.java diff --git a/front/src/App.js b/front/src/App.js index 97904c7..28a7eab 100644 --- a/front/src/App.js +++ b/front/src/App.js @@ -6,6 +6,8 @@ import 'bootstrap/dist/css/bootstrap.min.css'; import DrivingSchools from './components/DrivingSchools.jsx'; import Categories from './components/Categories.jsx'; import OneDrivingSchool from './components/OneDrivingSchool.jsx'; +import CountStudInCategory from './components/CountStudInCategory.jsx'; + function Router(props) { return useRoutes(props.rootRoute); } @@ -17,6 +19,7 @@ function Router(props) { { path: '/drivingSchools', element: , label: 'Автошколы' }, { path: '/students', element: , label: 'Студенты' }, { path: '/categories', element: , label: 'Категории' }, + { path: '/studcategory', element: , label: 'Количество студентов в категории' }, { path: '/drivingSchool/:id', element: }, ]; const links = routes.filter(route => route.hasOwnProperty('label')); diff --git a/front/src/components/CatalogForGroup.jsx b/front/src/components/CatalogForGroup.jsx new file mode 100644 index 0000000..629ab97 --- /dev/null +++ b/front/src/components/CatalogForGroup.jsx @@ -0,0 +1,12 @@ +import TableForGroup from "./commons/TableForGroup.jsx"; +// это абстрактный компонент для всех справочников +export default function CatalogForGroup(props) { + + return <> +
{props.name}
+ + +} \ No newline at end of file diff --git a/front/src/components/CatalogSC.jsx b/front/src/components/CatalogSC.jsx new file mode 100644 index 0000000..972857f --- /dev/null +++ b/front/src/components/CatalogSC.jsx @@ -0,0 +1,49 @@ +import Button from 'react-bootstrap/Button'; +import TableSC from "./commons/TableSC.jsx"; +import { useState} from 'react'; +import ModalForm from './commons/ModalForm.jsx'; +// это абстрактный компонент для всех справочников +export default function CatalogSC(props) { + const [show, setShow] = useState(false); + const [modalTitle, setModalTitle] = useState(""); + + const handleClose = () => setShow(false); + const handleShow = () => setShow(true); + + + function handleAdd() { + setModalTitle("Добавление"); + props.onBtnAdd(); + handleShow(); + } + function handleEdit(itemId) { + setModalTitle("Редактирование"); + props.onEdit(itemId); + handleShow(); + } + function handleRemove(item) { + props.onDelete(item); + } + function changeData(event) { + props.onFormChanged(event); + } + + return <> +
{props.name}
+ + + + +} \ No newline at end of file diff --git a/front/src/components/Categories.jsx b/front/src/components/Categories.jsx index bba6d16..57e701e 100644 --- a/front/src/components/Categories.jsx +++ b/front/src/components/Categories.jsx @@ -3,7 +3,7 @@ import Form from 'react-bootstrap/Form'; import Button from 'react-bootstrap/Button'; import { useState, useEffect } from 'react'; import DataService from '../services/DataService'; -import Catalog from "./Catalog.jsx"; +import CatalogSC from "./CatalogSC.jsx"; export default function Categories(props) { @@ -94,7 +94,7 @@ export default function Categories(props) { return
- - +
} \ No newline at end of file diff --git a/front/src/components/CountStudInCategory.jsx b/front/src/components/CountStudInCategory.jsx new file mode 100644 index 0000000..418cd60 --- /dev/null +++ b/front/src/components/CountStudInCategory.jsx @@ -0,0 +1,37 @@ +import { useState, useEffect } from 'react'; +import DataService from '../services/DataService'; +import CatalogForGroup from "./CatalogForGroup.jsx"; +import { useNavigate } from "react-router-dom"; +import GroupedStudAndCategoryDto from "../models/GroupedStudAndCategoryDto"; + +export default function CountStudInCategory(props) { + + const headers = [ + {name: 'categoryName', label: "Название"}, + {name: 'studentsCount', label: "Студенты"}, + ]; + + const nameCatalog = "Количество студентов в категории"; + + const url = '/categoryStudent/groupbycategory'; + + const [items, setItems] = useState([]); + + useEffect(() => { + loadItems(); + }, []); + + function loadItems() { + DataService.readAll(url, (data) => new GroupedStudAndCategoryDto(data)) + .then(data => setItems(data)); + } + + return
+ + +
+ + +} \ No newline at end of file diff --git a/front/src/components/Students.jsx b/front/src/components/Students.jsx index c13ab4e..b2c36f3 100644 --- a/front/src/components/Students.jsx +++ b/front/src/components/Students.jsx @@ -3,7 +3,7 @@ import Form from 'react-bootstrap/Form'; import Button from 'react-bootstrap/Button'; import { useState, useEffect } from 'react'; import DataService from '../services/DataService'; -import Catalog from "./Catalog.jsx"; +import CatalogSC from "./CatalogSC.jsx"; export default function Students(props) { const headers = [ {name: 'surname', label: "Фамилия"}, @@ -101,7 +101,7 @@ export default function Students(props) { return
- - +
} \ No newline at end of file diff --git a/front/src/components/commons/ItemTableForGroup.jsx b/front/src/components/commons/ItemTableForGroup.jsx new file mode 100644 index 0000000..55a04cb --- /dev/null +++ b/front/src/components/commons/ItemTableForGroup.jsx @@ -0,0 +1,8 @@ +export default function ItemTableForGroup(props) { + + return + { + props.headers.map((header) => {props.item[header.name]}) + } + +} \ No newline at end of file diff --git a/front/src/components/commons/ItemTableSC.jsx b/front/src/components/commons/ItemTableSC.jsx new file mode 100644 index 0000000..4fec8bb --- /dev/null +++ b/front/src/components/commons/ItemTableSC.jsx @@ -0,0 +1,18 @@ +import Button from 'react-bootstrap/Button'; +export default function ItemTableSC(props) { + function edit() { + props.onEdit(props.item.id); + } + function remove() { + props.onDelete(props.item.id); + } + + return + { + props.headers.map((header) => {props.item[header.name]}) + } + {props.isOnlyView || + + } + +} \ No newline at end of file diff --git a/front/src/components/commons/TableForGroup.jsx b/front/src/components/commons/TableForGroup.jsx new file mode 100644 index 0000000..bbfd7df --- /dev/null +++ b/front/src/components/commons/TableForGroup.jsx @@ -0,0 +1,26 @@ +import ItemTableForGroup from './ItemTableForGroup'; + +export default function TableForGroup(props) { + + return
+ + + + { + props.headers.map((header) => ) + } + + + + { + props.items.map((item, index) => + ) + } + +
{header.label}
+
+} \ No newline at end of file diff --git a/front/src/components/commons/TableSC.jsx b/front/src/components/commons/TableSC.jsx new file mode 100644 index 0000000..20c8127 --- /dev/null +++ b/front/src/components/commons/TableSC.jsx @@ -0,0 +1,35 @@ +import ItemTableSC from './ItemTableSC'; +export default function TableSC(props) { + function edit(itemId) { + props.onEdit(itemId) + } + function remove(itemId) { + props.onDelete(itemId); + } + + return
+ + + + { + props.headers.map((header) => ) + } + {props.isOnlyView || } + + + + + { + props.items.map((item, index) => + ) + } + +
{header.label}Элементы управления
+
+} \ No newline at end of file diff --git a/front/src/models/Category.js b/front/src/models/Category.js index 3335ab2..3a46c45 100644 --- a/front/src/models/Category.js +++ b/front/src/models/Category.js @@ -1,6 +1,6 @@ export default class Category { constructor(data) { this.id = data?.id; - this.name = data?.name || ''; + this.name = data?.name || ''; } } \ No newline at end of file diff --git a/front/src/models/GroupedStudAndCategoryDto.js b/front/src/models/GroupedStudAndCategoryDto.js new file mode 100644 index 0000000..5e101fb --- /dev/null +++ b/front/src/models/GroupedStudAndCategoryDto.js @@ -0,0 +1,7 @@ +export default class GroupedStudAndCategoryDto { + constructor(data) { + this.Id = data?.Id; + this.categoryName = data?.categoryName; + this.studentsCount = data?.studentsCount; + } +} \ No newline at end of file diff --git a/src/main/java/ru/ulstu/is/cbapp/controller/CategoryStudentController.java b/src/main/java/ru/ulstu/is/cbapp/controller/CategoryStudentController.java new file mode 100644 index 0000000..b140bc8 --- /dev/null +++ b/src/main/java/ru/ulstu/is/cbapp/controller/CategoryStudentController.java @@ -0,0 +1,26 @@ +package ru.ulstu.is.cbapp.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.ulstu.is.cbapp.dto.GroupedStudAndCategoryDto; +import ru.ulstu.is.cbapp.service.CategoryService; +import ru.ulstu.is.cbapp.service.CategoryStudentService; + +import java.util.List; + +@RestController +@RequestMapping("/categoryStudent") +public class CategoryStudentController { + + private CategoryStudentService categoryStudentService; + + public CategoryStudentController(CategoryStudentService categoryStudentService) { + this.categoryStudentService = categoryStudentService; + } + + @GetMapping("/groupbycategory") + public List getGroupedStudAndCategory(){ + return categoryStudentService.getGroupedStudAndCategory(); + } +} diff --git a/src/main/java/ru/ulstu/is/cbapp/dao/CategoryRepository.java b/src/main/java/ru/ulstu/is/cbapp/dao/CategoryRepository.java index 3462b6d..a9e4567 100644 --- a/src/main/java/ru/ulstu/is/cbapp/dao/CategoryRepository.java +++ b/src/main/java/ru/ulstu/is/cbapp/dao/CategoryRepository.java @@ -1,8 +1,11 @@ package ru.ulstu.is.cbapp.dao; +import org.springframework.data.jpa.repository.Query; +import ru.ulstu.is.cbapp.dto.GroupedStudAndCategoryDto; import ru.ulstu.is.cbapp.models.Category; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; import java.util.Optional; public interface CategoryRepository extends JpaRepository { diff --git a/src/main/java/ru/ulstu/is/cbapp/dao/StudentCategoriesRepository.java b/src/main/java/ru/ulstu/is/cbapp/dao/StudentCategoriesRepository.java new file mode 100644 index 0000000..f619ae3 --- /dev/null +++ b/src/main/java/ru/ulstu/is/cbapp/dao/StudentCategoriesRepository.java @@ -0,0 +1,19 @@ +package ru.ulstu.is.cbapp.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import ru.ulstu.is.cbapp.dto.GroupedStudAndCategoryDto; +import ru.ulstu.is.cbapp.models.StudentCategories; + +import java.util.List; +import java.util.Optional; + +public interface StudentCategoriesRepository extends JpaRepository { + + Optional findById(Long id); + + @Query("SELECT new ru.ulstu.is.cbapp.dto.GroupedStudAndCategoryDto(cs.category.name,COUNT(cs.student.id))"+ + "FROM StudentCategories cs "+ + "group by cs.category.name") + List getGroupedStudAndCategory(); +} diff --git a/src/main/java/ru/ulstu/is/cbapp/dto/GroupedStudAndCategoryDto.java b/src/main/java/ru/ulstu/is/cbapp/dto/GroupedStudAndCategoryDto.java new file mode 100644 index 0000000..9670337 --- /dev/null +++ b/src/main/java/ru/ulstu/is/cbapp/dto/GroupedStudAndCategoryDto.java @@ -0,0 +1,27 @@ +package ru.ulstu.is.cbapp.dto; + +public class GroupedStudAndCategoryDto { + private String categoryName; + private Long StudentsCount; + + public GroupedStudAndCategoryDto(String categoryName, Long StudentsCount){ + this.categoryName=categoryName; + this.StudentsCount=StudentsCount; + } + + public String getCategoryName() { + return categoryName; + } + + public void setCategoryId(String categoryName) { + this.categoryName = categoryName; + } + + public Long getStudentsCount() { + return StudentsCount; + } + + public void setStudentsCount(Long studentsCount) { + StudentsCount = studentsCount; + } +} diff --git a/src/main/java/ru/ulstu/is/cbapp/models/Category.java b/src/main/java/ru/ulstu/is/cbapp/models/Category.java index d8a3f2f..d8cbed8 100644 --- a/src/main/java/ru/ulstu/is/cbapp/models/Category.java +++ b/src/main/java/ru/ulstu/is/cbapp/models/Category.java @@ -2,9 +2,7 @@ package ru.ulstu.is.cbapp.models; import jakarta.persistence.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; @Entity public class Category { @@ -16,7 +14,7 @@ public class Category { //mappedBy - атрибут, указывающий, что классом-владельцем отношений является другой класс @ManyToMany(mappedBy = "categories", cascade = {CascadeType.REMOVE}, fetch = FetchType.EAGER) - private List students = new ArrayList<>(); + private Set students = new HashSet<>(); public Category() { } @@ -37,11 +35,11 @@ public class Category { return Id; } - public List getStudents() { + public Set getStudents() { return students; } - public void setStudents(List students) { + public void setStudents(Set students) { this.students = students; } diff --git a/src/main/java/ru/ulstu/is/cbapp/models/Student.java b/src/main/java/ru/ulstu/is/cbapp/models/Student.java index 720fc7c..694d72c 100644 --- a/src/main/java/ru/ulstu/is/cbapp/models/Student.java +++ b/src/main/java/ru/ulstu/is/cbapp/models/Student.java @@ -17,6 +17,9 @@ public class Student { private DrivingSchool drivingSchool; @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + //@JoinTable(name="CATEGORY_STUDENT", + //joinColumns = {@JoinColumn(name="student_id")}, + //inverseJoinColumns = {@JoinColumn(name="category_id")}) private Set categories = new HashSet<>(); diff --git a/src/main/java/ru/ulstu/is/cbapp/models/StudentCategories.java b/src/main/java/ru/ulstu/is/cbapp/models/StudentCategories.java new file mode 100644 index 0000000..ce3794d --- /dev/null +++ b/src/main/java/ru/ulstu/is/cbapp/models/StudentCategories.java @@ -0,0 +1,36 @@ +package ru.ulstu.is.cbapp.models; + +import jakarta.persistence.*; + +@Entity +@Table(name="student_categories") +@IdClass(StudentCategoriesId.class) +public class StudentCategories { + + public Student getStudent() { + return student; + } + + public void setStudent(Student student) { + this.student = student; + } + + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + @Id + @ManyToOne + @JoinColumn(name="students_id") + private Student student; + + @Id + @ManyToOne + @JoinColumn(name="categories_id") + private Category category; + +} diff --git a/src/main/java/ru/ulstu/is/cbapp/models/StudentCategoriesId.java b/src/main/java/ru/ulstu/is/cbapp/models/StudentCategoriesId.java new file mode 100644 index 0000000..db72e2e --- /dev/null +++ b/src/main/java/ru/ulstu/is/cbapp/models/StudentCategoriesId.java @@ -0,0 +1,24 @@ +package ru.ulstu.is.cbapp.models; + +import java.io.Serializable; + +public class StudentCategoriesId implements Serializable { + private Long student; + private Long category; + + public Long getStudent() { + return student; + } + + public void setStudent(Long student) { + this.student = student; + } + + public Long getCategory() { + return category; + } + + public void setCategory(Long category) { + this.category = category; + } +} diff --git a/src/main/java/ru/ulstu/is/cbapp/service/CategoryService.java b/src/main/java/ru/ulstu/is/cbapp/service/CategoryService.java index 62430c3..77a605a 100644 --- a/src/main/java/ru/ulstu/is/cbapp/service/CategoryService.java +++ b/src/main/java/ru/ulstu/is/cbapp/service/CategoryService.java @@ -1,6 +1,7 @@ package ru.ulstu.is.cbapp.service; import ru.ulstu.is.cbapp.dao.CategoryRepository; +import ru.ulstu.is.cbapp.dto.GroupedStudAndCategoryDto; import ru.ulstu.is.cbapp.models.Category; import jakarta.persistence.EntityNotFoundException; import org.springframework.stereotype.Service; @@ -65,5 +66,4 @@ public class CategoryService { categoryRepository.deleteAll(); } - } diff --git a/src/main/java/ru/ulstu/is/cbapp/service/CategoryStudentService.java b/src/main/java/ru/ulstu/is/cbapp/service/CategoryStudentService.java new file mode 100644 index 0000000..46eff4a --- /dev/null +++ b/src/main/java/ru/ulstu/is/cbapp/service/CategoryStudentService.java @@ -0,0 +1,23 @@ +package ru.ulstu.is.cbapp.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.ulstu.is.cbapp.dao.StudentCategoriesRepository; +import ru.ulstu.is.cbapp.dto.GroupedStudAndCategoryDto; + +import java.util.List; + +@Service +public class CategoryStudentService { + + private StudentCategoriesRepository studentCategoriesRepository; + + public CategoryStudentService(StudentCategoriesRepository studentCategoriesRepository) { + this.studentCategoriesRepository = studentCategoriesRepository; + } + + @Transactional(readOnly = true) + public List getGroupedStudAndCategory() { + return studentCategoriesRepository.getGroupedStudAndCategory(); + } +}