LIL-559 Добавить блок комментариев в уроки онлайн-школы

remotes/origin/hotfix/LIL-661
gzbender 8 years ago
parent 143a940104
commit 470d7252eb
  1. 27
      api/v1/views.py
  2. 13
      web/src/components/Comment.vue
  3. 10
      web/src/components/CommentForm.vue
  4. 20
      web/src/components/Comments.vue
  5. 4
      web/src/js/modules/api.js
  6. 42
      web/src/sass/_common.sass

@ -424,23 +424,24 @@ class ObjectCommentsViewSet(ExtendedModelViewSet):
queryset = self.queryset
obj_type = self.request.query_params.get('obj_type')
obj_id = self.request.query_params.get('obj_id')
is_deactivated = self.request.query_params.get('is_deactivated', '0')
is_deactivated = self.request.query_params.get('is_deactivated')
if obj_type == self.OBJ_TYPE_COURSE:
queryset = CourseComment.objects.filter(course=obj_id, parent__isnull=True)
queryset = CourseComment.objects.filter(course=obj_id)
elif obj_type == self.OBJ_TYPE_LESSON:
queryset = LessonComment.objects.filter(lesson=obj_id, parent__isnull=True)
queryset = LessonComment.objects.filter(lesson=obj_id)
if is_deactivated == '0':
queryset = queryset.filter(level=0)
elif is_deactivated == '1':
queryset = queryset.filter(deactivated_at__isnull=True)
elif is_deactivated == '2':
queryset = queryset.filter(deactivated_at__isnull=False)
return queryset
return queryset.order_by('update_at')
def get_serializer_class(self):
if self.request.method == 'POST':
return CommentCreateSerializer
obj_type = self.request.query_params.get('obj_type')
serializer_class = CommentSerializer
if obj_type == self.OBJ_TYPE_COURSE:
serializer_class = CourseCommentSerializer
elif obj_type == self.OBJ_TYPE_LESSON:
@ -451,18 +452,32 @@ class ObjectCommentsViewSet(ExtendedModelViewSet):
obj_type = self.request.data.get('obj_type')
obj_id = self.request.data.get('obj_id')
serializer.save()
pusher().trigger(f'comments_{obj_type}_{obj_id}', 'add', serializer.data)
try:
pusher().trigger(f'comments_{obj_type}_{obj_id}', 'add', serializer.data)
except Exception as e:
print(e)
def perform_destroy(self, instance):
obj_type = None
obj_id = None
if isinstance(instance, LessonComment):
obj_type = self.OBJ_TYPE_LESSON
obj_id = instance.lesson_id
elif isinstance(instance, CourseComment):
obj_type = self.OBJ_TYPE_COURSE
obj_id = instance.course_id
serializer = self.get_serializer(instance)
pusher().trigger(f'comments_{obj_type}_{obj_id}', 'delete', serializer.data)
try:
pusher().trigger(f'comments_{obj_type}_{obj_id}', 'delete', serializer.data)
except Exception as e:
print(e)
instance.delete()
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset()).filter(parent__isnull=True)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
class AuthorRequestViewSet(ExtendedModelViewSet):
queryset = AuthorRequest.objects.all()

@ -1,6 +1,6 @@
<template>
<div>
<div v-if="! comment.deactivated_at" :class="{'questions_heart': isHeart}">
<div v-if="! comment.deactivated_at">
<a class="questions__anchor" :id="'question__' + comment.id"></a>
<div :id="'question__replyto__' + comment.id" :class="{'questions__item_reply': comment.parent && ! controller.isChat}" class="questions__item">
@ -18,7 +18,10 @@
<span class="questions__author">{{ comment.author.first_name }} {{ comment.author.last_name }}</span>
<span class="questions__date">{{ comment.created_at_humanize }}</span>
</div>
<div class="questions__content">{{ comment.content }}</div>
<div class="questions__content">
<svg v-if="isHeart" class="icon questions__heart"><use xlink:href="/static/img/sprite.svg#icon-like"></use></svg>
<span v-if="! isHeart">{{ comment.content }}</span>
</div>
</div>
<div class="questions__foot" v-if="! controller.isChat">
<button @click="controller.reply(comment)" v-if="store.user.id" class="questions__action question__reply-button">ОТВЕТИТЬ</button>
@ -64,9 +67,3 @@
}
</script>
<style>
.questions_heart .questions__content {
font-size: 24px;
color: #d40700;
}
</style>

