Lab 4 - доп.задание

This commit is contained in:
AnnZhimol 2023-05-01 22:29:41 +04:00
parent f9c5202f6b
commit ec634ba472
22 changed files with 368 additions and 14 deletions

View File

@ -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: <DrivingSchools />, label: 'Автошколы' },
{ path: '/students', element: <Students />, label: 'Студенты' },
{ path: '/categories', element: <Categories />, label: 'Категории' },
{ path: '/studcategory', element: <CountStudInCategory />, label: 'Количество студентов в категории' },
{ path: '/drivingSchool/:id', element: <OneDrivingSchool />},
];
const links = routes.filter(route => route.hasOwnProperty('label'));

View File

@ -0,0 +1,12 @@
import TableForGroup from "./commons/TableForGroup.jsx";
// это абстрактный компонент для всех справочников
export default function CatalogForGroup(props) {
return <>
<div>{props.name}</div>
<TableForGroup
headers={props.headers}
items={props.items}
/></>
}

View File

@ -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 <>
<div>{props.name}</div>
<Button variant="success" onClick={handleAdd}>Добавить</Button>
<TableSC
headers={props.headers}
items={props.items}
onEdit={handleEdit}
onDelete={handleRemove}
/>
<ModalForm
show={show}
onClose={handleClose}
modalTitle={modalTitle}
// onSubmit={submitForm}
onChange={changeData}
form={props.form}
/></>
}

View File

@ -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) {
</Form>
return <div className="container-lg pt-5 min-vh-100">
<Catalog name={nameCatalog}
<CatalogSC name={nameCatalog}
headers={headers}
items={items}
onAdd={handleAdd}
@ -103,6 +103,6 @@ export default function Categories(props) {
onClose={reset}
onBtnAdd={reset}
form={form}>
</Catalog>
</CatalogSC>
</div>
}

View File

@ -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 <div className="container-lg pt-5 min-vh-100">
<CatalogForGroup name={nameCatalog}
headers={headers}
items={items}>
</CatalogForGroup>
</div>
}

View File

@ -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) {
</Form>
return <div className="container-lg pt-5 min-vh-100">
<Catalog name={nameCatalog}
<CatalogSC name={nameCatalog}
headers={headers}
items={items}
onAdd={handleAdd}
@ -110,6 +110,6 @@ export default function Students(props) {
onClose={reset}
onBtnAdd={reset}
form={form}>
</Catalog>
</CatalogSC>
</div>
}

View File

@ -0,0 +1,8 @@
export default function ItemTableForGroup(props) {
return <tr key={props.item.id}>
{
props.headers.map((header) => <td key={`${header.name}_${props.item.id}`}>{props.item[header.name]}</td>)
}
</tr>
}

View File

@ -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 <tr key={props.item.id}>
{
props.headers.map((header) => <td key={`${header.name}_${props.item.id}`}>{props.item[header.name]}</td>)
}
{props.isOnlyView || <td key={`controls_${props.item.id}`}>
<Button variant="btn btn-outline-primary" onClick={edit}>Редактировать</Button>
<Button variant="btn btn-outline-danger" onClick={remove}>Удалить</Button></td>}
</tr>
}

View File

@ -0,0 +1,26 @@
import ItemTableForGroup from './ItemTableForGroup';
export default function TableForGroup(props) {
return <div >
<table className={`table table-hover`}>
<thead>
<tr>
{
props.headers.map((header) => <th key={header.name}>{header.label}</th>)
}
</tr>
</thead>
<tbody>
{
props.items.map((item, index) =>
<ItemTableForGroup
key={index}
headers={props.headers}
item={item}
isOnlyView={props.isOnlyView}/>)
}
</tbody>
</table>
</div>
}

View File

@ -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 <div >
<table className={`table table-hover`}>
<thead>
<tr>
{
props.headers.map((header) => <th key={header.name}>{header.label}</th>)
}
{props.isOnlyView || <th key='controls'>Элементы управления</th>}
</tr>
</thead>
<tbody>
{
props.items.map((item, index) =>
<ItemTableSC
key={index}
headers={props.headers}
item={item}
onDelete={remove}
onEdit={edit}
isOnlyView={props.isOnlyView}/>)
}
</tbody>
</table>
</div>
}

View File

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

View File

@ -0,0 +1,7 @@
export default class GroupedStudAndCategoryDto {
constructor(data) {
this.Id = data?.Id;
this.categoryName = data?.categoryName;
this.studentsCount = data?.studentsCount;
}
}

View File

@ -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<GroupedStudAndCategoryDto> getGroupedStudAndCategory(){
return categoryStudentService.getGroupedStudAndCategory();
}
}

View File

@ -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<Category, Long> {

View File

@ -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<StudentCategories, Long> {
Optional<StudentCategories> 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<GroupedStudAndCategoryDto> getGroupedStudAndCategory();
}

View File

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

View File

@ -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<Student> students = new ArrayList<>();
private Set<Student> students = new HashSet<>();
public Category() {
}
@ -37,11 +35,11 @@ public class Category {
return Id;
}
public List<Student> getStudents() {
public Set<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
public void setStudents(Set<Student> students) {
this.students = students;
}

View File

@ -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<Category> categories = new HashSet<>();

View File

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

View File

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

View File

@ -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();
}
}

View File

@ -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<GroupedStudAndCategoryDto> getGroupedStudAndCategory() {
return studentCategoriesRepository.getGroupedStudAndCategory();
}
}