Lab5 + vue

This commit is contained in:
Данила Мочалов 2023-04-18 09:57:05 +04:00
parent 859f55cbde
commit 36f22805bb
14 changed files with 18253 additions and 1 deletions

1
.gitignore vendored
View File

@ -36,3 +36,4 @@ out/
### VS Code ###
.vscode/
/front/vue_front/node_modules/

@ -1 +0,0 @@
Subproject commit 2bc9e21c22b7fbd6679612d7e6fc1170964cc128

19
front/vue_front/README.md Normal file
View File

@ -0,0 +1,19 @@
# lab4_vue_front
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}

17561
front/vue_front/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
{
"name": "lab4_vue_front",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"@popperjs/core": "^2.11.7",
"axios": "^1.3.4",
"core-js": "^3.8.3",
"vue": "^3.2.13",
"vue-router": "^4.0.3",
"vuex": "^4.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
}

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<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 href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<title>Лабораторная 4</title>
</head>
<body>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -0,0 +1,26 @@
<template>
<div>
<p class='text-center m-3 h3'> Лабораторная работа 4</p>
</div>
<div>
<p class='h4 text-center'>
<router-link to="/profiles" class="text-decoration-none m-3">Профили</router-link>
<router-link to="/comments" class="text-decoration-none m-3">Лента</router-link>
</p>
</div>
<router-view></router-view>
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
<style lang="">
</style>

View File

