remotes/origin/hotfix/LIL-661
parent
055141c9f0
commit
3f4426618f
11 changed files with 277 additions and 133 deletions
@ -0,0 +1,14 @@ |
|||||||
|
from django.conf import settings |
||||||
|
from pusher import Pusher |
||||||
|
|
||||||
|
|
||||||
|
def pusher(): |
||||||
|
try: |
||||||
|
pusher_cluster = settings.PUSHER_CLUSTER |
||||||
|
except AttributeError: |
||||||
|
pusher_cluster = 'mt1' |
||||||
|
|
||||||
|
return Pusher(app_id=settings.PUSHER_APP_ID, |
||||||
|
key=settings.PUSHER_KEY, |
||||||
|
secret=settings.PUSHER_SECRET, |
||||||
|
cluster=pusher_cluster) |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
<template> |
||||||
|
<div class="questions__form" :class="{'questions__item_reply': controller.$data.replyTo}"> |
||||||
|
<div class="questions__ava ava"> |
||||||
|
<img class="ava__pic" :src="store.user.photo || store.defaultUserPhoto"> |
||||||
|
</div> |
||||||
|
<div class="questions__wrap"> |
||||||
|
<div class="questions__field"> |
||||||
|
<textarea v-model="content" class="questions__textarea" |
||||||
|
:placeholder="controller.$data.replyTo ? 'Ответьте на комментарий' : 'Задайте автору курса интересующие вас вопросы'"></textarea> |
||||||
|
</div> |
||||||
|
<div style="text-align: center;"> |
||||||
|
<button class="questions__btn btn btn_light" style="display: inline; margin: 0 20px;" @click="add">ОТПРАВИТЬ</button> |
||||||
|
<button v-show="controller.$data.replyTo" class="questions__btn btn btn_light" style="display: inline; margin: 0 20px;" |
||||||
|
@click="controller.cancelReply">ОТМЕНИТЬ</button> |
||||||
|
<button v-if="controller.isChat" class="questions__btn btn btn_light" style="display: inline; margin: 0 20px; color: #d40700;" |
||||||
|
@click="controller.addHeart">❤</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
|
||||||
|
<script> |
||||||
|
import {api} from "../js/modules/api"; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'comment-form', |
||||||
|
props: ['controller',], |
||||||
|
data() { |
||||||
|
return { |
||||||
|
content: '', |
||||||
|
store: window.VUE_STORE, |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
add() { |
||||||
|
this.controller.add(this.content); |
||||||
|
this.content = ''; |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
@ -1,97 +1,142 @@ |
|||||||
<template> |
<template> |
||||||
<div> |
<div :class="{'questions_chat': isChat}"> |
||||||
<ul v-for="node in nodes"> |
<comment-form v-if="store.user.id && ! replyTo" :controller="controller"></comment-form> |
||||||
|
<div class="questions-block" style=""> |
||||||
|
<ul v-for="(node, index) in nodes" :key="index"> |
||||||
<li> |
<li> |
||||||
<comment v-on:reply="onReply" v-if="! node.deactivated_at" :comment="node" :user-id="userId" :default-author-picture="defaultAuthorPicture"></comment> |
<comment v-if="! node.deactivated_at" :comment="node" :controller="controller" v-on:remove="remove"></comment> |
||||||
<comments v-if="! node.is_leaf_node && node.children" :comments="node.children" default-author-picture="defaultAuthorPicture"></comments> |
|
||||||
</li> |
</li> |
||||||
</ul> |
</ul> |
||||||
<form v-if="userId" class="questions__form" method="post" > |
|
||||||
<input type="hidden" name="reply_id"> |
|
||||||
<div class="questions__ava ava"> |
|
||||||
<img class="ava__pic" :src="userPhoto || defaultAuthorPicture"> |
|
||||||
</div> |
</div> |
||||||
<div class="questions__wrap"> |
|
||||||
<div v-show="replyTo" class="questions__reply-info" style="display: block;">В ответ на |
|
||||||
<a :href="replyAnchor" class="questions__reply-anchor">этот комментарий</a>. |
|
||||||
<a href="#" @click="cancelReply" class="questions__reply-cancel grey-link">Отменить</a> |
|
||||||
</div> |
|
||||||
<div class="questions__field"> |
|
||||||
<textarea v-model="content" class="questions__textarea" placeholder="Задайте автору курса интересующие вас вопросы"></textarea> |
|
||||||
</div> |
|
||||||
<button class="questions__btn btn btn_light" @click="post">ОТПРАВИТЬ</button> |
|
||||||
</div> |
|
||||||
</form> |
|
||||||
</div> |
</div> |
||||||
</template> |
</template> |
||||||
|
|
||||||
<script type="text/javascript"> |
<script type="text/javascript"> |
||||||
import Comment from './comment'; |
import Comment from './Comment'; |
||||||
|
import CommentForm from './CommentForm'; |
||||||
import {api} from "../js/modules/api"; |
import {api} from "../js/modules/api"; |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: 'comments', |
name: 'comments', |
||||||
props: ['objType', 'objId', 'comments', 'userId', 'userPhoto', 'accessToken', 'defaultAuthorPicture'], |
props: ['objType', 'objId', 'isChat'], |
||||||
data() { |
data() { |
||||||
return { |
return { |
||||||
loading: false, |
loading: false, |
||||||
replyTo: null, |
replyTo: null, |
||||||
content: '', |
|
||||||
nodes: [], |
nodes: [], |
||||||
} |
controller: this, |
||||||
}, |
store: window.VUE_STORE, |
||||||
computed: { |
flatComments: {}, |
||||||
replyAnchor(){ |
|
||||||
return this.replyTo ? `#question__${this.replyTo.id}` : ''; |
|
||||||
} |
} |
||||||
}, |
}, |
||||||
methods: { |
methods: { |
||||||
clear() { |
reply(comment) { |
||||||
this.content = '', |
this.replyTo = comment; |
||||||
this.replyTo = null |
|
||||||
}, |
}, |
||||||
cancelReply(){ |
cancelReply(){ |
||||||
this.replyTo = null; |
this.replyTo = null; |
||||||
}, |
}, |
||||||
post() { |
addHeart(){ |
||||||
|
this.add('❤'); |
||||||
|
}, |
||||||
|
add(content){ |
||||||
|
let vm = this; |
||||||
this.loading = true; |
this.loading = true; |
||||||
let request = api.addComment(this.objId, this.objType, { |
let request = api.addObjComment(this.objId, this.objType, { |
||||||
content: this.content, |
content: content, |
||||||
author: this.userId, |
author: this.store.user.id, |
||||||
parent: this.replyTo && this.replyTo.id, |
parent: this.replyTo && this.replyTo.id, |
||||||
}, this.accessToken); |
}, this.store.accessToken); |
||||||
request.then((response) => { |
request.then((response) => { |
||||||
this.loading = false; |
vm.loading = false; |
||||||
if(this.replyTo){ |
vm.onAdd(response.data); |
||||||
this.replyTo.children.push(response.data); |
if(vm.replyTo){ |
||||||
} |
vm.cancelReply(); |
||||||
else { |
|
||||||
this.nodes.push(response.data); |
|
||||||
} |
} |
||||||
this.clear(); |
|
||||||
}).catch(() => { |
}).catch(() => { |
||||||
this.loading = false; |
vm.loading = false; |
||||||
}); |
}); |
||||||
}, |
}, |
||||||
onReply(replyTo) { |
remove(comment){ |
||||||
this.replyTo = replyTo; |
if(! confirm('Удалить комментарий?')){ |
||||||
|
return; |
||||||
|
} |
||||||
|
let vm = this; |
||||||
|
this.loading = true; |
||||||
|
let request = api.removeComment(comment.id, this.store.accessToken); |
||||||
|
request.then((response) => { |
||||||
|
vm.loading = false; |
||||||
|
vm.onRemove(comment); |
||||||
|
}); |
||||||
}, |
}, |
||||||
|
onAdd(comment){ |
||||||
|
if(this.flatComments[comment.id]){ |
||||||
|
return; |
||||||
|
} |
||||||
|
if(comment.parent){ |
||||||
|
this.flatComments[comment.parent].children.unshift(comment); |
||||||
|
} |
||||||
|
else{ |
||||||
|
this.nodes.unshift(comment); |
||||||
|
} |
||||||
|
this.flatComments[comment.id] = comment; |
||||||
}, |
}, |
||||||
mounted() { |
onRemove(comment){ |
||||||
if(this.comments && this.comments.length){ |
let comments = []; |
||||||
this.nodes = this.comments; |
if(comment.parent){ |
||||||
|
comments = this.flatComments[comment.parent].children; |
||||||
|
} |
||||||
|
else{ |
||||||
|
comments = this.nodes; |
||||||
|
} |
||||||
|
let index = comments.indexOf(comment); |
||||||
|
if(index === -1){ |
||||||
|
return; |
||||||
} |
} |
||||||
else if(this.objType && this.objId){ |
comments.splice(index, 1); |
||||||
let request = api.getObjComments(this.objId, this.objType, this.accessToken); |
delete this.flatComments[comment.id]; |
||||||
|
}, |
||||||
|
connectToPusher(){ |
||||||
|
let vm = this; |
||||||
|
// Enable pusher logging - don't include this in production |
||||||
|
Pusher.logToConsole = true; |
||||||
|
|
||||||
|
let pusher = new Pusher('d9bfd3aaf6ed22bdcc0d', { |
||||||
|
cluster: 'eu', |
||||||
|
encrypted: true |
||||||
|
}); |
||||||
|
|
||||||
|
let channel = pusher.subscribe('comments_' + this.objType + '_' + this.objId); |
||||||
|
channel.bind('add', this.onAdd); |
||||||
|
channel.bind('delete', this.onRemove); |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
let vm = this; |
||||||
|
this.loading = true; |
||||||
|
let request = api.getObjComments(this.objId, this.objType, this.store.accessToken); |
||||||
request |
request |
||||||
.then((response) => { |
.then((response) => { |
||||||
this.nodes = response.data.results; |
vm.loading = false; |
||||||
|
vm.nodes = response.data.results; |
||||||
|
vm.connectToPusher(); |
||||||
|
}) |
||||||
|
.catch(() => { |
||||||
|
vm.loading = false; |
||||||
}); |
}); |
||||||
} |
|
||||||
console.log('nodes', this.nodes); |
|
||||||
}, |
}, |
||||||
components: { |
components: { |
||||||
Comment |
Comment, |
||||||
|
CommentForm |
||||||
} |
} |
||||||
} |
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
|
<style> |
||||||
|
.questions_chat .questions-block { |
||||||
|
background: white; |
||||||
|
border: 1px solid #ccc; |
||||||
|
padding: 10px; |
||||||
|
border-radius: 5px; |
||||||
|
} |
||||||
|
</style> |
||||||
|
|||||||
Loading…
Reference in new issue