@ -8,12 +8,12 @@
<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;"
<div class="questions__form-foot">
<button v-if="controller.isChat" class="questions__btn"
@click="controller.addHeart"><svg class="icon questions__heart"><use xlink:href="/static/img/sprite.svg#icon-like"></use></svg></button>
<button class="questions__btn" :class="{'btn btn_light': ! controller.isChat}" @click="add">ОТПРАВИТЬ</button>
<button v-show="controller.$data.replyTo" class="questions__btn" :class="{'btn btn_light': ! controller.isChat}"
@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">&#10084;</button>
</div>
</div>
</div>

@ -1,13 +1,13 @@
<template>
<div :class="{'questions_chat': isChat}">
<comment-form v-if="store.user.id && ! replyTo" :controller="controller"></comment-form>
<div class="questions-block" style="">
<div :class="{'questions--chat': isChat}">
<div v-show="nodes.length" class="questions__items">
<ul v-for="(node, index) in nodes" :key="index">
<li>
<comment v-if="! node.deactivated_at" :comment="node" :controller="controller" v-on:remove="remove"></comment>
</li>
</ul>
</div>
<comment-form v-if="store.user.id && ! replyTo" :controller="controller"></comment-form>
</div>
</template>
@ -63,7 +63,7 @@
}
let vm = this;
this.loading = true;
let request = api.removeComment(comment.id, this.store.accessToken);
let request = api.removeObjComment(comment.id, this.store.accessToken);
request.then((response) => {
vm.loading = false;
vm.onRemove(comment);
@ -89,7 +89,7 @@
else{
comments = this.nodes;
}
let index = comments.indexOf(comment);
let index = comments.findIndex((c) => +c.id === +comment.id);
if(index === -1){
return;
}
@ -118,7 +118,7 @@
request
.then((response) => {
vm.loading = false;
vm.nodes = response.data.results;
vm.nodes = response.data;
vm.connectToPusher();
})
.catch(() => {
@ -132,11 +132,3 @@
}
</script>
<style>
.questions_chat .questions-block {
background: white;
border: 1px solid #ccc;
padding: 10px;
border-radius: 5px;
}
</style>

@ -523,8 +523,8 @@ export const api = {
}
});
},
removeComment: (commentId, accessToken) => {
return api.delete(`/api/v1/comments/${commentId}/`, {
removeObjComment: (commentId, accessToken) => {
return api.delete(`/api/v1/obj-comments/${commentId}/`, {
headers: {
'Authorization': `Token ${accessToken}`,
}

@ -2773,9 +2773,11 @@ a.grey-link
&__item
display: flex
&__form
margin-bottom: 40px
margin-top: 20px
padding-bottom: 20px
border-bottom: 1px solid $border
&__form-foot
text-align: center;
&__item
&:not(:last-child)
margin-bottom: 25px
@ -2821,8 +2823,7 @@ a.grey-link
+m
height: 64px
&__btn
display: block
margin: 0 auto
margin: 0 15px;
border-radius: 20px
&__details
margin-bottom: 5px
@ -2844,9 +2845,44 @@ a.grey-link
&__date
display: inline-block
&__foot
height: 20px
text-align: right
&__action
margin-left: auto
&__heart
fill: #d40700
width: 28px
height: 28px
&--heart
&__content
font-size: 24px;
color: #d40700;
&--chat &__items
background: white;
border: 1px solid #ccc;
padding: 10px;
border-radius: 5px;
max-height: 400px;
overflow: auto;
&--chat &__ava
height: 40px
margin-right: 10px
flex: 0 0 40px
&--chat &__content
margin-bottom: 10px
&--chat &__wrap
display: flex
flex: 0 0 calc(100% - 60px);
&--chat &__field
margin-bottom: 0;
flex: 0 0 calc(100% - 160px);
&--chat &__btn
font-weight: 600;
text-shadow: 1px 1px #fff;
&--chat &__form-foot
display: flex;
.share
&__title

Loading…
Cancel
Save