ЛР4 начало изменений

This commit is contained in:
ityurner02@mail.ru 2023-05-20 20:15:57 +04:00
parent c9132c20eb
commit e1fe87f1fa
21 changed files with 132 additions and 902 deletions

View File

@ -1,13 +0,0 @@
<template>
<h1 class="text-white text-center mt-3 mb-3 fw-bold">О нас</h1>
<div class="text-white text-left mx-auto" style="max-width: 1200px">
<div class="last_info">
<span class="text-danger">V</span>IDEO | <span class="text-danger">F</span>ILMS - это онлайн кинотеатр, в котором есть лучшие фильмы разных жанров в хорошем качестве.<br>
Мы предлагаем:<br>
1. Каталог фильмов, которые можно смотреть в хорошем качестве.<br>
2. Грамотно продуманный поиск фильмов позволит быстро и легко подобрать кино.<br>
3. Возможность насладиться просмотром любимого фильма в удобное время.
</div>
</div>
<div class="mock"></div>
</template>

View File

@ -1,106 +0,0 @@
<script>
import axios from 'axios';
import CatalogMixins from '../mixins/CatalogMixins.js';
import Collection from "../models/Collection";
import Film from "../models/Film";
import DataService from '../services/DataService';
export default {
mixins: [
CatalogMixins
],
data() {
return {
getAllUrl: 'collection/',
dataUrl: 'collection',
transformer: (data) => new Collection(data),
headers: [
{ name: 'name', label: 'Название' }
],
headersFilms: [
{ name: 'name', label: 'Фильм' }
],
selectedItemsFilms: [],
genreUrl: 'film/',
films: []
}
},
created() {
DataService.readAll(this.genreUrl, (data) => new Film(data))
.then(data => {
this.films = data;
});
},
methods: {
addFilm(collectionId) {
let filmId = document.getElementById('films').value;
let response = axios.post(`http://localhost:8080/collection/add_film/${collectionId}?film_id=${filmId}`);
console.log(response);
},
delFilm(collectionId) {
let filmId = document.getElementById('films').value;
let response = axios.delete(`http://localhost:8080/collection/del_film/${collectionId}?film_id=${filmId}`);
console.log(response);
},
itemsFilms(filmIds) {
let result = [];
if (typeof filmIds === 'undefined') {
return;
}
this.films.forEach(film => {
for (let i = 0; i < filmIds.length; i++) {
if (film.id === filmIds[i]) {
result.push(film);
}
}
});
return result;
}
}
}
</script>
<template>
<ToolBar
@add="showAddModal"
@edit="showEditModal"
@remove="removeSelectedItems">
</ToolBar>
<DataTable
:headers="this.headers"
:items="this.items"
:selectedItems="this.selectedItems"
@dblclick="showEditModalDblClick">
</DataTable>
<Modal
:header="this.modal.header"
:confirm="this.modal.confirm"
v-model:visible="this.modalShow"
@done="saveItem">
<div class="mb-3">
<label for="name" class="form-label">Название коллекции</label>
<input type="text" class="form-control" id="name" required v-model="data.name">
</div>
<DataTable
:headers="this.headersFilms"
:items="itemsFilms(data.filmIds)"
:selectedItems="this.selectedItemsFilms">
</DataTable>
<div class="mb-3">
<label for="films" class="form-label">Фильмы</label>
<select class="form-select" id="films" required>
<option disabled value="">Выберите фильм</option>
<option v-for="film in this.films"
:value="film.id">
{{ film.name }}
</option>
</select>
</div>
<div class="d-flex justify-content-between">
<button class="btn btn-outline-secondary" type="button" id="addFilmButton"
@click.prevent="addFilm(data.id)">Добавить</button>
<button class="btn btn-outline-secondary" type="button" id="delFilmButton"
@click.prevent="delFilm(data.id)">Удалить</button>
</div>
</Modal>
</template>

View File

