Lab4 is done
This commit is contained in:
parent
00c99afbcf
commit
2224416988
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
/frontend/node_modules/
|
||||
/build
|
||||
/.idea
|
||||
|
9
frontend/node_modules/fs/README.md
generated
vendored
9
frontend/node_modules/fs/README.md
generated
vendored
@ -1,9 +0,0 @@
|
||||
# Security holding package
|
||||
|
||||
This package name is not currently in use, but was formerly occupied
|
||||
by another package. To avoid malicious use, npm is hanging on to the
|
||||
package name, but loosely, and we'll probably give it to you if you
|
||||
want it.
|
||||
|
||||
You may adopt this package by contacting support@npmjs.com and
|
||||
requesting the name.
|
46
frontend/node_modules/fs/package.json
generated
vendored
46
frontend/node_modules/fs/package.json
generated
vendored
@ -1,46 +0,0 @@
|
||||
{
|
||||
"_from": "fs",
|
||||
"_id": "fs@0.0.1-security",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==",
|
||||
"_location": "/fs",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "fs",
|
||||
"name": "fs",
|
||||
"escapedName": "fs",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
|
||||
"_shasum": "8a7bd37186b6dddf3813f23858b57ecaaf5e41d4",
|
||||
"_spec": "fs",
|
||||
"_where": "C:\\Users\\user\\Desktop\\something\\frontend",
|
||||
"author": "",
|
||||
"bugs": {
|
||||
"url": "https://github.com/npm/security-holder/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "This package name is not currently in use, but was formerly occupied by another package. To avoid malicious use, npm is hanging on to the package name, but loosely, and we'll probably give it to you if you want it.",
|
||||
"homepage": "https://github.com/npm/security-holder#readme",
|
||||
"keywords": [],
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"name": "fs",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/npm/security-holder.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"version": "0.0.1-security"
|
||||
}
|
9
frontend/node_modules/http/README.md
generated
vendored
9
frontend/node_modules/http/README.md
generated
vendored
@ -1,9 +0,0 @@
|
||||
# Security holding package
|
||||
|
||||
This package name is not currently in use, but was formerly occupied
|
||||
by another package. To avoid malicious use, npm is hanging on to the
|
||||
package name, but loosely, and we'll probably give it to you if you
|
||||
want it.
|
||||
|
||||
You may adopt this package by contacting support@npmjs.com and
|
||||
requesting the name.
|
39
frontend/node_modules/http/package.json
generated
vendored
39
frontend/node_modules/http/package.json
generated
vendored
@ -1,39 +0,0 @@
|
||||
{
|
||||
"_from": "http",
|
||||
"_id": "http@0.0.1-security",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==",
|
||||
"_location": "/http",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "http",
|
||||
"name": "http",
|
||||
"escapedName": "http",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz",
|
||||
"_shasum": "3aac09129d12dc2747bbce4157afde20ad1f7995",
|
||||
"_spec": "http",
|
||||
"_where": "C:\\Users\\user\\Desktop\\something\\frontend",
|
||||
"bugs": {
|
||||
"url": "https://github.com/npm/security-holder/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "security holding package",
|
||||
"homepage": "https://github.com/npm/security-holder#readme",
|
||||
"name": "http",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/npm/security-holder.git"
|
||||
},
|
||||
"version": "0.0.1-security"
|
||||
}
|
4
frontend/package-lock.json
generated
4
frontend/package-lock.json
generated
@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "lab4_vue_front",
|
||||
"name": "front",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "lab4_vue_front",
|
||||
"name": "front",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.7",
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "lab4_vue_front",
|
||||
"name": "front",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -1,20 +1,44 @@
|
||||
<template>
|
||||
<div class="nav">
|
||||
<div class="nav-center">
|
||||
|
||||
<div class="nav row">
|
||||
<div class="nav-left col-10">
|
||||
<router-link to="/customers" class="button primary clear">Профили</router-link>
|
||||
<router-link to="/posts" class="button primary clear">Посты</router-link>
|
||||
<router-link to="/comments" class="button primary clear">Комментарии</router-link>
|
||||
</div>"
|
||||
</div>
|
||||
<div class="nav-right col-2">
|
||||
<select class="form-select" style="font-size: 16px;" v-model="currentCustomerId">
|
||||
<option value="-1" selected class="button dark outline" :on-click="updateCurrentCustomer()">Не выбран</option>
|
||||
<option v-for="customer in customers" v-bind:value="customer['id']" class="button dark outline" :on-click="updateCurrentCustomer()">{{ customer['username'] }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
return {
|
||||
currentCustomerId: -1,
|
||||
customers: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async updateCurrentCustomer() {
|
||||
history.replaceState(this.currentCustomerId, "");
|
||||
}
|
||||
},
|
||||
async beforeMount() {
|
||||
setInterval(async () => {
|
||||
const response = await axios.get('http://localhost:8080/customer');
|
||||
this.customers = [];
|
||||
response.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
}, 500)
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -1,194 +0,0 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="row mb-5">
|
||||
<p class='is-center h2'>Комментарии</p>
|
||||
</div>
|
||||
<div class="row mb-5">
|
||||
<div class="col"></div>
|
||||
<div class="col-3">
|
||||
<div class="dropdown row">
|
||||
<button class="button secondary outline dropdown-toggle mb-5" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ selectedCustomerUsername }}
|
||||
</button>
|
||||
<ul class="dropdown-menu" >
|
||||
<li v-for="customer in customers">
|
||||
<a class="dropdown-item button secondary outline" href="#" v-on:click="getSelectedCustomer(customer)">
|
||||
{{ customer['username'] }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedCustomerId != 0">
|
||||
<div v-if="!(posts.length == 0)" class="row">
|
||||
<div class="col">
|
||||
<div class="row mb-5 card" v-for="post in posts">
|
||||
<div class="col">
|
||||
<div class="row is-left h3"><p>Автор: <span class="text-primary">{{ post['customerName'] }}</span></p></div>
|
||||
<div class="row text-center">
|
||||
<span class="h1">{{ post['title'] }}</span>
|
||||
</div>
|
||||
<div class="row text-center mb-5">
|
||||
<span class="h3">{{ post['content'] }}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p class="row h2 is-center mb-3">Комментарии</p>
|
||||
<div v-if="!(post['comments'].length == 0)" class="row text-left mb-5 card" v-for="comment in post['comments']">
|
||||
<div class="row mb-1">
|
||||
<span class="h2 text-primary">{{ comment['customerName'] }}</span>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<span class="h3">{{ comment['content'] }}</span>
|
||||
</div>
|
||||
<div v-if="selectedCustomerContainsComment(comment) == true" class="row">
|
||||
<button v-on:click="selectedCommentId = comment['id']; selectedPostTitle = post['title']" class="button primary outline col" data-bs-toggle="modal" data-bs-target="#commentEdit">Изменить комментарий</button>
|
||||
<button v-on:click="deleteComment(comment['id'])" class="button error col">Удалить комментарий</button>
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="h3 row is-center mb-1">Пусто</p>
|
||||
<div class="row">
|
||||
<button type="button" v-on:click="selectedPostId = post['id']; selectedPostTitle = post['title'];" class="button secondary outline" data-bs-toggle="modal" data-bs-target="#commentCreate">Добавить комментарий</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="row text-center is-center">
|
||||
Нет постов
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="commentCreate" tabindex="-1" role="dialog" aria-labelledby="commentCreateLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentCreateLabel">Создать комментарий</h5>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p>Под именем:</p>
|
||||
<p>{{ selectedCustomerUsername }}</p>
|
||||
<p>К посту:</p>
|
||||
<p>{{ selectedPostTitle }}</p>
|
||||
<p>Комментарий</p>
|
||||
<textarea v-model='contentModal' id="createModalText" cols="30" rows="1"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-on:click='createComment'>Создать</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="commentEdit" tabindex="-1" role="dialog" aria-labelledby="commentEditLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentEditLabel">Изменить комментарий</h5>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p>Под именем:</p>
|
||||
<p>{{ selectedCustomerUsername }}</p>
|
||||
<p>К посту:</p>
|
||||
<p>{{ selectedPostTitle }}</p>
|
||||
<p>Комментарий</p>
|
||||
<textarea v-model='contentModal' id="editModalText" cols="30" rows="1"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-on:click='editComment'>Изменить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
customers: [],
|
||||
selectedCustomerId: 0,
|
||||
selectedCustomerUsername: 'Профиль не выбран',
|
||||
posts: [],
|
||||
selectedPostId: 0,
|
||||
selectedPostTitle: '',
|
||||
contentModal: '',
|
||||
selectedCommentId: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getSelectedCustomer(customer){
|
||||
this.selectedCustomerId = customer['id'];
|
||||
this.selectedCustomerUsername = customer['username'];
|
||||
this.refreshList();
|
||||
},
|
||||
|
||||
selectedCustomerContainsComment(comment) {
|
||||
var customer = this.customers.find(element => element['id'] == this.selectedCustomerId);
|
||||
console.log(customer);
|
||||
if (customer == null) return false;
|
||||
var flag = false;
|
||||
customer['comments'].forEach(commentIn => {
|
||||
if (commentIn['id'] == comment['id']) {
|
||||
flag = true;
|
||||
}
|
||||
});
|
||||
return flag;
|
||||
},
|
||||
|
||||
async createComment() {
|
||||
await axios.post('http://localhost:8080/comment?text=' + this.contentModal + '&ownerId=' + this.selectedCustomerId + '&postId=' + this.selectedPostId);
|
||||
this.refreshList();
|
||||
},
|
||||
async deleteComment(commentId) {
|
||||
await axios.delete('http://localhost:8080/comment/' + commentId);
|
||||
this.refreshList();
|
||||
},
|
||||
async editComment(){
|
||||
await axios.put('http://localhost:8080/comment/' + this.selectedCommentId + '?text=' + this.contentModal);
|
||||
this.refreshList();
|
||||
},
|
||||
async refreshList(){
|
||||
this.customers = [];
|
||||
this.posts = [];
|
||||
const responseCustomer = await axios.get('http://localhost:8080/customer');
|
||||
responseCustomer.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
const responsePost = await axios.get('http://localhost:8080/post');
|
||||
responsePost.data.forEach(element => {
|
||||
this.posts.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
}
|
||||
},
|
||||
async beforeMount() {
|
||||
const responseCustomer = await axios.get('http://localhost:8080/customer');
|
||||
responseCustomer.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
const responsePost = await axios.get('http://localhost:8080/post');
|
||||
responsePost.data.forEach(element => {
|
||||
this.posts.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="">
|
||||
|
||||
</style>
|
@ -42,7 +42,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="row">Нет постов</p>
|
||||
<div class="row">
|
||||
<div class="row" v-if="customer['id'] == currentCustomerId">
|
||||
<button v-on:click="deleteUser(customer['id'])" class="col button dark outline">Удалить</button>
|
||||
<button v-on:click="selectedCustomer = customer; usernameModal=customer['username'];passwordModal=customer['password']" class="col button primary outline" data-bs-toggle="modal" data-bs-target="#customerEdit">Редактировать</button>
|
||||
</div>
|
||||
@ -104,6 +104,7 @@ export default {
|
||||
usernameModal: '',
|
||||
passwordModal: '',
|
||||
selectedCustomer: {},
|
||||
currentCustomerId: -1
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -120,22 +121,41 @@ export default {
|
||||
this.refreshList();
|
||||
},
|
||||
async refreshList() {
|
||||
const response = await axios.get('http://localhost:8080/customer');
|
||||
this.customers = [];
|
||||
if (this.$route.params.id === "") {
|
||||
const response = await axios.get('http://localhost:8080/customer');
|
||||
response.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
} else {
|
||||
const response = await axios.get('http://localhost:8080/customer/' + this.$route.params.id);
|
||||
this.customers.push(response.data)
|
||||
}
|
||||
},
|
||||
async beforeMount() {
|
||||
|
||||
},
|
||||
async mounted() {
|
||||
this.currentCustomerId = history.state;
|
||||
setInterval(async () => this.currentCustomerId = history.state, 50)
|
||||
if (this.$route.params.id === "") {
|
||||
const response = await axios.get('http://localhost:8080/customer');
|
||||
response.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
|
||||
} else {
|
||||
const response = await axios.get('http://localhost:8080/customer/' + this.$route.params.id);
|
||||
this.customers.push(response.data)
|
||||
}
|
||||
|
||||
},
|
||||
async beforeRouteUpdate(to, from) {
|
||||
this.$route.params.id = to.params.id;
|
||||
this.refreshList();
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
@ -1,188 +0,0 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="row mb-5">
|
||||
<p class='is-center h2'>Посты</p>
|
||||
</div>
|
||||
<div class="row mb-5">
|
||||
<div class="col"></div>
|
||||
<div class="col-3">
|
||||
<div class="dropdown row">
|
||||
<button class="button secondary outline dropdown-toggle mb-5" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ selectedCustomer }}
|
||||
</button>
|
||||
<ul class="dropdown-menu" >
|
||||
<li v-for="customer in customers">
|
||||
<a class="dropdown-item button secondary outline" href="#" v-on:click="getSelectedCustomer(customer)">
|
||||
{{ customer['username'] }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type='button' class="button primary" data-bs-toggle="modal" data-bs-target="#postCreate">
|
||||
Добавить новый пост
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
|
||||
<div class="row text-center">
|
||||
<p class='h2 mb-5'>Список постов пользователя {{ selectedCustomer }}</p>
|
||||
</div>
|
||||
<div v-if="!(posts.length == 0)" class="row">
|
||||
<div class="col">
|
||||
<div class="row mb-4 card" v-for="post in posts">
|
||||
<div class="col">
|
||||
<div class="row text-center">
|
||||
<span class="h1">{{ post['title'] }}</span>
|
||||
</div>
|
||||
<div class="row text-center">
|
||||
<span class="h3">{{ post['content'] }}</span>
|
||||
</div>
|
||||
<br class="row" />
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p class="row h2 is-center mb-3">Комментарии</p>
|
||||
<div v-if="!(post['comments'].length == 0)" class="row text-left mb-5 card" v-for="comment in post['comments']">
|
||||
<div class="row mb-3">
|
||||
<span class="h2 text-primary">{{ comment['customerName'] }}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="h3">{{ comment['content'] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="h3 row is-center">Пусто</p>
|
||||
</div>
|
||||
</div>
|
||||
<br class="row" />
|
||||
<div class="row">
|
||||
<button type="button" v-on:click="deletePost(post['id'])" class="col button dark outline">Удалить пост</button>
|
||||
<button type="button" v-on:click="selectedPostId = post['id']" class="col button primary outline" data-bs-toggle="modal" data-bs-target="#postEdit">Изменить пост</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="row text-center is-center">
|
||||
Нет постов
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="postCreate" tabindex="-1" role="dialog" aria-labelledby="postCreateLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="postCreateLabel">Создать пост</h5>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p>Пользователь:</p>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-secondary dropdown-toggle ms-3 mb-3" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{selectedCustomer}}
|
||||
</button>
|
||||
<ul class="dropdown-menu" >
|
||||
<li v-for="customer in customers">
|
||||
<a class="dropdown-item" href="#" v-on:click="getSelectedCustomer(customer)">
|
||||
{{ customer['username'] }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>Заголовок:</p>
|
||||
<textarea v-model='titleModal' id="modalText" cols="30" rows="1"></textarea>
|
||||
<p>Содержание:</p>
|
||||
<textarea v-model='contentModal' id="modalText" cols="30" rows="1"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-on:click='createPost'>Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="postEdit" tabindex="-1" role="dialog" aria-labelledby="postEditLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="postEditLabel">Редактировать пост</h5>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p>{{ selectedCustomer }}</p>
|
||||
<p>Заголовок</p>
|
||||
<textarea v-model='titleModal' id="editModalTitle" cols="30" rows="1"></textarea>
|
||||
<p>Содержание</p>
|
||||
<textarea v-model='contentModal' id="editModalContent" cols="30" rows="1"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-on:click='editPost'>Изменить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
customers: [],
|
||||
selectedCustomerId: 0,
|
||||
selectedCustomer: 'Профиль не выбран',
|
||||
posts: [],
|
||||
titleModal: '',
|
||||
contentModal: '',
|
||||
selectedPostId: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async getSelectedCustomer(customer){
|
||||
this.selectedCustomerId = customer['id'];
|
||||
this.selectedCustomer = customer['username'];
|
||||
this.posts = customer['posts'];
|
||||
},
|
||||
async createPost() {
|
||||
const response = await axios.post('http://localhost:8080/post?title=' + this.titleModal + '&content=' + this.contentModal + '&authorId=' + this.selectedCustomerId);
|
||||
this.refreshList();
|
||||
|
||||
},
|
||||
async deletePost(postId) {
|
||||
const response = await axios.delete('http://localhost:8080/post/' + postId);
|
||||
this.refreshList();
|
||||
},
|
||||
async editPost(){
|
||||
const response = await axios.put('http://localhost:8080/post/' + this.selectedPostId + '?title=' + this.titleModal + '&content=' + this.contentModal);
|
||||
this.refreshList();
|
||||
},
|
||||
async refreshList() {
|
||||
const response = await axios.get('http://localhost:8080/customer');
|
||||
this.customers = [];
|
||||
response.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
if (element['id'] == this.selectedCustomerId) {
|
||||
this.selectedCustomerUsername = element['username'];
|
||||
this.posts = element['posts'];
|
||||
}
|
||||
console.log(element);
|
||||
});
|
||||
this.textModal = '';
|
||||
}
|
||||
},
|
||||
async beforeMount() {
|
||||
const response = await axios.get('http://localhost:8080/customer');
|
||||
response.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="">
|
||||
|
||||
</style>
|
227
frontend/src/components/Posts.vue
Normal file
227
frontend/src/components/Posts.vue
Normal file
@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="row mb-5">
|
||||
<p class='is-center h2'>Посты</p>
|
||||
</div>
|
||||
<div class="row mb-5" v-if="currentCustomerId != -1">
|
||||
<div class="col"></div>
|
||||
<div class="col-10">
|
||||
<div class="row mb-4 is-center">
|
||||
<p class="col-2 is-left mb-2">Заголовок:</p>
|
||||
<input type="text" class="col-6" v-model="titleModal"/>
|
||||
</div>
|
||||
<div class="row mb-4 is-center">
|
||||
<p class="col-2 is-left mb-2">Текст:</p>
|
||||
<textarea type="textarea" class="col-6" v-model="postContentModal"/>
|
||||
</div>
|
||||
<div class="row is-center">
|
||||
<button type='button' class="button primary col-8" v-on:click='createPost'>
|
||||
Опубликовать
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
<div v-if="!(posts.length == 0)" class="row">
|
||||
<div class="col">
|
||||
<div class="row mb-5 card" v-for="post in posts">
|
||||
<div class="col">
|
||||
<div class="row h3">
|
||||
<div class="col is-left">
|
||||
<p>Автор: <router-link v-bind:to="'/customers/' + post['customerId']" class="text-primary">{{ post['customerName'] }}</router-link></p>
|
||||
</div>
|
||||
<div class="col is-right">
|
||||
<p>Дата: <span class="text-primary">{{ post['createDate'] }}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row text-center">
|
||||
<span class="h1">{{ post['title'] }}</span>
|
||||
</div>
|
||||
<div class="row text-center mb-5">
|
||||
<span class="h3">{{ post['content'] }}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p class="row h2 is-center mb-3">Комментарии</p>
|
||||
<div v-if="!(post['comments'].length == 0)" class="row text-left mb-5 card" v-for="comment in post['comments']">
|
||||
<div class="row mb-1">
|
||||
<div class="col is-left">
|
||||
<span class="h2 text-primary">{{ comment['customerName'] }}</span>
|
||||
</div>
|
||||
<div class="col is-right">
|
||||
<span class="h2 text-primary">{{ comment['createDate'] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<span class="h3">{{ comment['content'] }}</span>
|
||||
</div>
|
||||
<div v-if="selectedCustomerContainsComment(comment) == true" class="row">
|
||||
<button v-on:click="selectedCommentId = comment['id']; selectedPostTitle = post['title']" class="button primary outline col" data-bs-toggle="modal" data-bs-target="#commentEdit">Изменить комментарий</button>
|
||||
<button v-on:click="deleteComment(comment['id'])" class="button error col">Удалить комментарий</button>
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="h3 row is-center mb-5">Пусто</p>
|
||||
<div class="row" v-if="currentCustomerId != -1">
|
||||
<input type="text" v-bind:id="'post-comment-' + post['id']" class="col-9"/>
|
||||
<button type="button" v-on:click="selectedPostId = post['id']; selectedPostTitle = post['title']; createComment()" class="button col-3 secondary outline">Комментировать</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-if="post['customerId'] == currentCustomerId">
|
||||
<button type="button" v-on:click="deletePost(post['id'])" class="col button dark outline">Удалить пост</button>
|
||||
<button type="button" v-on:click="selectedPostId = post['id']" class="col button primary outline" data-bs-toggle="modal" data-bs-target="#postEdit">Изменить пост</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="row text-center is-center">
|
||||
Нет постов
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="commentEdit" tabindex="-1" role="dialog" aria-labelledby="commentEditLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="commentEditLabel">Изменить комментарий</h5>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p>Под именем:</p>
|
||||
<p>{{ currentCustomer['username'] }}</p>
|
||||
<p>К посту:</p>
|
||||
<p>{{ selectedPostTitle }}</p>
|
||||
<p>Комментарий</p>
|
||||
<textarea v-model='contentModal' id="editModalText" cols="30" rows="1"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-on:click='editComment'>Изменить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="postEdit" tabindex="-1" role="dialog" aria-labelledby="postEditLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="postEditLabel">Редактировать пост</h5>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p>{{ currentCustomer['username'] }}</p>
|
||||
<p>Заголовок</p>
|
||||
<textarea v-model='titleModal' id="editModalTitle" cols="30" rows="1"></textarea>
|
||||
<p>Содержание</p>
|
||||
<textarea v-model='postContentModal' id="editModalPostContent" cols="30" rows="1"></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
|
||||
<button type="button" class="btn btn-primary" v-on:click='editPost'>Изменить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
customers: [],
|
||||
selectedCustomerId: 0,
|
||||
currentCustomer: {},
|
||||
posts: [],
|
||||
selectedPostId: 0,
|
||||
selectedPostTitle: '',
|
||||
contentModal: '',
|
||||
titleModal: '',
|
||||
postContentModal: '',
|
||||
selectedCommentId: 0,
|
||||
currentCustomerId: -1,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectedCustomerContainsComment(comment) {
|
||||
var customer = this.customers.find(element => element['id'] == this.currentCustomerId);
|
||||
console.log(customer);
|
||||
if (customer == null) return false;
|
||||
var flag = false;
|
||||
customer['comments'].forEach(commentIn => {
|
||||
if (commentIn['id'] == comment['id']) {
|
||||
flag = true;
|
||||
}
|
||||
});
|
||||
return flag;
|
||||
},
|
||||
|
||||
async createComment() {
|
||||
const content = document.getElementById("post-comment-" + this.selectedPostId).value
|
||||
await axios.post('http://localhost:8080/comment?text=' + content + '&ownerId=' + this.currentCustomerId + '&postId=' + this.selectedPostId);
|
||||
document.getElementById("post-comment-" + this.selectedPostId).value = ''
|
||||
this.refreshList();
|
||||
},
|
||||
async deleteComment(commentId) {
|
||||
await axios.delete('http://localhost:8080/comment/' + commentId);
|
||||
this.refreshList();
|
||||
},
|
||||
async editComment(){
|
||||
await axios.put('http://localhost:8080/comment/' + this.selectedCommentId + '?text=' + this.contentModal);
|
||||
this.refreshList();
|
||||
},
|
||||
async createPost() {
|
||||
const response = await axios.post('http://localhost:8080/post?title=' + this.titleModal + '&content=' + this.postContentModal + '&authorId=' + this.currentCustomerId);
|
||||
this.titleModal = ''
|
||||
this.postContentModal = ''
|
||||
this.refreshList();
|
||||
|
||||
},
|
||||
async deletePost(postId) {
|
||||
const response = await axios.delete('http://localhost:8080/post/' + postId);
|
||||
this.refreshList();
|
||||
},
|
||||
async editPost(){
|
||||
const response = await axios.put('http://localhost:8080/post/' + this.selectedPostId + '?title=' + this.titleModal + '&content=' + this.postContentModal);
|
||||
this.refreshList();
|
||||
},
|
||||
async refreshList(){
|
||||
this.customers = [];
|
||||
this.posts = [];
|
||||
const responseCustomer = await axios.get('http://localhost:8080/customer');
|
||||
responseCustomer.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
console.log(element);
|
||||
});
|
||||
const responsePost = await axios.get('http://localhost:8080/post');
|
||||
responsePost.data.forEach(element => {
|
||||
this.posts.splice(0, 0, element);
|
||||
console.log(element);
|
||||
});
|
||||
}
|
||||
},
|
||||
async beforeMount() {
|
||||
this.currentCustomerId = history.state;
|
||||
setInterval(async () => this.currentCustomerId = history.state, 50)
|
||||
const responseCustomer = await axios.get('http://localhost:8080/customer');
|
||||
responseCustomer.data.forEach(element => {
|
||||
this.customers.push(element);
|
||||
if (element['id'] == this.currentCustomerId) {
|
||||
this.currentCustomer = element;
|
||||
}
|
||||
console.log(element);
|
||||
});
|
||||
const responsePost = await axios.get('http://localhost:8080/post');
|
||||
responsePost.data.forEach(element => {
|
||||
this.posts.splice(0, 0, element);
|
||||
console.log(element);
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="">
|
||||
|
||||
</style>
|
@ -2,22 +2,21 @@ import {createApp} from 'vue'
|
||||
import App from './App'
|
||||
import { createRouter, createWebHistory } from "vue-router"
|
||||
|
||||
import Customer from './components/Customer'
|
||||
import Post from './components/Post'
|
||||
import Comment from './components/Comment'
|
||||
import Customers from './components/Customers'
|
||||
import Posts from './components/Posts'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/customers',
|
||||
component: Customer
|
||||
path: '/customers/:id?',
|
||||
name: "Customers",
|
||||
component: Customers,
|
||||
props: true
|
||||
},
|
||||
{
|
||||
path: '/posts',
|
||||
component: Post
|
||||
},
|
||||
{
|
||||
path: '/comments',
|
||||
component: Comment
|
||||
name: "Posts",
|
||||
component: Posts,
|
||||
props: true
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -2,12 +2,18 @@ package np.something.DTO;
|
||||
|
||||
import np.something.model.Comment;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class CommentDto {
|
||||
public final long id;
|
||||
public final String content;
|
||||
public final String customerName;
|
||||
public final String postTitle;
|
||||
public final String postAuthor;
|
||||
public final long postAuthorId;
|
||||
|
||||
public final String createDate;
|
||||
|
||||
public CommentDto(Comment comment) {
|
||||
this.id = comment.getId();
|
||||
@ -15,6 +21,8 @@ public class CommentDto {
|
||||
this.customerName = comment.getCustomer().getUsername();
|
||||
this.postTitle = comment.getPost().getTitle();
|
||||
this.postAuthor = comment.getPost().getCustomer().getUsername();
|
||||
this.postAuthorId = comment.getPost().getCustomer().getId();
|
||||
this.createDate = comment.getCreateDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
@ -34,4 +42,12 @@ public class CommentDto {
|
||||
public String getPostAuthor() {
|
||||
return postAuthor;
|
||||
}
|
||||
|
||||
public long getPostAuthorId() {
|
||||
return postAuthorId;
|
||||
}
|
||||
|
||||
public String getCreateDate() {
|
||||
return createDate;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package np.something.DTO;
|
||||
|
||||
import np.something.model.Post;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
public class PostDto {
|
||||
@ -9,14 +11,20 @@ public class PostDto {
|
||||
public final String title;
|
||||
public final String content;
|
||||
public final String customerName;
|
||||
|
||||
public final long customerId;
|
||||
public final List<CommentDto> comments;
|
||||
|
||||
public String createDate;
|
||||
|
||||
public PostDto(Post post) {
|
||||
this.id = post.getId();
|
||||
this.title = post.getTitle();
|
||||
this.content = post.getContent();
|
||||
this.customerName = post.getCustomer().getUsername();
|
||||
this.customerId = post.getCustomer().getId();
|
||||
this.comments = post.getComments().stream().map(CommentDto::new).toList();
|
||||
this.createDate = post.getCreateDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
@ -38,4 +46,12 @@ public class PostDto {
|
||||
public List<CommentDto> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public long getCustomerId() {
|
||||
return customerId;
|
||||
}
|
||||
|
||||
public String getCreateDate() {
|
||||
return createDate;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package np.something.model;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@ -23,6 +24,9 @@ public class Comment {
|
||||
@JoinColumn(name="post_fk")
|
||||
private Post post;
|
||||
|
||||
@Column(columnDefinition = "timestamp default NOW()")
|
||||
private LocalDateTime createDate;
|
||||
|
||||
public Comment() {
|
||||
|
||||
}
|
||||
@ -67,4 +71,12 @@ public class Comment {
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
public LocalDateTime getCreateDate() {
|
||||
return createDate;
|
||||
}
|
||||
|
||||
public void setCreateDate(LocalDateTime createDate) {
|
||||
this.createDate = createDate;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package np.something.model;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -27,6 +28,9 @@ public class Post {
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "post", cascade = CascadeType.ALL)
|
||||
private List<Comment> comments;
|
||||
|
||||
@Column(columnDefinition = "timestamp default NOW()")
|
||||
private LocalDateTime createDate;
|
||||
|
||||
public Post() {
|
||||
|
||||
}
|
||||
@ -80,4 +84,12 @@ public class Post {
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreateDate() {
|
||||
return createDate;
|
||||
}
|
||||
|
||||
public void setCreateDate(LocalDateTime createDate) {
|
||||
this.createDate = createDate;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import np.something.repositories.CommentRepository;
|
||||
import np.something.util.validation.ValidatorUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -37,6 +38,7 @@ public class CommentService {
|
||||
@Transactional
|
||||
public Comment addComment(Customer customer, Post post, String content) {
|
||||
final Comment comment = new Comment(customer, post, content);
|
||||
comment.setCreateDate(LocalDateTime.now());
|
||||
validatorUtil.validate(comment);
|
||||
customer.getComments().add(comment);
|
||||
post.getComments().add(comment);
|
||||
|
@ -14,6 +14,7 @@ import np.something.util.validation.ValidatorUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@ -40,6 +41,7 @@ public class PostService {
|
||||
@Transactional
|
||||
public Post addPost(Customer customer, String title, String content) {
|
||||
Post post = new Post(customer, title, content);
|
||||
post.setCreateDate(LocalDateTime.now());
|
||||
validatorUtil.validate(post);
|
||||
customer.getPosts().add(post);
|
||||
return postRepository.save(post);
|
||||
|
Loading…
Reference in New Issue
Block a user