4 lab full

This commit is contained in:
parap 2023-04-30 23:07:58 +04:00
parent 4d916bdfe6
commit 651d1a95f4
57 changed files with 21803 additions and 417 deletions

BIN
data.mv.db Normal file

Binary file not shown.

8235
data.trace.db Normal file

File diff suppressed because it is too large Load Diff

23
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

0
frontend/README.md Normal file
View File

26
frontend/data.json Normal file
View File

@ -0,0 +1,26 @@
{
"films": [
{
"id": 1,
"name": "film super",
"genre": "Комедия"
}
],
"genres": [
{
"name": "",
"genre": "Драма",
"id": 1
},
{
"name": "",
"genre": "Комедия",
"id": 2
},
{
"name": "",
"genre": "Трилер",
"id": 3
}
]
}

View File

@ -1,46 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./node_modules/bootstrap/dist/css/bootstrap.min.css">
<title>Document</title>
</head>
<body>
<form class="" id="form">
<h2>Калькулятор</h2>
<div class="container row">
<div class="form-group col-3">
<label for="formGroupExampleInput">X</label>
<input name="x" class="form-control col-3" placeholder="Первый аргумент">
</div>
<div class="form-group col-3">
<label for="formGroupExampleInput">Оператор</label>
<select name="selected" id="inputState" class="form-control">
<option selected>+</option>
<option>-</option>
<option>*</option>
<option>/</option>
</select>
<select name="type" id="inputState" class="form-control">
<option selected>Int</option>
<option>String</option>
<option>Array</option>
</select>
</div>
<div class="form-group col-3">
<label for="formGroupExampleInput2">Y</label>
<input name="y" type="number" class="form-control col-3" placeholder="Второй аргумент">
</div>
</div>
<button type="submit" class="btn btn-primary m-3">Посчитать</button>
</form>
<h2 class="text" id="res"></h2>
<script src="./node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="../js/script.js"></script>
</body>
</html>

View File

@ -1,40 +0,0 @@
let form = document.getElementById("form");
let info = document.getElementById("res");
form.onsubmit = async (e) => {
e.preventDefault();
if(form.x.value === "") return;
if(form.y.value === "") return;
let index = form.selected.selectedIndex;
let indexType = form.type.selectedIndex;
let op = form.selected.options[index].textContent;
let type = form.type.options[indexType].textContent;
let res = "";
switch(op) {
case "+":
res = await fetch(`http://localhost:8080/sum${type}?x=${form.x.value}&y=${form.y.value}`)
res = await res.text();
break;
case "-":
res = await fetch(`http://localhost:8080/diff${type}?x=${form.x.value}&y=${form.y.value}`)
res = await res.text();
break;
case "*":
res = await fetch(`http://localhost:8080/multiple${type}?x=${form.x.value}&y=${form.y.value}`)
res = await res.text();
break;
case "/":
if(form.y.value == 0) return;
res = await fetch(`http://localhost:8080/divide${type}?x=${form.x.value}&y=${form.y.value}`)
res = await res.text();
break;
}
info.textContent = res;
}

12613
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,43 @@
{
"name": "frontend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "http-server -p 3000 -c-1 -o ./"
},
"author": "",
"license": "ISC",
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"bootstrap": "^5.2.3",
"http-server": "^14.1.1"
"json-server": "^0.17.1",
"npm-run-all": "^4.1.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.4.5",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"fake-server": "json-server data.json -p 8079",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js" integrity="sha384-cuYeSxntonz0PPNlHhBs68uyIAVpIIOZZ5JqeqvYYIcEL727kskC66kF92t6Xl2V" crossorigin="anonymous"></script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

0
frontend/src/App.css Normal file
View File

45
frontend/src/App.js Normal file
View File

@ -0,0 +1,45 @@
import './App.css';
import {BrowserRouter, Routes, Route} from "react-router-dom";
import Header from './components/common/Header';
import Home from './components/pages/Home';
import Films from './components/pages/Films';
import Film from './components/pages/Film';
import Contacts from './components/pages/Contacts';
import Catalogs from './components/pages/Catalogs';
import CatalogFilms from './components/catalogs/CatalogFilms';
import CatalogGenres from './components/catalogs/CatalogGenres';
import Reports from './components/pages/Reports';
import ReportsFilms from './components/reports/ReportsFilms';
const links = [
{id: 1, text: "Главная", path: ""},
{id: 2, text: "Фильмы", path: "films"},
{id: 3, text: "Контакты", path: "contacts"},
{id: 4, text: "Каталог", path: "catalogs"},
{id: 5, text: "Отчеты", path: "reports"},
];
function App() {
return (
<>
<BrowserRouter>
<Header links={links}/>
<Routes path="/">
<Route index element={<Home/>}></Route>
<Route path="films" element={<Films/>}/>
<Route path="film" element={<Film/>}/>
<Route path="contacts" element={<Contacts/>}/>
<Route path="catalogs" element={<Catalogs/>}/>
<Route path="catalogs/catalogFilms" element={<CatalogFilms />}/>
<Route path="catalogs/catalogGenres" element={<CatalogGenres />}/>
<Route path="reports" element={<Reports />}/>
<Route path="reports/reportsFilms" element={<ReportsFilms />}/>
</Routes>
</BrowserRouter>
</>
);
}
export default App;

View File

@ -0,0 +1,23 @@
.banner-block {
width: 90%;
}
.banner-card {
width: 0;
height: 0;
overflow: hidden;
opacity: 0.2;
transition: 0.5s opacity ease;
}
.banner-card.active {
width: 100%;
height: auto;
opacity: 1;
margin: 0 auto;
}
.banner-card.active img {
height: 75vh;
}

View File

@ -0,0 +1,29 @@
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import "./Banner.css";
export default function Banner(props) {
const [currentImage, setCurrent] = useState(1);
useEffect(() => {
let timer = setInterval(() => {
setCurrent(prev => {
return prev === 5 ? 1 : prev + 1;
});
}, 3000)
return clearInterval.bind(this, timer);
}, [])
return (
<div className="banner-block" id="banner">
{props.images.map(({img, id}) => (
<div key={id} className={"banner-card" + (id === currentImage ? " active" : "")}>
<Link to="film">
<img src={img} alt="" className=""/>
</Link>
</div>
))}
</div>
)
}