@ -0,0 +1,335 @@
<template>
<div class="text-center ">
<div class="dropdown text-center mx-auto w-25 ">
<div class="text-end mt-3">
<button class="btn btn-secondary dropdown-toggle ms-3 mb-3 " type="button" data-bs-toggle="dropdown" aria-expanded="false">
{{ selectedProfileLogin }}
</button>
<ul class="dropdown-menu " >
<li v-for="profile in profiles">
<a class="dropdown-item" href="#" v-on:click="getSelectedProfile(profile)">
{{ profile['login'] }}
</a>
</li>
</ul>
</div>
</div>
<div class='h3 m-3 d-flex justify-content-between text-center mx-auto w-25'>
Лента
<button type='button' class="btn btn-primary ms-5 mb-3 " data-bs-toggle="modal" data-bs-target="#postCreate">
Добавить новый пост
</button>
</div>
<div>
<input @change="findPosts(va)" v-model="textFinder" type="text" class="mb-2" style="width: 25%" placeholder="Поиск...">
</div>
<div v-if="selectedProfileId != 0" class="text-center mx-auto w-25 ">
<div v-if="!(posts.length == 0)">
<p v-for="post in posts">
<div class="border p-2">
<p class="h4 text-start"> {{ post['text'] }} </p>
<div class="d-flex justify-content-between">
<a class="text-start fst-italic" @click="getPostOwner(post['id'])">Автор: {{ findPostOwner(post['id']) }}</a>
<div class="h4 text-end">
<button v-if="selectedProfileContainsPost(post) == true" type="button" v-on:click="selectedPostId = post['id']" class="btn btn-warning mb-1" data-bs-toggle="modal" data-bs-target="#postEdit">
<i class="fa fa-pencil" aria-hidden="true"></i>
</button>
<button v-if="selectedProfileContainsPost(post) == true" type="button" v-on:click="deletePost(post['id'])" class="btn btn-danger me-1 mb-1 ms-2">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<div class="border p-2">
<div v-if="!(post['comments'].length == 0)" class="mb-3 text-start">
<p class="text-start h5">Комментарии:</p>
<p v-for="comment in post['comments']">
<p class="fst-italic"> {{ findCommentOwner(comment['id'], comment['text']) }}: </p>
<div class="ms-3">
{{ comment['text'] }}
<button v-if="selectedProfileContainsComment(comment) == true" v-on:click="selectedCommentId = comment['id']; selectedPostText = post['text']" class="btn btn-warning me-2 mb-1 ms-5" data-bs-toggle="modal" data-bs-target="#commentEdit"><i class="fa fa-pencil" aria-hidden="true"></i></button>
<button v-if="selectedProfileContainsComment(comment) == true" v-on:click="deleteComment(comment['id'])" class="btn btn-danger me-3 mb-1"><i class="fa fa-trash" aria-hidden="true"></i></button>
</div>
</p>
</div>
<div class="text-end">
<button type="button" v-on:click="selectedPostId = post['id']; selectedPostText = post['text'];" class="btn btn-info me-3 mb-3" data-bs-toggle="modal" data-bs-target="#commentCreate">Добавить комментарий</button>
</div>
</div>
</p>
</div>
<p v-else class='ms-3'>
Нет постов
</p>
</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>{{ selectedProfileLogin }}</p>
<p>К посту:</p>
<p>{{ selectedPostText }}</p>
<p>Комментарий</p>
<textarea v-model='textModal' 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>{{ selectedProfileLogin }}</p>
<p>К посту:</p>
<p>{{ selectedPostText }}</p>
<p>Комментарий</p>
<textarea v-model='textModal' 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>
<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">
{{selectedProfileLogin}}
</button>
<ul class="dropdown-menu" >
<li v-for="profile in profiles">
<a class="dropdown-item" href="#" v-on:click="getSelectedProfile(profile)">
{{ profile['login'] }}
</a>
</li>
</ul>
</div>
<p>Текст поста:</p>
<textarea v-model='textModal' 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>{{ selectedProfileLogin }}</p>
<p>Текст</p>
<textarea v-model='textModal' 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='editPost'>Изменить</button>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
profiles: [],
selectedProfileId: 0,
selectedProfileLogin: 'Профиль не выбран',
posts: [],
selectedPostId: 0,
selectedPostText: '',
textModal: '',
selectedCommentId: 0,
textFinder: ''
}
},
methods: {
async findPosts(){
this.posts = (await axios.get('http://localhost:8080/api/post/find?text=' + this.textFinder)).data
},
getSelectedProfile(profile){
this.selectedProfileId = profile['id'];
this.selectedProfileLogin = profile['login'];
this.refreshList();
},
selectedProfileContainsComment(comment) {
var profile = this.profiles.find(element => element['id'] == this.selectedProfileId);
console.log(profile);
if (profile == null) return false;
var flag = false;
profile['comments'].forEach(commentIn => {
if (commentIn['id'] == comment['id']) {
flag = true;
}
});
return flag;
},
selectedProfileContainsPost(post) {
var profile = this.profiles.find(element => element['id'] == this.selectedProfileId);
if (profile == null) return false;
var flag = false;
profile['posts'].forEach(postIn => {
if (postIn['id'] == post['id']) {
flag = true;
}
});
return flag;
},
findCommentOwner(id, text) {
console.log(id)
console.log(text)
var profile = null;
this.profiles.forEach(element => {
console.log(element['comments'][0])
element['comments'].forEach(comm => {
if (comm['id'] == id) {
profile = element
}
})
})
if (profile == null) return 'User not found'
else return profile['login']
},
findPostOwner(id) {
var profile = null;
this.profiles.forEach(element => {
console.log(element['posts'][0])
element['posts'].forEach(post => {
if (post['id'] == id) {
profile = element
}
})
})
if (profile == null) return 'User not found'
else return profile['login']
},
getPostOwner(id) {
var profile = null;
this.profiles.forEach(element => {
console.log(element['posts'][0])
element['posts'].forEach(post => {
if (post['id'] == id) {
profile = element
}
})
})
if (profile == null) return null
else {
this.$router.push(
{
name: 'posts',
params: {
profileId: profile['id']
}
}
)
}
},
async createComment() {
await axios.post('http://localhost:8080/comment/?text=' + this.textModal + '&ownerId=' + this.selectedProfileId + '&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.textModal);
this.refreshList();
},
async refreshList(){
this.profiles = [];
this.posts = [];
const responseProfile = await axios.get('http://localhost:8080/api/profile/');
responseProfile.data.forEach(element => {
this.profiles.push(element);
console.log(element);
});
const responsePost = await axios.get('http://localhost:8080/api/post/');
responsePost.data.forEach(element => {
this.posts.push(element);
console.log(element);
});
},
async createPost() {
const response = await axios.post('http://localhost:8080/api/post/?text=' + this.textModal + '&authorId=' + this.selectedProfileId);
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 + '?text=' + this.textModal);
this.refreshList();
},
},
async beforeMount() {
const responseProfile = await axios.get('http://localhost:8080/api/profile/');
responseProfile.data.forEach(element => {
this.profiles.push(element);
console.log(element);
});
const responsePost = await axios.get('http://localhost:8080/api/post/');
responsePost.data.forEach(element => {
this.posts.push(element);
console.log(element);
});
}
}
</script>
<style lang="">
</style>

View File

@ -0,0 +1,80 @@
<template>
<div class="text-center">
<div class="text-start mx-auto w-25 border p-5">
<p class='h5'>Профиль</p>
<p>Логин: {{profile['login']}} </p>
<p class='h6 '>Список постов пользователя: </p>
<div v-if="!(profile['posts'].length == 0)">
<div v-for="post in profile['posts']">
<p class="mb-3 ms-2 border p-2"> {{ post['text'] }} </p>
</div>
</div>
<p v-else class=''>
Нет постов
</p>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
profile: null,
selectedProfileId: 0,
selectedProfileLogin: 'Профиль не выбран',
posts: [],
textModal: '',
selectedPostId: 0,
}
},
methods: {
async getSelectedProfile(profile){
this.selectedProfileId = profile['id'];
this.selectedProfileLogin = profile['login'];
this.posts = profile['posts'];
},
async createPost() {
const response = await axios.post('http://localhost:8080/api/post/?text=' + this.textModal + '&authorId=' + this.selectedProfileId);
this.refreshList();
},
async deletePost(postId) {
const response = await axios.delete('http://localhost:8080/api/post/' + postId);
this.refreshList();
},
async editPost(){
const response = await axios.put('http://localhost:8080/api/post/' + this.selectedPostId + '?text=' + this.textModal);
this.refreshList();
},
async refreshList() {
const response = await axios.get('http://localhost:8080/api/profile/');
this.profiles = [];
response.data.forEach(element => {
this.profiles.push(element);
if (element['id'] == this.selectedProfileId) {
this.selectedProfileLogin = element['login'];
this.posts = element['posts'];
}
console.log(element);
});
this.textModal = '';
}
},
async beforeMount() {
console.log(this.$route.params.profileId)
this.selectedProfileId = this.$route.params.profileId
console.log(this.selectedProfileId)
this.profile = (await axios.get('http://localhost:8080/api/profile/' + this.selectedProfileId)).data;
}
}
</script>
<style lang="">
</style>