@ -1,105 +0,0 @@
<script>
import axios from 'axios';
import CatalogMixins from '../mixins/CatalogMixins.js';
import Film from "../models/Film";
import Genre from "../models/Genre";
import DataService from '../services/DataService';
export default {
mixins: [
CatalogMixins
],
data() {
return {
getAllUrl: 'film/',
dataUrl: 'film',
transformer: (data) => new Film(data),
headers: [
{ name: 'name', label: 'Название' }
],
selectedGenres: [],
genreUrl: 'genre/',
genres: [],
open: [],
len: undefined
}
},
created() {
DataService.readAll(this.genreUrl, (data) => new Genre(data))
.then(data => {
this.genres = data;
});
},
methods: {
addGenre(filmId, genreId) {
let response = axios.post(`http://localhost:8080/film/add_genre/${filmId}?genre_id=${genreId}`);
console.log(response);
return response;
},
delGenres(filmId) {
let response = axios.delete(`http://localhost:8080/film/del_genres/${filmId}`);
console.log(response);
return response;
},
async createGenres(filmId, genreIds){
await this.delGenres(filmId);
for(var j=0; j<genreIds.length; j++){
await this.addGenre(filmId, genreIds[j]);
}
},
funct(filmId, genreIds, genreId){
this.selectedGenres = [];
this.open
if(genreIds != undefined){
this.len = genreIds.length;
}
else{
this.len = 0;
}
for (var i = 0; i < this.len; i++) {
if (genreIds[i] === genreId) {
this.selectedGenres.push(genreId);
}
}
return this.selectedGenres;
}
}
}
</script>
<template>
<ToolBar
@add="showAddModal"
@edit="showEditModal"
@remove="removeSelectedItems">
</ToolBar>
<DataTable
:headers="this.headers"
:items="this.items"
:selectedItems="this.selectedItems"
@dblclick="showEditModalDblClick">
</DataTable>
<Modal
:header="this.modal.header"
:confirm="this.modal.confirm"
v-model:visible="this.modalShow"
@done="saveItem">
<div class="mb-3">
<label for="name" class="form-label">Название фильма</label>
<input type="text" class="form-control" id="name" required v-model="data.name">
</div>
<div class="form-genre">
<label for="name">Выберите жанры для добавления:</label>
<ul class="list-genre">
<li class="list-genre-item" v-for="genre in genres" :key="genre.id">
<div class="form-check">
<input class="form-check-input" type="checkbox" v-model="selectedGenres" :value="genre.id">
<label class="form-check-label" for="genreCheck{{ genre.id }}">{{ genre.name }}</label>
</div>
</li>
</ul>
<button class="btn btn-outline-secondary" type="button" id="GenreOnFilm"
@click="createGenres(data.id, selectedGenres)">Добавить</button>
</div>
</Modal>
</template>

View File