View File

@ -0,0 +1,69 @@
import Catalog from "../common/Catalog";
import { useEffect, useState } from "react";
import DataService from "../../services/DataService"
let headers = [
{label: "name", text: "Имя"},
{label: "genre", text: "Жанр"}
]
export default function CatalogFilms() {
const url = "/films";
const [data, setData] = useState({
name: "",
genre: ""
});
const [genres, setGenres] = useState([]);
useEffect(() => {
DataService.readAll("/genres").then(res => {
setGenres(res)
setData({...data, genre: res[0].genre})
});
}, [])
function handleFormChange(e) {
console.log(e.target.value);
setData({ ...data, [e.target.id]: e.target.value })
}
function onAdd() {
setData({name: "", genre: genres[0].genre});
}
function onChange(data) {
setData(data);
}
function validate(data) {
if(data.name === "") return false;
return true;
}
return (
<Catalog url={url} headers={headers} data={data} onAdd={onAdd} onChange={onChange} validate={validate}>
<div>
<div className="mb-3">
<label htmlFor="name" className="form-label">Название</label>
<input type="text" value={data.name} id="name" className="form-control" required autoComplete="off"
onChange={handleFormChange}/>
</div>
<select id="genre" className="form-select" required
value={data.genre} onChange={handleFormChange}>
<option disabled value="">Укажите жанр</option>
{
genres.map(({genre, id}) =>
<option key={id} value={genre}>{genre}</option>
)
}
</select>
</div>
</Catalog>
)
}

View File

@ -0,0 +1,46 @@
import Catalog from "../common/Catalog";
import { useEffect, useState } from "react";
import DataService from "../../services/DataService"
let headers = [
{label: "genre", text: "Жанр"}
]
export default function CatalogGenres() {
const url = "/genres";
const [data, setData] = useState({
genre: ""
});
const [genres, setGenres] = useState([]);
function handleFormChange(e) {
setData({ ...data, [e.target.id]: e.target.value })
}
function onAdd() {
setData({name: "", genre: genres[0]});
}
function onChange(data) {
setData(data);
}
function validate(data) {
if(data.genre === "") return false;
return true;
}
return (
<Catalog url={url} headers={headers} data={data} onAdd={onAdd} onChange={onChange} validate={validate}>
<div className="mb-3">
<label htmlFor="genre" className="form-label">Название</label>
<input type="text" value={data.genre} id="genre" className="form-control" required autoComplete="off"
onChange={handleFormChange}/>
</div>
</Catalog>
)
}

View File

@ -0,0 +1,102 @@
import { useEffect, useState } from "react";
import Table from "./Table";
import Toolbar from "./Toolbar";
import Modal from "./Modal";
import DataService from "../../services/DataService"
export default function Catalog(props) {
const [items, setItems] = useState([]);
const [visible, setVisible] = useState(false);
const [modalConfirm, setModalConfirm] = useState("");
const [modalHeader, setModalHeader] = useState("");
const [isEdit, setEdit] = useState(false);
let selectedItems = new Set();
useEffect(() => {
loadItems();
}, [])
function toggleSelect(id) {
if(selectedItems.has(id)) selectedItems.delete(id);
else selectedItems.add(id);
}
function loadItems() {
DataService.readAll(props.url)
.then(res => setItems(res));
}
function saveData() {
if(!props.validate(props.data)) return;
if(!isEdit) {
DataService.create(props.url, props.data).then(() => loadItems());
} else {
console.log(props.data);
DataService.update(props.url, props.data, props.data.id).then(() => loadItems());
}
}
function addHandler() {
setModalHeader("Добавление фильма");
setModalConfirm("Добавить");
setEdit(false);
setVisible(true);
props.onAdd();
}
function changeHandler() {
if(!selectedItems.size) return;
if(!items.length) return;
let id = selectedItems.keys().next().value;
console.log(id);
let index = 0;
while(items[index].id !== id) {
index++;
}
props.onChange(items[index]);
selectedItems = new Set();
setModalHeader("Изменение фильма");
setModalConfirm("Изменить");
setEdit(true);
setVisible(true);
}
function removeHandler() {
let queries = [];
for(let id of selectedItems.keys()) {
queries.push(DataService.remove(props.url, id));
}
Promise.all(queries).then(() => loadItems());
}
function confirmHandler() {
saveData();
setVisible(false);
}
function closeHandler() {
setVisible(false);
}
return (
<div className="m-3">
<Toolbar addHandler={addHandler} changeHandler={changeHandler} removeHandler={removeHandler} />
<Table headers={props.headers} items={items} selected={selectedItems} toggleSelect={toggleSelect} selectable={true}/>
<Modal
visible={visible}
closeHandler={closeHandler}
header={modalHeader}
confirm={modalConfirm}
confirmHandler={confirmHandler}
>
{props.children}
</Modal>
</div>
)
}

View File