View File

@ -0,0 +1,125 @@
<template>
<div class="ms-5">
<p class='h5 m-3'>Профили</p>
<button type='button' class="btn btn-primary ms-3 mb-3" data-bs-toggle="modal" data-bs-target="#profileCreate">
Добавить новый профиль
</button>
<p class='h6 ms-3'>Список профилей</p>
<ul>
<li v-for="profile in profiles">
<p>ID:{{ profile['id'] }}, ЛОГИН: {{ profile['login'] }}, ПАРОЛЬ: {{ profile['password'] }} </p>
<p>Комментарии:</p>
<ul v-if="!(profile['comments'].length == 0)">
<li v-for="comment in profile['comments']" class='mb-3'>
{{ comment['text'] }}
</li>
</ul>
<p v-else class='mb-3'>
Нет комментариев
</p>
<p>Посты: </p>
<ul v-if="!(profile['posts'].length == 0)">
<li v-for="post in profile['posts']" class='mb-3'>
{{ post['text'] }}
</li>
</ul>
<p v-else class='mb-3'>
Нет постов
</p>
<button type="button" v-on:click="deleteUser(profile['id'])" class="btn btn-danger me-3 mb-3">Удалить</button>
<button type="button" v-on:click="selectedProfileId = profile['id']" class="btn btn-warning mb-3" data-bs-toggle="modal" data-bs-target="#profileEdit">Редактировать</button>
</li>
</ul>
</div>
<!-- Modal -->
<div class="modal fade" id="profileCreate" tabindex="-1" role="dialog" aria-labelledby="profileCreateLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="profileCreateLabel">Создать профиль</h5>
</div>
<div class="modal-body text-center">
<p>Логин</p>
<textarea v-model='loginModal' id="loginText" cols="30" rows="1"></textarea>
<p>Пароль</p>
<textarea v-model='passwordModal' id="passwordText" 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='createUser'>Сохранить</button>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="profileEdit" tabindex="-1" role="dialog" aria-labelledby="profileEditLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="profileEditLabel">Редактировать профиль</h5>
</div>
<div class="modal-body text-center">
<p>Логин</p>
<textarea v-model='loginModal' id="loginText" cols="30" rows="1"></textarea>
<p>Пароль</p>
<textarea v-model='passwordModal' id="passwordText" 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='editUser'>Изменить</button>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
profiles: [],
loginModal: '',
passwordModal: '',
selectedProfileId: 0,
}
},
methods: {
async createUser(){
const response = await axios.post('http://localhost:8080/api/profile/?login=' + this.loginModal + '&password=' + this.passwordModal);
this.refreshList();
},
async deleteUser(id) {
const response = await axios.delete('http://localhost:8080/api/profile/' + id);
this.refreshList();
},
async editUser() {
const response = await axios.put('http://localhost:8080/api/profile/' + this.selectedProfileId + '?login=' + this.loginModal + '&password=' + this.passwordModal);
this.refreshList();
},
async refreshList() {
const response = await axios.get('http://localhost:8080/api//profile/');
this.profiles = [];
response.data.forEach(element => {
this.profiles.push(element);
console.log(element);
});
}
},
async beforeMount() {
const response = await axios.get('http://localhost:8080/api/profile/');
response.data.forEach(element => {
this.profiles.push(element);
console.log(element);
});
}
}
</script>
<style lang="">
</style>

View File

@ -0,0 +1,32 @@
import {createApp} from 'vue'
import App from './App'
import { createRouter, createWebHistory } from "vue-router"
import Profile from './components/Profile'
import Post from './components/Post'
import Comment from './components/Comment'
const routes = [
{
path: '/profiles',
component: Profile
},
{
path: '/posts/:profileId',
name: 'posts',
component: Post,
props: true
},
{
path: '/comments',
component: Comment
}
]
const router = createRouter({
routes,
history: createWebHistory()
})
createApp(App).use(router).mount('#app')

View File

@ -0,0 +1,4 @@
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true
})