@ -1,46 +1,131 @@
<script>
import 'axios';
import axios from 'axios';
import CatalogMixins from '../mixins/CatalogMixins.js';
import Genre from "../models/Genre";
import DataService from '../services/DataService';
export default {
mixins: [
CatalogMixins
],
created() {
this.getGenres();
},
mounted() {
const addModal = document.getElementById('editModal');
addModal.addEventListener('shown.bs.modal', function () {
})
},
data() {
return {
getAllUrl: 'genre/',
dataUrl: 'genre',
transformer: (data) => new Genre(data),
headers: [
{ name: 'name', label: 'Жанр' }
]
genres: [],
URL: "http://localhost:8080/",
genre: new Genre(),
editedGenre: new Genre()
}
},
methods: {
getGenres(){
axios.get(this.URL + "genre")
.then(response => {
this.genres = response.data;
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
addGenre(genre) {
console.log(genre);
axios
.post(this.URL + "genre", genre)
.then(() => {
this.getGenres();
this.closeModal();
})
.catch((error) => {
console.log(error);
});
},
deleteGenre(id){
axios.delete(this.URL + `genre/${id}`)
.then(() =>{
this.getGenres();
})
},
openModal(status, genre = null) {
if (status === "create") {
this.editedGenre = new Genre();
this.editedGenre.status = "create";
} else if (status === "edit" && genre) {
this.editedGenre = { ...genre };
this.editedGenre.status = "edit";
}
document.getElementById("editModal").style.display = "block";
},
closeModal() {
document.getElementById("editModal").style.display = "none";
},
editGenre(genre) {
axios.put(this.URL + `genre/${genre.id}`, genre)
.then(() => {
const index = this.genres.findIndex((s) => s.id === genre.id);
if (index !== -1) {
this.genres[index] = { ...genre };
}
this.closeModal();
this.getGenres();
})
.catch((error) => {
console.log(error);
});
}
}
}
</script>
<template>
<ToolBar
@add="showAddModal"
@edit="showEditModal"
@remove="removeSelectedItems">
</ToolBar>
<DataTable
:headers="this.headers"
:items="this.items"
:selectedItems="this.selectedItems"
@dblclick="showEditModalDblClick">
</DataTable>
<Modal
:header="this.modal.header"
:confirm="this.modal.confirm"
v-model:visible="this.modalShow"
@done="saveItem">
<div class="mb-3">
<label for="genre" class="form-label">Жанр</label>
<input type="text" class="form-control" id="name" required v-model="data.name">
<div class="container mt-4">
<button class="btn btn-success mr-2" @click="openModal('create')">Добавить</button>
<table class="table text-light">
<thead>
<tr>
<th>Название</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="gen in genres" :key="gen.id">
<td>{{ gen.name }}</td>
<td>
<td>
<button class="btn btn-warning mr-2" @click="openModal('edit', gen)">Изменить</button>
</td>
<td>
<button class="btn btn-danger" @click="deleteGenre(gen.id)">Удалить</button>
</td>
</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="editedGenre.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="editedGenre.status === 'create'" @click="addGenre(editedGenre)">Создать</button>
<button type="button" class="btn btn-primary" v-else @click="editGenre(editedGenre)">Сохранить</button>
</div>
</div>
</div>
</div>
</Modal>
</template>

View File

@ -1,53 +0,0 @@
<template>
<div class="row gx-0">
<div class="block_films col my-5 text-left text-success bg-white mx-5 overflow-auto">
<div class="text-center fw-bold">Фантастика</div>
<ul>
<li>Начало</li>
<li>Интерстеллар</li>
<li>Доктор Стрэндж</li>
<li>Железный человек</li>
<li>Гиперболоид инженера Гарина</li>
</ul>
</div>
<div class="block_films col my-5 text-left text-success bg-white mx-5 overflow-auto">
<div class="text-center fw-bold">Драма</div>
<ul>
<li>Учитель на замену</li>
<li>Бесприданница</li>
<li>Зеленая миля</li>
<li>Джокер</li>
<li>Великий Гэтсби</li>
</ul>
</div>
<div class="block_films col my-5 text-left text-success bg-white mx-5 overflow-auto">
<div class="text-center fw-bold">Ужасы</div>
<ul>
<li>Оно</li>
<li>Пункт назначения</li>
<li>Звонок</li>
<li>Нечто</li>
<li>Кошмар на улице Вязов</li>
</ul>
</div>
<div class="block_films col my-5 text-left text-success bg-white mx-5 overflow-auto">
<div class="text-center fw-bold">Комедия</div>
<ul>
<li>Один дома</li>
<li>Бриллиантовая рука</li>
<li>Джентельмены удачи</li>
<li>Иван Васильевич меняет профессию</li>
<li>Маска</li>
</ul>
</div>
</div>
<div class="mock"></div>
</template>
<style scoped>
.block_films{
height: 65vh;
max-width: 450px;
min-width: 250px;
}
</style>

View File

@ -1,94 +0,0 @@
<template>
<h1 class="text-danger text-center">Связь</h1>
<form class="row m-2 gx-0" @submit.prevent="onSubmit">
<div class="form-group col-md-4 m-1" :class="{ error: v$.form.name.$errors.length }">
<label for="" class="form-label text-white">Имя</label>
<input class="form-control" type="text" v-model="v$.form.name.$model">
<!-- error message -->
<div class="input-errors" v-for="(error, index) of v$.form.name.$errors" :key="index">
<div class="error-msg text-danger">{{ error.$message }}</div>
</div>
</div>
<div class="form-group col-md-4 m-1" :class="{ error: v$.form.surname.$errors.length }">
<label for="" class="form-label text-white">Фамилия</label>
<input class="form-control" type="text" v-model="v$.form.surname.$model">
<!-- error message -->
<div class="input-errors" v-for="(error, index) of v$.form.surname.$errors" :key="index">
<div class="error-msg text-danger">{{ error.$message }}</div>
</div>
</div>
<div class="form-group col-md-4 m-1" :class="{ error: v$.form.email.$errors.length }">
<label for="" class="form-label text-white">Почта</label>
<input class="form-control" type="email" v-model="v$.form.email.$model">
<!-- error message -->
<div class="input-errors" v-for="(error, index) of v$.form.email.$errors" :key="index">
<div class="error-msg text-danger">{{ error.$message }}</div>
</div>
</div>
<div class="col-md-4 m-1">
<label for="" class="form-label text-white">Страна проживания</label>
<select class="form-control" v-model="form.selectedCountry">
<option v-for="country in form.countries" v-bind:value="country.name">{{country.name}}</option>
</select>
</div>
<div class="col-md-8 m-1">
<label for="" class="form-label text-white">Пожелания или замечания</label>
<textarea class="form-control" rows="3"></textarea>
</div>
<div class="col-12 m-2">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="notification" v-model="form.agree">
<label class="form-check-label text-white" for="notification">
Примите условия и соглашения
</label>
</div>
</div>
<div class="buttons-w">
<button :disabled="v$.form.$invalid" class="btn btn-success">Отправить</button>
</div>
</form>
<div class="mock"></div>
</template>
<script>
import useVuelidate from '@vuelidate/core'
import { required, email, minLength } from '@vuelidate/validators'
export default{
setup () {
return { v$: useVuelidate() }
},
data(){
return{
form:{
name: '',
surname: '',
email: '',
countries: [
{name: 'Россия'},
{name: 'Белоруссия'},
{name: 'Казахстан'}
],
selectedCountry: 'Россия',
agree: false
}
}
},
validations () {
return {
form:{
name: { required, min: minLength(2) },
surname: { required, min: minLength(4) },
email: { required, email },
agree: { checked (val) { return val } }
}
}
}
}
</script>

View File

@ -1,6 +1,6 @@
<template>
<header>
<nav class="navbar navbar-dark navbar-expand-xl bg-black">
<nav class="navbar navbar-dark navbar-expand-lg bg-black">
<div class="container-fluid">
<router-link to="/index" class="navbar-brand"><img src="/src/images/name.png" alt="name"></router-link>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Переключатель навигации">
@ -12,19 +12,13 @@
<router-link to="/index" class="nav-link">Главная</router-link>
</li>
<li class="nav-item">
<router-link to="/player" class="nav-link">Проигрыватель</router-link>
<router-link to="/catalogs/genres" class="nav-link">Жанры</router-link>
</li>
<li class="nav-item">
<router-link to="/films" class="nav-link">Фильмы</router-link>
<router-link to="/catalogs/films" class="nav-link">Фильмы</router-link>
</li>
<li class="nav-item">
<router-link to="/about_us" class="nav-link">О нас</router-link>
</li>
<li class="nav-item">
<router-link to="/form" class="nav-link">Связь</router-link>
</li>
<li class="nav-item">
<router-link to="/table" class="nav-link">Таблица</router-link>
<router-link to="/catalogs/collections" class="nav-link">Коллекции</router-link>
</li>
</ul>
</div>

View File

@ -1,66 +0,0 @@
<script>
export default {
props: {
header: String,
confirm: String,
visible: Boolean
},
emits: {
done: null,
'update:visible': (value) => {
if (typeof value !== 'boolean') {
throw 'Value is not a boolean';
}
return true;
}
},
methods: {
hide() {
this.$emit('update:visible', false);
},
done() {
if (this.$refs.form.checkValidity()) {
this.$emit('done');
this.hide();
} else {
this.$refs.form.reportValidity();
}
}
}
}
</script>
<template>
<div class="modal fade" tabindex="-1" aria-hidden="true"
:class="{ 'modal-show': this.visible, 'show': this.visible }">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">{{ header }}</h1>
<button type="button" class="btn-close" aria-label="Close"
@click.prevent="hide"></button>
</div>
<div class="modal-body">
<form @submit.prevent="done" ref="form">
<slot></slot>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
@click.prevent="hide">Закрыть</button>
<button type="button" class="btn btn-primary"
@click.prevent="done">{{ confirm }}</button>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.modal-show {
display: block;
}
.modal-content {
width: max-content;
}
</style>

View File

@ -1,59 +0,0 @@
<template>
<section class="title_player">
<h1 class="text-danger text-center">Проигрыватель</h1>
<div class="player">
<div class="player_menu">
<button class="player_button"><img class="player_button_img" src="/src/images/play.png" alt="play"></button>
<div class="player_progress"></div>
</div>
</div>
</section>
<div class="mock"></div>
</template>
<style scoped>
.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;
}
.player:hover .player__menu{
opacity: 1;
}
</style>

View File

@ -1,126 +0,0 @@
<script>
import axios from 'axios';
import CatalogMixins from '../mixins/CatalogMixins.js';
import Film from "../models/Film";
import Genre from "../models/Genre";
import DataService from '../services/DataService';
export default {
mixins: [
CatalogMixins
],
data() {
return {
getAllUrl: 'film/',
dataUrl: 'film',
transformer: (data) => new Film(data),
headers: [
{ name: 'name', label: 'Название' }
],
headersGenres: [
{ name: 'name', label: 'Жанр' }
],
selectedItemsGenres: [],
genreUrl: 'genre/',
genres: [],
dataFilterUrl: 'genre/film/'
}
},
created() {
DataService.readAll(this.genreUrl, (data) => new Genre(data))
.then(data => {
this.genres = data;
});
},
methods: {
addGenre(filmId) {
let genreId = document.getElementById('genres').value;
let response = axios.post(`http://localhost:8080/film/add_genre/${filmId}?genre_id=${genreId}`);
console.log(response);
},
delGenre(filmId) {
let genreId = document.getElementById('genres').value;
let response = axios.delete(`http://localhost:8080/film/del_genre/${filmId}?genre_id=${genreId}`);
console.log(response);
},
itemsGenres(genreIds) {
let result = [];
if (typeof genreIds === 'undefined') {
return;
}
this.genres.forEach(genre => {
for (let i = 0; i < genreIds.length; i++) {
if (genre.id === genreIds[i]) {
result.push(genre);
}
}
});
return result;
},
filter() {
let genreId = document.getElementById('genreFilterSelect').value;
DataService.readAll(this.dataFilterUrl + this.genreId, (data) => new Genre(data))
.then(data => {
this.items = data;
});
},
clearFilters() {
this.loadItems();
this.id = null;
this.name = null;
this.genreId = null;
}
}
}
</script>
<template>
<div>
<select class="form-select" id="genreFilterSelect" v-model="genreId">
<option disabled value="" selected>Выберите жанр</option>
<option v-for="genre in this.genres" :value="genre.id">{{ genre.name }}</option>
</select>
<button class="btn btn-primary" type="button" id="report-button"
@click.prevent="filter">Сформировать</button>
<button class="btn btn-outline-secondary" type="button" id="report-button"
@click.prevent="clearFilters">Очистить</button>
</div>
<DataTable
:headers="this.headers"
:items="this.items"
:selectedItems="this.selectedItems"
@dblclick="showEditModalDblClick">
</DataTable>
<Modal
:header="this.modal.header"
:confirm="this.modal.confirm"
v-model:visible="this.modalShow"
@done="saveItem">
<div class="mb-3">
<label for="name" class="form-label">Название фильма</label>
<input type="text" class="form-control" id="name" required v-model="data.name">
</div>
<DataTable
:headers="this.headersGenres"
:items="itemsGenres(data.genreIds)"
:selectedItems="this.selectedItemsGenres">
</DataTable>
<div class="mb-3">
<label for="genres" class="form-label">Жанры</label>
<select class="form-select" id="genres" required>
<option disabled value="">Выберите жанр</option>
<option v-for="genre in this.genres"
:value="genre.id">
{{ genre.name }}
</option>
</select>
</div>
<div class="d-flex justify-content-between">
<button class="btn btn-outline-secondary" type="button" id="addGenreButton"
@click.prevent="addGenre(data.id)">Добавить</button>
<button class="btn btn-outline-secondary" type="button" id="delGenreButton"
@click.prevent="delGenre(data.id)">Удалить</button>
</div>
</Modal>
</template>

View File

@ -1,10 +0,0 @@
<template>
<router-link to="/catalogs" class="nav-link"><button class="btn btn-success my-1" type="submit">Каталоги</button></router-link>
<router-link to="/report" class="nav-link"><button class="btn btn-success my-1" type="submit">Отчет</button></router-link>
</template>
<style scoped>
.btn{
min-width: 120px;
}
</style>

View File

@ -1,46 +0,0 @@
<script>
export default {
props: {
},
emits: {
add: null,
edit: null,
remove: null
},
methods: {
add() {
this.$emit('add');
},
edit() {
this.$emit('edit');
},
remove() {
this.$emit('remove');
}
}
}
</script>
<template>
<div class="btn-group mt-2" role="group">
<button type="button" class="btn btn-success"
@click.prevent="add">
Добавить
</button>
<button type="button" class="btn btn-warning"
@click.prevent="edit">
Изменить
</button>
<button type="button" class="btn btn-danger"
@click.prevent="remove">
Удалить
</button>
</div>
</template>
<style scoped>
.btn {
min-width: 140px;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -2,30 +2,12 @@ import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
import Index from './components/Index.vue'
import Player from './components/Player.vue'
import Films from './components/Films.vue'
import About_us from './components/About_us.vue'
import Form from './components/Form.vue'
import Table from './components/Table.vue'
import Catalogs from './components/Catalogs.vue'
import CatalogGenres from './components/CatalogGenres.vue'
import CatalogFilms from './components/CatalogFilms.vue'
import CatalogCollections from './components/CatalogCollections.vue'
import ReportGenre from './components/ReportGenre.vue'
const routes = [
{ path: '/', redirect: '/index' },
{ path: '/index', component: Index},
{ path: '/player', component: Player},
{ path: '/films', component: Films},
{ path: '/about_us', component: About_us},
{ path: '/form', component: Form},
{ path: '/table', component: Table},
{ path: '/catalogs', component: Catalogs},
{ path: '/catalogs/genres', component: CatalogGenres},
{ path: '/catalogs/films', component: CatalogFilms},
{ path: '/catalogs/collections', component: CatalogCollections},
{ path: '/report', component: ReportGenre}
{ path: '/catalogs/genres', component: CatalogGenres}
]
const router = createRouter({

View File

@ -1,102 +0,0 @@
import ToolBar from '../components/ToolBar.vue';
import DataTable from '../components/DataTable.vue';
import Modal from '../components/Modal.vue';
import DataService from '../services/DataService';
const CatalogMixin = {
components: {
ToolBar, DataTable, Modal
},
data() {
return {
getAllUrl: undefined,
dataUrl: undefined,
transformer: undefined,
headers: [],
items: [],
selectedItems: [],
modal: {
header: undefined,
confirm: undefined,
},
modalShow: false,
data: undefined,
isEdit: false
}
},
created() {
this.loadItems();
},
methods: {
loadItems() {
this.getItems();
this.data = this.transformer();
},
getItems() {
DataService.readAll(this.getAllUrl, this.transformer)
.then(data => {
this.items = data;
});
},
showAddModal() {
this.isEdit = false;
this.data = this.transformer();
this.modal.header = 'Добавление элемента';
this.modal.confirm = 'Добавить';
this.modalShow = true;
},
showEditModal() {
if (this.selectedItems.length === 0) {
return;
}
this.showEditModalDblClick(this.selectedItems[0]);
},
showEditModalDblClick(editId) {
DataService.read(this.dataUrl + "/" + editId, this.transformer)
.then(data => {
this.data = data;
this.isEdit = true;
this.modal.header = 'Редактирование элемента';
this.modal.confirm = 'Сохранить';
this.modalShow = true;
});
},
saveItem() {
if (!this.isEdit) {
DataService.create(this.dataUrl + "/", this.data)
.then(() => {
this.getItems();
});
} else {
DataService.update(this.dataUrl + "/" + this.data.id, this.data)
.then(() => {
this.getItems();
});
}
},
removeSelectedItems() {
if (this.selectedItems.length === 0) {
return;
}
if (confirm('Удалить выбранные элементы?')) {
const promises = [];
const self = this;
this.selectedItems.forEach(item => {
promises.push(DataService.delete(this.dataUrl + "/" + item));
});
Promise.all(promises).then((results) => {
results.forEach(function (id) {
const index = self.selectedItems.indexOf(id);
if (index === - 1) {
return;
}
self.selectedItems.splice(index, 1);
});
this.getItems();
});
}
}
}
}
export default CatalogMixin;

View File

@ -1,21 +1,6 @@
export default class Genre {
constructor(data) {
this._id = data?.id;
this._name = data?.name;
}
get id() {
return this._id;
}
get name() {
return this._name;
}
set name(value) {
if (typeof value !== 'string' || value === null || value.length == 0) {
throw 'New name value ' + value + ' is not a string or empty';
}
this._name = value;
this.id = data?.id;
this.name = data?.name;
}
}

View File

@ -1,42 +0,0 @@
import axios from 'axios';
function toJSON(data) {
const jsonObj = {};
const fields = Object.getOwnPropertyNames(data);
for (const field of fields) {
if (data[field] === undefined) {
continue;
}
jsonObj[field.substring(1)] = data[field];
}
return jsonObj;
}
export default class DataService {
static dataUrlPrefix = 'http://localhost:8080/';
static async readAll(url, transformer) {
const response = await axios.get(this.dataUrlPrefix + url);
return response.data.map(item => transformer(item));
}
static async read(url, transformer) {
const response = await axios.get(this.dataUrlPrefix + url);
return transformer(response.data);
}
static async create(url, data) {
const response = await axios.post(this.dataUrlPrefix + url, toJSON(data));
return true;
}
static async update(url, data) {
const response = await axios.put(this.dataUrlPrefix + url, toJSON(data));
return true;
}
static async delete(url) {
const response = await axios.delete(this.dataUrlPrefix + url);
return response.data.id;
}
}

Binary file not shown.

View File

@ -20,12 +20,12 @@ public class GenreController {
return new GenreDTO(genreService.findGenre(id));
}
@GetMapping("/")
@GetMapping
public List<GenreDTO> getGenre() {
return genreService.findAllGenres().stream().map(GenreDTO::new).toList();
}
@PostMapping("/")
@PostMapping
public GenreDTO createGenre(@RequestBody @Valid GenreDTO genreDTO) {
return new GenreDTO(genreService.addGenre(genreDTO.getName()));
}
@ -40,7 +40,7 @@ public class GenreController {
return new GenreDTO(genreService.deleteGenre(id));
}
@DeleteMapping("/")
@DeleteMapping
public void deleteAllGenres(){
genreService.deleteAllGenres();
}

View File

@ -17,4 +17,10 @@ public class GenreDTO {
public String getName(){
return name;
}
public void setId(long id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
}