diff --git a/Frontend/vue-project/src/components/CatalogGenres.vue b/Frontend/vue-project/src/components/CatalogGenres.vue
new file mode 100644
index 0000000..f29daf6
--- /dev/null
+++ b/Frontend/vue-project/src/components/CatalogGenres.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+ Жанр
+
+
+
+
\ No newline at end of file
diff --git a/Frontend/vue-project/src/components/Catalogs.vue b/Frontend/vue-project/src/components/Catalogs.vue
new file mode 100644
index 0000000..b95dcad
--- /dev/null
+++ b/Frontend/vue-project/src/components/Catalogs.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+ {{ catalog.label }}
+
+
+
\ No newline at end of file
diff --git a/Frontend/vue-project/src/components/DataTable.vue b/Frontend/vue-project/src/components/DataTable.vue
new file mode 100644
index 0000000..036f145
--- /dev/null
+++ b/Frontend/vue-project/src/components/DataTable.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+ #
+ {{ header.label }}
+
+
+
+
+ {{ index + 1 }}
+
+ {{ item[header.name] }}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Frontend/vue-project/src/components/Header.vue b/Frontend/vue-project/src/components/Header.vue
index 225f150..01a052a 100644
--- a/Frontend/vue-project/src/components/Header.vue
+++ b/Frontend/vue-project/src/components/Header.vue
@@ -23,6 +23,9 @@
Связь
+
+ Таблица
+
diff --git a/Frontend/vue-project/src/components/Modal.vue b/Frontend/vue-project/src/components/Modal.vue
new file mode 100644
index 0000000..f12c004
--- /dev/null
+++ b/Frontend/vue-project/src/components/Modal.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Frontend/vue-project/src/components/Table.vue b/Frontend/vue-project/src/components/Table.vue
new file mode 100644
index 0000000..732105b
--- /dev/null
+++ b/Frontend/vue-project/src/components/Table.vue
@@ -0,0 +1,9 @@
+
+ Каталоги
+
+
+
\ No newline at end of file
diff --git a/Frontend/vue-project/src/components/ToolBar.vue b/Frontend/vue-project/src/components/ToolBar.vue
new file mode 100644
index 0000000..0a21290
--- /dev/null
+++ b/Frontend/vue-project/src/components/ToolBar.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+ Добавить
+
+
+ Изменить
+
+
+ Удалить
+
+
+
+
+
\ No newline at end of file
diff --git a/Frontend/vue-project/src/main.js b/Frontend/vue-project/src/main.js
index 2281dd6..75e6397 100644
--- a/Frontend/vue-project/src/main.js
+++ b/Frontend/vue-project/src/main.js
@@ -6,15 +6,21 @@ 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'
const routes = [
{ path: '/', redirect: '/index' },
- { path: '/index', component: Index },
+ { path: '/index', component: Index},
{ path: '/player', component: Player},
{ path: '/films', component: Films},
{ path: '/about_us', component: About_us},
- { path: '/form', component: Form}
+ { path: '/form', component: Form},
+ { path: '/table', component: Table},
+ { path: '/catalogs', component: Catalogs},
+ { path: '/catalogs/genres', component: CatalogGenres}
]
const router = createRouter({
diff --git a/Frontend/vue-project/src/mixins/CatalogMixins.js b/Frontend/vue-project/src/mixins/CatalogMixins.js
new file mode 100644
index 0000000..4b493d2
--- /dev/null
+++ b/Frontend/vue-project/src/mixins/CatalogMixins.js
@@ -0,0 +1,102 @@
+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;
\ No newline at end of file
diff --git a/Frontend/vue-project/src/models/Collection.js b/Frontend/vue-project/src/models/Collection.js
new file mode 100644
index 0000000..dbef5df
--- /dev/null
+++ b/Frontend/vue-project/src/models/Collection.js
@@ -0,0 +1,26 @@
+export default class Collection {
+ constructor(data) {
+ this._id = data?.id;
+ this._name = data?.name;
+ this._filmIds = data?.filmIds;
+ }
+
+ 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;
+ }
+
+ get filmIds() {
+ return this.filmIds;
+ }
+}
\ No newline at end of file
diff --git a/Frontend/vue-project/src/models/Film.js b/Frontend/vue-project/src/models/Film.js
new file mode 100644
index 0000000..aa7c7d0
--- /dev/null
+++ b/Frontend/vue-project/src/models/Film.js
@@ -0,0 +1,26 @@
+export default class Film {
+ constructor(data) {
+ this._id = data?.id;
+ this._name = data?.name;
+ this._genreIds = data?.genreIds;
+ }
+
+ 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;
+ }
+
+ get genreIds() {
+ return this._genreIds;
+ }
+}
\ No newline at end of file
diff --git a/Frontend/vue-project/src/models/Genre.js b/Frontend/vue-project/src/models/Genre.js
new file mode 100644
index 0000000..80b53da
--- /dev/null
+++ b/Frontend/vue-project/src/models/Genre.js
@@ -0,0 +1,21 @@
+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;
+ }
+}
\ No newline at end of file
diff --git a/Frontend/vue-project/src/services/DataService.js b/Frontend/vue-project/src/services/DataService.js
new file mode 100644
index 0000000..54810c9
--- /dev/null
+++ b/Frontend/vue-project/src/services/DataService.js
@@ -0,0 +1,42 @@
+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;
+ }
+}
\ No newline at end of file
diff --git a/data.mv.db b/data.mv.db
index 9be51e6..39ecef2 100644
Binary files a/data.mv.db and b/data.mv.db differ
diff --git a/src/main/java/ru/ulstu/is/lab1/DataBase/controller/GenreController.java b/src/main/java/ru/ulstu/is/lab1/DataBase/controller/GenreController.java
index 3453274..d0db0aa 100644
--- a/src/main/java/ru/ulstu/is/lab1/DataBase/controller/GenreController.java
+++ b/src/main/java/ru/ulstu/is/lab1/DataBase/controller/GenreController.java
@@ -9,7 +9,6 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
-import ru.ulstu.is.lab1.DataBase.model.Genre;
import ru.ulstu.is.lab1.DataBase.service.GenreService;
import java.util.List;
diff --git a/src/main/java/ru/ulstu/is/lab1/DataBase/service/CollectionService.java b/src/main/java/ru/ulstu/is/lab1/DataBase/service/CollectionService.java
index 6dc63cd..14bac03 100644
--- a/src/main/java/ru/ulstu/is/lab1/DataBase/service/CollectionService.java
+++ b/src/main/java/ru/ulstu/is/lab1/DataBase/service/CollectionService.java
@@ -3,7 +3,6 @@ package ru.ulstu.is.lab1.DataBase.service;
import ru.ulstu.is.lab1.DataBase.model.Film;
import ru.ulstu.is.lab1.DataBase.model.Collection;
import ru.ulstu.is.lab1.DataBase.Repository.ICollectionRepository;
-import ru.ulstu.is.lab1.DataBase.model.Genre;
import ru.ulstu.is.lab1.util.validation.ValidatorUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;