@ -0,0 +1,21 @@
.navbar__logo {
text-decoration: none;
margin-left: 30px;
}
.navbar__logo-text {
font-size: 30px;
text-decoration: none;
color: white;
}
.navbar__logo-text_first {
color: yellow;
}
body {
margin: 0;
background: linear-gradient(135deg, #8bf292, #a5ebb1) fixed;
min-height: 100vh;
position: relative;
}

View File

@ -0,0 +1,28 @@
import {NavLink} from "react-router-dom";
import "./Header.css";
export default function Header(props) {
return (
<header>
<nav className="navbar navbar-dark navbar-expand-lg bg-success">
<div className="container-fluid">
<NavLink className="navbar-brand" href="#">
<span className="navbar__logo-text navbar__logo-text_first">L</span><span className="navbar__logo-text navbar__logo-text_second">umer</span>
</NavLink>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Переключатель навигации">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav">
{props.links.map(({id, text, path}) => (
<li key={id} className="nav-item">
<NavLink className="nav-link btn btn-success" aria-current="page" to={path}>{text}</NavLink>
</li>
))}
</ul>
</div>
</div>
</nav>
</header>
)
}

View File

@ -0,0 +1,11 @@
import {Link} from "react-router-dom";
export default function LinksList(props) {
return (
<div>
{props.items.map(({link, text}) => (
<Link key={link} to={link} className="btn btn-success">{text}</Link>
))}
</div>
)
}

View File

@ -0,0 +1,21 @@
export default function Modal(props) {
return (
<div className="modal fade show" tabIndex="-1" style={{ display: props.visible ? 'block' : 'none' }}>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">{props.header}</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Закрыть" onClick={props.closeHandler}></button>
</div>
<div className="modal-body">
{props.children}
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data-bs-dismiss="modal" onClick={props.closeHandler}>Закрыть</button>
<button type="button" className="btn btn-primary" onClick={props.confirmHandler}>{props.confirm}</button>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,3 @@
.selected {
background: #2150de;
}

View File

@ -0,0 +1,40 @@
import { useState } from "react"
import "./Table.css";
export default function Table(props) {
const [tableUpdate, setTableUpdate] = useState(false);
function click(id) {
if(!props.selectable) return;
props.toggleSelect(id);
console.log(props.selected);
setTableUpdate(!tableUpdate);
}
return (
<table className="table table-hover">
<thead>
<tr>
<th>#</th>
{props.headers.map(({label, text}) => (
<th key={label}>{text}</th>
))}
</tr>
</thead>
<tbody>
{props.items.map((elem, index) => {
let trClass = "";
if(props.selectable && props.selected.has(elem.id)) trClass = "selected";
return (
<tr key={elem.id} onClick={click.bind(this, elem.id)} className={trClass}>
<td>{index + 1}</td>
{props.headers.map(({label}) => (
<td key={label}>{elem[label]}</td>
))}
</tr>
)})}
</tbody>
</table>
)
}

View File

@ -0,0 +1,9 @@
export default function Toolbar(props) {
return (
<div className="btn-group">
<button onClick={props.addHandler} className="btn btn-success">Добавить</button>
<button onClick={props.changeHandler} className="btn btn-info">Изменить</button>
<button onClick={props.removeHandler} className="btn btn-danger">Удалить</button>
</div>
)
}

View File

@ -0,0 +1,12 @@
import LinksList from "../common/LinksList";
export default function Catalogs() {
let items = [
{text: "фильмы", link: "catalogFilms"},
{text: "жанры", link: "catalogGenres"}
];
return (
<LinksList items={items}/>
)
}

View File

@ -0,0 +1,5 @@
.map__frame {
width: 90%;
height: 500px;
margin-bottom: 30px;
}

View File

@ -0,0 +1,12 @@
import "./Contacts.css";
export default function Contacts() {
return(
<main>
<section className="map">
<h2 className="text-white">Контакты</h2>
<iframe className="map__frame" title="map" src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d158855.07580070102!2d-0.2470504135400737!3d51.52953198005434!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47d8a00baf21de75%3A0x52963a5addd52a99!2z0JvQvtC90LTQvtC9LCDQktC10LvQuNC60L7QsdGA0LjRgtCw0L3QuNGP!5e0!3m2!1sru!2sru!4v1664443841067!5m2!1sru!2sru" loading="lazy"/>
</section>
</main>
)
}

View File

@ -0,0 +1,47 @@
.player {
position: relative;
width: 80%;
height: 600px;
background: black;
margin: 10px auto;
}
.player:hover .player__menu {
opacity: 1;
}
.player__menu {
position: absolute;
width: 100%;
height: 60px;
bottom: 0;
background: gray;
display: flex;
align-items: center;
justify-content: space-around;
transition: 0.6s all ease;
opacity: 0;
}
.player__button {
width: 30px;
height: 30px;
background: transparent;
border: none;
padding: 0;
cursor: pointer;
}
.player__button:focus {
outline: none;
}
.player__button-img {
width: 100%;
}
.player__progress {
width: 85%;
height: 7px;
background: black;
}

View File

@ -0,0 +1,15 @@
import playIcon from "../../img/play.png";
import "./Film.css";
export default function Film() {
return (
<main>
<div class="player">
<div class="player__menu">
<button class="player__button"><img class="player__button-img" src={playIcon} alt=""/></button>
<div class="player__progress"></div>
</div>
</div>
</main>
)
}

View File

@ -0,0 +1,36 @@
import img1 from "../../img/1.jpg";
import img2 from "../../img/2.jpg";
import img3 from "../../img/3.jpg";
import img4 from "../../img/4.jpg";
import img5 from "../../img/5.jpg";
import Banner from "../Banner";
const images = [
{img: img1, id: 1},
{img: img2, id: 2},
{img: img3, id: 3},
{img: img4, id: 4},
{img: img5, id: 5}
];
export default function Films() {
return (
<main>
<section className="categories">
<h2 className="text-white">Категории</h2>
<div className="btn-group">
<button className="btn btn-success">Комедии</button>
<button className="btn btn-success">Драмы</button>
<button className="btn btn-success">Трилер</button>
</div>
</section>
<section className="banner">
<h2 className="text-white">Все фильмы</h2>
<Banner images={images}/>
</section>
</main>
)
}

View File

@ -0,0 +1,25 @@
import img1 from "../../img/1.jpg";
import img2 from "../../img/2.jpg";
import img3 from "../../img/3.jpg";
import img4 from "../../img/4.jpg";
import img5 from "../../img/5.jpg";
import Banner from "../Banner";
const images = [
{img: img1, id: 1},
{img: img2, id: 2},
{img: img3, id: 3},
{img: img4, id: 4},
{img: img5, id: 5}
];
export default function Home() {
return (
<main>
<section className="banner">
<h2 className="text-white">Популярные</h2>
<Banner images={images}/>
</section>
</main>
)
}

View File

@ -0,0 +1,11 @@
import LinksList from "../common/LinksList";
export default function Reports() {
let items = [
{text: "фильмы", link: "reportsFilms"},
];
return (
<LinksList items={items}/>
)
}

View File

@ -0,0 +1,50 @@
import { useEffect, useState } from "react";
import Table from "../common/Table";
import DataService from "../../services/DataService";
export default function ReportSelector(props) {
const [genres, setGenres] = useState([]);
const [currentGenre, setCurrentGenre] = useState("");
const [items, setItems] = useState([]);
useEffect(() => {
DataService.readAll("/genres").then(res => {
setGenres(res)
});
}, [])
useEffect(() => {
DataService.readAll(props.url).then(res => {
console.log(res);
setItems(res)
});
}, [props.url])
function changeGenre(e) {
setCurrentGenre(e.target.value);
}
console.log(props.url);
function click() {
props.formData(currentGenre);
}
return (
<div>
<div className="input-group mb-3">
<select className="form-select" onChange={changeGenre} value={currentGenre}>
<option disabled value="">Выберите группу</option>
{
genres.map(genre => (
<option key={genre.id} value={genre.genre}>{genre.genre}</option>
))
}
</select>
<button className="btn btn-outline-secondary" type="button" onClick={click}
>Сформировать</button>
</div >
<Table headers={props.headers} items={items} />
</div>
)
}

View File

@ -0,0 +1,26 @@
import Catalog from "../common/Catalog";
import { useEffect, useState } from "react";
import DataService from "../../services/DataService"
import Table from "../common/Table";
import ReportSelector from "./ReportSelector";
let headers = [
{label: "name", text: "Имя"},
{label: "genre", text: "Жанр"}
]
export default function ReportsFilms() {
const [url, setUrl] = useState("/films?genre=asdfasdfsadf");
function formData(genre) {
console.log(genre);
setUrl("/films?genre=" + genre);
}
return (
<ReportSelector headers={headers} url={url} formData={formData}/>
)
}

BIN
frontend/src/img/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
frontend/src/img/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
frontend/src/img/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
frontend/src/img/4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
frontend/src/img/5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
frontend/src/img/play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

13
frontend/src/index.css Normal file
View File

@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

17
frontend/src/index.js Normal file
View File

@ -0,0 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

View File

@ -0,0 +1,13 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

View File

@ -0,0 +1,39 @@
export default class DataSirvice {
static urlPrefix = "http://localhost:8079";
static async readAll(url) {
let data = await fetch(this.urlPrefix + url);
return data.json();
}
static create(url, data) {
return fetch(this.urlPrefix + url, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
}
static update(url, data, id) {
console.log(this.urlPrefix + url + "/" + id)
console.log(data);
data.id = id;
return fetch(this.urlPrefix + url + "/" + id, {
method: "PUT",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
}
static remove(url, id) {
fetch(this.urlPrefix + url + "/" + id, {
method: "DELETE"
});
}
}

View File

@ -18,26 +18,26 @@ public class ActorController {
@GetMapping("/{id}")
public ActorDTO getActor(@PathVariable Long id) {
return actorService.findActor(id);
return new ActorDTO(actorService.findActor(id));
}
@GetMapping("")
public List<ActorDTO> getActors() {
return actorService.findAllActors();
return actorService.findAllActors().stream().map(ActorDTO::new).toList();
}
@PostMapping("")
public ActorDTO createActor(@RequestBody @Valid ActorDTO actor) {
return actorService.addActor(actor.getName(), actor.getSurname());
return new ActorDTO(actorService.addActor(actor.getName(), actor.getSurname()));
}
@PatchMapping("")
public ActorDTO updateActor(@PathVariable Long id, @RequestBody @Valid ActorDTO actor) {
return actorService.updateActor(id, actor.getName(), actor.getSurname());
return new ActorDTO(actorService.updateActor(id, actor.getName(), actor.getSurname()));
}
@DeleteMapping("/{id}")
public ActorDTO deleteActor(@PathVariable Long id) {
return actorService.deleteActor(id);
return new ActorDTO(actorService.deleteActor(id));
}
}

View File

@ -21,39 +21,41 @@ public class FilmController {
@GetMapping("/{id}")
public FilmDTO getFilm(@PathVariable Long id) {
return filmService.findFilm(id);
return new FilmDTO(filmService.findFilm(id));
}
@GetMapping("")
public List<FilmDTO> getFilms() {
return filmService.findAllFilms();
return filmService.findAllFilms().stream().map(FilmDTO::new).toList();
}
@PostMapping("")
public FilmDTO createFilm(@RequestBody @Valid FilmDTO film) {
FilmDTO result = filmService.addFilm(film.getName());
return filmService.updateGenres(result.getId(), film.getGenre());
Film result = filmService.addFilm(film.getName());
filmService.updateActors(result.getId(), film.getFullNames());
return new FilmDTO(filmService.updateGenres(result.getId(), film.getGenre()));
}
@PatchMapping("/{id}")
public FilmDTO updateFilm(@PathVariable Long id,
@RequestBody @Valid FilmDTO film) {
FilmDTO result = filmService.updateFilm(id, film.getName());
return filmService.updateGenres(result.getId(), film.getGenre());
Film result = filmService.updateFilm(id, film.getName());
filmService.updateActors(result.getId(), film.getFullNames());
return new FilmDTO(filmService.updateGenres(result.getId(), film.getGenre()));
}
@PatchMapping("/add_genre/{id}")
public FilmDTO addGenre(@PathVariable Long id, @RequestParam Long genre_id) {
return filmService.addGenre(id, genre_id);
return new FilmDTO(filmService.addGenre(id, genre_id));
}
@PatchMapping("/add_actor/{id}")
public FilmDTO addActor(@PathVariable Long id, @RequestParam Long actor_id) {
return filmService.addActor(id, actor_id);
return new FilmDTO(filmService.addActor(id, actor_id));
}
@DeleteMapping("/{id}")
public FilmDTO deleteFilm(@PathVariable Long id) {
return filmService.deleteFilm(id);
return new FilmDTO(filmService.deleteFilm(id));
}
}

View File

@ -23,27 +23,27 @@ public class GenreController {
@GetMapping("/{id}")
public GenreDTO getGenre(@PathVariable Long id) {
return genreService.findGenre(id);
return new GenreDTO(genreService.findGenre(id));
}
@GetMapping("")
public List<GenreDTO> getGenres() {
return genreService.findAllGenres();
return genreService.findAllGenres().stream().map(GenreDTO::new).toList();
}
@PostMapping("")
public GenreDTO createGenre(@RequestBody @Valid GenreDTO genre) {
return genreService.addGenre(genre.getName());
return new GenreDTO(genreService.addGenre(genre.getName()));
}
@PatchMapping("/{id}")
public GenreDTO updateGenre(@PathVariable Long id,
@RequestBody @Valid GenreDTO genre) {
return genreService.updateGenre(id, genre.getName());
return new GenreDTO(genreService.updateGenre(id, genre.getName()));
}
@DeleteMapping("/{id}")
public GenreDTO deleteGenre(@PathVariable Long id) {
return genreService.deleteGenre(id);
return new GenreDTO(genreService.deleteGenre(id));
}
}

View File

@ -16,17 +16,19 @@ public class FilmDTO {
private Long id;
private String name;
private List<String> genre;
private List<Actor> actors;
private List<String> fullNames;
public FilmDTO() {}
public FilmDTO(Film film) {
this.id = film.getId();
this.name = film.getName();
if(film.getGenres() == null) return;
this.genre = film.getGenres().stream().map(g -> {
return g.getName();
}).toList();
if(film.getGenres() != null) {
this.genre = film.getGenres().stream().map(Genre::getName).toList();
}
if(film.getActors() != null) {
this.fullNames = film.getActors().stream().map(actor -> actor.getName() + " " + actor.getSurname()).toList();
}
}
public FilmDTO(Long id, String name) {
@ -46,16 +48,8 @@ public class FilmDTO {
this.name = name;
}
public void addGenre(String g) {
genre.add(g);
}
public void addActor(Actor actor) {
actors.add(actor);
}
public List<Actor> getActors() {
return actors;
public List<String> getFullNames() {
return fullNames;
}
public List<String> getGenre() {

View File

@ -1,4 +1,7 @@
package ru.ip.labs.labs.films.models;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import javax.persistence.*;
import java.io.File;
import java.io.IOException;

View File

@ -1,6 +1,8 @@
package ru.ip.labs.labs.films.models;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import javax.persistence.*;
import java.util.ArrayList;

View File

@ -3,7 +3,6 @@ package ru.ip.labs.labs.films.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import ru.ip.labs.labs.films.dto.ActorDTO;
import ru.ip.labs.labs.films.models.Actor;
import ru.ip.labs.labs.films.models.Film;
import ru.ip.labs.labs.films.repository.ActorRepository;
@ -25,17 +24,17 @@ public class ActorService {
}
@Transactional
public ActorDTO addActor(String name, String surname) {
public Actor addActor(String name, String surname) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Student name is null or empty");
}
Actor actor = new Actor(name, surname);
return new ActorDTO(repo.save(actor));
return repo.save(actor);
}
@Transactional
public ActorDTO addActor(String name, String surname, String path) {
public Actor addActor(String name, String surname, String path) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Student name is null or empty");
}
@ -47,25 +46,38 @@ public class ActorService {
// System.out.println(err.getMessage());
throw new RuntimeException(err);
}
return new ActorDTO(repo.save(actor));
return repo.save(actor);
}
@Transactional(readOnly = true)
public ActorDTO findActor(Long id) {
public Actor findActor(Long id) {
final Optional<Actor> actor = repo.findById(id);
if (actor.isEmpty()) {
throw new EntityNotFoundException(String.format("Actor with id [%s] is not found", id));
}
return new ActorDTO(actor.get());
return actor.get();
}
@Transactional(readOnly = true)
public List<ActorDTO> findAllActors() {
return repo.findAll().stream().map(x -> new ActorDTO(x)).toList();
public Actor findByFullName(String name, String surname) {
if(!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Actor name is null or empty");
}
if(!StringUtils.hasText(surname)) {
throw new IllegalArgumentException("Actor surname is null or empty");
}
return repo.findActorByNameAndSurname(name, surname);
}
@Transactional(readOnly = true)
public List<Actor> findAllActors() {
return repo.findAll();
}
@Transactional
public ActorDTO updateActor(Long id, String name, String surname) {
public Actor updateActor(Long id, String name, String surname) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Actor name is null or empty");
}
@ -80,18 +92,18 @@ public class ActorService {
if(name != null) currentActor.setName(name);
if(surname != null) currentActor.setSurname(surname);
return new ActorDTO(repo.save(currentActor));
return repo.save(currentActor);
}
@Transactional
public ActorDTO deleteActor(Long id) {
public Actor deleteActor(Long id) {
final Optional<Actor> currentActor = repo.findById(id);
if(currentActor.isEmpty()) {
return null;
}
repo.deleteById(id);
return new ActorDTO(currentActor.get());
return currentActor.get();
}
@Transactional

View File

@ -3,7 +3,6 @@ package ru.ip.labs.labs.films.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import ru.ip.labs.labs.films.dto.FilmDTO;
import ru.ip.labs.labs.films.models.Actor;
import ru.ip.labs.labs.films.models.Film;
import ru.ip.labs.labs.films.models.Genre;
@ -11,152 +10,130 @@ import ru.ip.labs.labs.films.repository.ActorRepository;
import ru.ip.labs.labs.films.repository.FilmRepository;
import ru.ip.labs.labs.films.repository.GenreRepository;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
@Service
public class FilmsService {
@PersistenceContext
private EntityManager em;
private FilmRepository repo;
private GenreRepository repoGenre;
private ActorRepository repoActor;
private GenreService genreService;
private ActorService actorService;
public FilmsService(FilmRepository repo, GenreRepository repoGenre, ActorRepository repoActor) {
public FilmsService(FilmRepository repo, ActorService actorService, GenreService genreService) {
this.repo = repo;
this.repoGenre = repoGenre;
this.repoActor = repoActor;
this.actorService = actorService;
this.genreService = genreService;
}
@Transactional
public FilmDTO addFilm(String name) {
public Film addFilm(String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Student name is null or empty");
}
Film film = new Film(name);
return new FilmDTO(repo.save(film));
return repo.save(film);
}
// фильмы по жанру
// фильмы по актеру
@Transactional
public FilmDTO addGenre(Long filmId, Long genreId) {
final Film film = em.find(Film.class, filmId);
public Film addGenre(Long filmId, Long genreId) {
final Optional<Film> filmOpt = repo.findById(filmId);
if (film == null) {
if (filmOpt.isEmpty()) {
throw new EntityNotFoundException(String.format("Film with id [%s] is not found", filmId));
}
final Optional<Genre> genre = repoGenre.findById(genreId);
if (genre.isEmpty()) {
Film film = filmOpt.get();
final Genre genre = genreService.findGenre(genreId);
if (genre == null) {
throw new EntityNotFoundException(String.format("Genre with id [%s] is not found", genreId));
}
film.addGenre(genre.get());
return new FilmDTO(repo.save(film));
film.addGenre(genre);
return repo.save(film);
}
@Transactional
public FilmDTO updateGenres(Long filmId, List<String> genres) {
final Film film = em.find(Film.class, filmId);
public Film updateGenres(Long filmId, List<String> genres) {
final Optional<Film> filmOpt = repo.findById(filmId);
if (film == null) {
if (filmOpt.isEmpty()) {
throw new EntityNotFoundException(String.format("Film with id [%s] is not found", filmId));
}
Film film = filmOpt.get();
film.deleteGenres();
for(String g : genres) {
Genre genre = repoGenre.findByName(g);
Genre genre = genreService.findByName(g);
film.addGenre(genre);
}
return new FilmDTO(repo.save(film));
return repo.save(film);
}
@Transactional
public FilmDTO updateActors(Long filmId, List<String> fullNames) {
final Film film = em.find(Film.class, filmId);
public Film updateActors(Long filmId, List<String> fullNames) {
final Optional<Film> filmOpt = repo.findById(filmId);
if (film == null) {
if (filmOpt.isEmpty()) {
throw new EntityNotFoundException(String.format("Film with id [%s] is not found", filmId));
}
Film film = filmOpt.get();
film.deleteActors();
for(String fn : fullNames) {
String arr[] = fn.split(" ");
Actor actor = repoActor.findActorByNameAndSurname(arr[0], arr[1]);
Actor actor = actorService.findByFullName(arr[0], arr[1]);
film.addActor(actor);
}
return new FilmDTO(repo.save(film));
return repo.save(film);
}
@Transactional
public FilmDTO addActor(Long filmId, Long actorId) {
final Film film = em.find(Film.class, filmId);
if (film == null) {
public Film addActor(Long filmId, Long actorId) {
final Optional<Film> filmOpt = repo.findById(filmId);
if (filmOpt.isEmpty()) {
throw new EntityNotFoundException(String.format("Film with id [%s] is not found", filmId));
}
final Optional<Actor> actor = repoActor.findById(actorId);
Film film = filmOpt.get();
final Actor actor = actorService.findActor(actorId);
if (actor == null) {
throw new EntityNotFoundException(String.format("Genre with id [%s] is not found", actorId));
}
film.addActor(actor.get());
return new FilmDTO(repo.save(film));
film.addActor(actor);
return repo.save(film);
}
@Transactional(readOnly = true)
public FilmDTO findFilm(Long id) {
public Film findFilm(Long id) {
final Optional<Film> film = repo.findById(id);
if (film.isEmpty()) {
throw new EntityNotFoundException(String.format("Film with id [%s] is not found", id));
}
return new FilmDTO(film.get());
return film.get();
}
@Transactional(readOnly = true)
public List<FilmDTO> findFilmByGenre(Long id, Long genreId) {
Query query = em.createQuery("select f from Film f " +
"join f.genres g " +
"where g.id = :genreId", Film.class)
.setParameter("genreId", genreId);
List<Film> result = query.getResultList();
return result.stream().map(x -> new FilmDTO(x)).toList();
}
@Transactional(readOnly = true)
public List<FilmDTO> findFilmByActor(Long id, String name) {
Query query = em.createQuery("select f from Film f " +
"join f.actors a " +
"where a.name like :actorName", Film.class)
.setParameter("actorName", '%' + name + '%');
List<Film> result = query.getResultList();
return result.stream().map(x -> new FilmDTO(x)).toList();
}
@Transactional(readOnly = true)
public List<FilmDTO> findAllFilms() {
return repo.findAll().stream().map(x -> new FilmDTO(x)).toList();
public List<Film> findAllFilms() {
return repo.findAll();
}
@Transactional
public FilmDTO updateFilm(Long id, String name) {
public Film updateFilm(Long id, String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Film name is null or empty");
}
@ -169,18 +146,18 @@ public class FilmsService {
final Film currentFilm = currentFilmOpt.get();
currentFilm.setName(name);
return new FilmDTO(repo.save(currentFilm));
return repo.save(currentFilm);
}
@Transactional
public FilmDTO deleteFilm(Long id) {
public Film deleteFilm(Long id) {
final Optional<Film> currentFilm = repo.findById(id);
if(currentFilm.isEmpty()) {
return null;
}
repo.deleteById(id);
return new FilmDTO(currentFilm.get());
return currentFilm.get();
}
@Transactional

View File

@ -3,15 +3,10 @@ package ru.ip.labs.labs.films.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import ru.ip.labs.labs.films.dto.GenreDTO;
import ru.ip.labs.labs.films.models.Film;
import ru.ip.labs.labs.films.models.Genre;
import ru.ip.labs.labs.films.repository.ActorRepository;
import ru.ip.labs.labs.films.repository.GenreRepository;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import java.util.List;
import java.util.Optional;
@ -24,31 +19,31 @@ public class GenreService {
this.repo = repo;
}
@Transactional
public GenreDTO addGenre(String name) {
public Genre addGenre(String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Genre name is null or empty");
}
Genre genre = new Genre(name);
return new GenreDTO(repo.save(genre));
return repo.save(genre);
}
@Transactional(readOnly = true)
public GenreDTO findGenre(Long id) {
public Genre findGenre(Long id) {
final Optional<Genre> genre = repo.findById(id);
if (genre.isEmpty()) {
throw new EntityNotFoundException(String.format("Genre with id [%s] is not found", id));
}
return new GenreDTO(genre.get());
return genre.get();
}
@Transactional(readOnly = true)
public List<GenreDTO> findAllGenres() {
return repo.findAll().stream().map(x -> new GenreDTO(x)).toList();
public List<Genre> findAllGenres() {
return repo.findAll();
}
@Transactional
public GenreDTO updateGenre(Long id, String name) {
public Genre updateGenre(Long id, String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Film name is null or empty");
}
@ -61,18 +56,26 @@ public class GenreService {
final Genre currentGenre = currentGenreOpt.get();
currentGenre.setName(name);
return new GenreDTO(repo.save(currentGenre));
return repo.save(currentGenre);
}
@Transactional
public GenreDTO deleteGenre(Long id) {
public Genre findByName(String name) {
if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Genre name is null or empty");
}
return repo.findByName(name);
}
@Transactional
public Genre deleteGenre(Long id) {
Optional<Genre> genre = repo.findById(id);
if(genre.isEmpty()) {
return null;
}
repo.deleteById(id);
return new GenreDTO(genre.get());
return genre.get();
}
@Transactional

View File

@ -6,8 +6,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import ru.ip.labs.labs.films.dto.ActorDTO;
import ru.ip.labs.labs.films.dto.FilmDTO;
import ru.ip.labs.labs.films.models.Actor;
import ru.ip.labs.labs.films.models.Film;
import ru.ip.labs.labs.films.models.Genre;
@ -31,7 +29,7 @@ public class JpaActorsTest {
void testActorCreate() {
filmService.deleteAllFilms();
actorService.deleteAllActors();
final ActorDTO actor = actorService.addActor("Victor", "Ivanov");
final Actor actor = actorService.addActor("Victor", "Ivanov");
log.info(actor.toString());
Assertions.assertNotNull(actor.getId());
}
@ -46,9 +44,9 @@ public class JpaActorsTest {
void findActor() {
filmService.deleteAllFilms();
actorService.deleteAllActors();
final ActorDTO actor = actorService.addActor("Victor", "Ivanov");
final Actor actor = actorService.addActor("Victor", "Ivanov");
log.info(actor.toString());
final ActorDTO findActor = actorService.findActor(actor.getId());
final Actor findActor = actorService.findActor(actor.getId());
log.info(findActor.toString());
Assertions.assertEquals(actor.toString(), findActor.toString());
}
@ -57,9 +55,9 @@ public class JpaActorsTest {
void testReadAll() {
filmService.deleteAllFilms();
actorService.deleteAllActors();
final ActorDTO actor = actorService.addActor("Victor", "Ivanov");
final Actor actor = actorService.addActor("Victor", "Ivanov");
log.info(actor.toString());
final List<ActorDTO> actors = actorService.findAllActors();
final List<Actor> actors = actorService.findAllActors();
Assertions.assertEquals(actors.size(), 1);
}
@ -67,9 +65,9 @@ public class JpaActorsTest {
void updateActor() {
filmService.deleteAllFilms();
actorService.deleteAllActors();
final ActorDTO actor = actorService.addActor("Victor", "Ivanov");
final Actor actor = actorService.addActor("Victor", "Ivanov");
actorService.updateActor(actor.getId(), "Terminator", null);
final ActorDTO findActor = actorService.findActor(actor.getId());
final Actor findActor = actorService.findActor(actor.getId());
log.info(findActor.toString());
Assertions.assertEquals(findActor.getName() + " " + findActor.getSurname(), "Terminator Ivanov");
}
@ -78,7 +76,7 @@ public class JpaActorsTest {
void deleteActor() {
filmService.deleteAllFilms();
actorService.deleteAllActors();
final ActorDTO actor = actorService.addActor("Victor", "Ivanov");
final Actor actor = actorService.addActor("Victor", "Ivanov");
log.info(actor.toString());
actorService.deleteActor(actor.getId());
Assertions.assertThrows(EntityNotFoundException.class, () -> actorService.findActor(actor.getId()));
@ -88,8 +86,8 @@ public class JpaActorsTest {
void addPhoto() {
filmService.deleteAllFilms();
actorService.deleteAllActors();
final ActorDTO actor = actorService.addActor("Victor", "Ivanov", "C:\\Users\\parap\\OneDrive\\Рабочий стол\\work\\ferrari.jpg");
ActorDTO findActor = actorService.findActor(actor.getId());
final Actor actor = actorService.addActor("Victor", "Ivanov", "C:\\Users\\parap\\OneDrive\\Рабочий стол\\work\\ferrari.jpg");
Actor findActor = actorService.findActor(actor.getId());
Assertions.assertNotEquals(findActor.getPhoto().length, 0);
}
@ -97,12 +95,12 @@ public class JpaActorsTest {
void addFilm() {
filmService.findAllFilms();
actorService.deleteAllActors();
final ActorDTO actor = actorService.addActor("Victor", "Ivanov");
final FilmDTO film = filmService.addFilm("Terminator 2");
final Actor actor = actorService.addActor("Victor", "Ivanov");
final Film film = filmService.addFilm("Terminator 2");
filmService.addActor(film.getId(), actor.getId());
final ActorDTO findActor = actorService.findActor(actor.getId());
final Actor findActor = actorService.findActor(actor.getId());
Assertions.assertEquals(findActor.getFilms().get(0).getId(), film.getId());
}
}

View File

@ -5,8 +5,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import ru.ip.labs.labs.films.dto.ActorDTO;
import ru.ip.labs.labs.films.dto.FilmDTO;
import ru.ip.labs.labs.films.models.Actor;
import ru.ip.labs.labs.films.models.Film;
import ru.ip.labs.labs.films.models.Genre;
@ -32,7 +30,7 @@ public class JpaFilmsTest {
@Test
void testFilmCreate() {
filmService.deleteAllFilms();
final FilmDTO film = filmService.addFilm("Terminator 2");
final Film film = filmService.addFilm("Terminator 2");
log.info(film.toString());
Assertions.assertNotNull(film.getId());
}
@ -46,9 +44,9 @@ public class JpaFilmsTest {
@Test
void findFilm() {
filmService.deleteAllFilms();
final FilmDTO film = filmService.addFilm("Terminator 2");
final Film film = filmService.addFilm("Terminator 2");
log.info(film.toString());
final FilmDTO findFilm = filmService.findFilm(film.getId());
final Film findFilm = filmService.findFilm(film.getId());
log.info(findFilm.toString());
Assertions.assertEquals(film.toString(), findFilm.toString());
}
@ -56,9 +54,9 @@ public class JpaFilmsTest {
@Test
void updateFilm() {
filmService.deleteAllFilms();
final FilmDTO film = filmService.addFilm("Terminator 2");
final Film film = filmService.addFilm("Terminator 2");
filmService.updateFilm(film.getId(), "Terminator 3");
final FilmDTO findFilm = filmService.findFilm(film.getId());
final Film findFilm = filmService.findFilm(film.getId());
log.info(findFilm.toString());
Assertions.assertEquals(findFilm.getName(), "Terminator 3");
}
@ -66,75 +64,31 @@ public class JpaFilmsTest {
@Test
void testReadAll() {
filmService.deleteAllFilms();
final FilmDTO film = filmService.addFilm("Terminator 2");
final Film film = filmService.addFilm("Terminator 2");
log.info(film.toString());
final List<FilmDTO> films = filmService.findAllFilms();
final List<Film> films = filmService.findAllFilms();
Assertions.assertEquals(films.size(), 1);
}
@Test
void deleteFilm() {
filmService.deleteAllFilms();
final FilmDTO film = filmService.addFilm("Terminator 2");
final Film film = filmService.addFilm("Terminator 2");
log.info(film.toString());
filmService.deleteFilm(film.getId());
Assertions.assertThrows(EntityNotFoundException.class, () -> filmService.findFilm(film.getId()));
}
@Test
void findFilmsByGenres() {
filmService.deleteAllFilms();
genreService.deleteAllGenres();
// final FilmDTO film = filmService.addFilm("Terminator 2");
// filmService.addFilm("Terminator 3");
// final Genre genre = genreService.addGenre("Comedy");
//
// filmService.addGenre(film.getId(), genre.getId());
//
// final List<FilmDTO> films = filmService.findFilmByGenre(film.getId(), genre.getId());
// Assertions.assertEquals(films.size(), 1);
}
@Test
void findFilmsByActor() {
filmService.deleteAllFilms();
genreService.deleteAllGenres();
final FilmDTO film = filmService.addFilm("Terminator 2");
final FilmDTO film2 = filmService.addFilm("Terminator 3");
filmService.addFilm("Terminator 4");
final ActorDTO actor = actorService.addActor("Victor", "Ivanov");
final ActorDTO actor2 = actorService.addActor("Victoria", "Ivanov");
filmService.addActor(film.getId(), actor.getId());
filmService.addActor(film2.getId(), actor2.getId());
final List<FilmDTO> films = filmService.findFilmByActor(film.getId(), "Victor");
Assertions.assertEquals(films.size(), 2);
}
@Test
void addGenre() {
filmService.deleteAllFilms();
genreService.deleteAllGenres();
final FilmDTO film = filmService.addFilm("Terminator 2");
// final Genre genre = genreService.addGenre("Comedy");
//
// filmService.addGenre(film.getId(), genre.getId());
//
// final FilmDTO findFilm = filmService.findFilm(film.getId());
// Assertions.assertEquals(findFilm.getGenre().get(0).toString(), genre.toString());
}
@Test
void addActor() {
filmService.deleteAllFilms();
genreService.deleteAllGenres();
final FilmDTO film = filmService.addFilm("Terminator 2");
final ActorDTO actor = actorService.addActor("Victor", "Ivanov");
final Film film = filmService.addFilm("Terminator 2");
final Actor actor = actorService.addActor("Victor", "Ivanov");
filmService.addActor(film.getId(), actor.getId());
final FilmDTO findFilm = filmService.findFilm(film.getId());
final Film findFilm = filmService.findFilm(film.getId());
Assertions.assertEquals(findFilm.getActors().get(0).getId(), actor.getId());
}
}

View File

@ -6,8 +6,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import ru.ip.labs.labs.films.dto.GenreDTO;
import ru.ip.labs.labs.films.models.Film;
import ru.ip.labs.labs.films.models.Genre;
import ru.ip.labs.labs.films.service.FilmsService;
import ru.ip.labs.labs.films.service.GenreService;
@ -27,7 +25,7 @@ public class JpaGenresTest {
@Test
void testGenreCreate() {
genreService.deleteAllGenres();
final GenreDTO genre = genreService.addGenre("Comedy");
final Genre genre = genreService.addGenre("Comedy");
log.info(genre.toString());
Assertions.assertNotNull(genre.getId());
}
@ -41,9 +39,9 @@ public class JpaGenresTest {
@Test
void findGenre() {
genreService.deleteAllGenres();
final GenreDTO genre = genreService.addGenre("Comedy");
final Genre genre = genreService.addGenre("Comedy");
log.info(genre.toString());
final GenreDTO findGenre = genreService.findGenre(genre.getId());
final Genre findGenre = genreService.findGenre(genre.getId());
log.info(findGenre.toString());
Assertions.assertEquals(genre.toString(), findGenre.toString());
}
@ -51,18 +49,18 @@ public class JpaGenresTest {
@Test
void testReadAll() {
genreService.deleteAllGenres();
final GenreDTO genre = genreService.addGenre("Comedy");
final Genre genre = genreService.addGenre("Comedy");
log.info(genre.toString());
final List<GenreDTO> genres = genreService.findAllGenres();
final List<Genre> genres = genreService.findAllGenres();
Assertions.assertEquals(genres.size(), 1);
}
@Test
void updateGenre() {
genreService.deleteAllGenres();
final GenreDTO genre = genreService.addGenre("Comedy");
final Genre genre = genreService.addGenre("Comedy");
genreService.updateGenre(genre.getId(), "Drama");
final GenreDTO findGenre = genreService.findGenre(genre.getId());
final Genre findGenre = genreService.findGenre(genre.getId());
log.info(findGenre.toString());
Assertions.assertEquals(findGenre.getName(), "Drama");
}
@ -70,7 +68,7 @@ public class JpaGenresTest {
@Test
void deleteGenre() {
genreService.deleteAllGenres();
final GenreDTO genre = genreService.addGenre("Comedy");
final Genre genre = genreService.addGenre("Comedy");
log.info(genre.toString());
genreService.deleteGenre(genre.getId());
Assertions.assertThrows(EntityNotFoundException.class, () -> filmService.findFilm(genre.getId()));