diff --git a/api/v1/views.py b/api/v1/views.py index fb79a335..5505310a 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -64,6 +64,7 @@ from apps.payment.models import ( ) from apps.school.models import SchoolSchedule, LiveLesson from apps.user.models import AuthorRequest +from project.pusher import pusher User = get_user_model() @@ -395,15 +396,15 @@ class ConfigViewSet(generics.RetrieveUpdateAPIView): class CommentViewSet(ExtendedModelViewSet): - queryset = Comment.objects.filter(level=0) - serializer_class = CommentCreateSerializer - permission_classes = (IsAdmin,) + queryset = Comment.objects.all() + serializer_class = CommentSerializer + permission_classes = (IsAuthorObjectOrAdmin,) def get_queryset(self): queryset = self.queryset is_deactivated = self.request.query_params.get('is_deactivated', '0') if is_deactivated == '0': - queryset = queryset + queryset = queryset.filter(level=0) elif is_deactivated == '1': queryset = queryset.filter(deactivated_at__isnull=True) elif is_deactivated == '2': @@ -412,11 +413,12 @@ class CommentViewSet(ExtendedModelViewSet): return queryset -class ObjectCommentsViewSet(viewsets.ReadOnlyModelViewSet): - queryset = Comment.objects.filter(level=0) +class ObjectCommentsViewSet(ExtendedModelViewSet): OBJ_TYPE_COURSE = 'course' OBJ_TYPE_LESSON = 'lesson' - permission_classes = (IsAdmin,) + queryset = Comment.objects.all() + serializer_class = CommentCreateSerializer + permission_classes = (IsAuthorObjectOrAdmin,) def get_queryset(self): queryset = self.queryset @@ -424,11 +426,11 @@ class ObjectCommentsViewSet(viewsets.ReadOnlyModelViewSet): obj_id = self.request.query_params.get('obj_id') is_deactivated = self.request.query_params.get('is_deactivated', '0') if obj_type == self.OBJ_TYPE_COURSE: - queryset = CourseComment.objects.filter(course=obj_id) + queryset = CourseComment.objects.filter(course=obj_id, parent__isnull=True) elif obj_type == self.OBJ_TYPE_LESSON: - queryset = LessonComment.objects.filter(lesson=obj_id) + queryset = LessonComment.objects.filter(lesson=obj_id, parent__isnull=True) if is_deactivated == '0': - queryset = queryset + queryset = queryset.filter(level=0) elif is_deactivated == '1': queryset = queryset.filter(deactivated_at__isnull=True) elif is_deactivated == '2': @@ -436,6 +438,8 @@ class ObjectCommentsViewSet(viewsets.ReadOnlyModelViewSet): return queryset def get_serializer_class(self): + if self.request.method == 'POST': + return CommentCreateSerializer obj_type = self.request.query_params.get('obj_type') if obj_type == self.OBJ_TYPE_COURSE: serializer_class = CourseCommentSerializer @@ -443,6 +447,22 @@ class ObjectCommentsViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = LessonCommentSerializer return serializer_class + def perform_create(self, serializer): + 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) + + def perform_destroy(self, instance): + obj_type = None + if isinstance(instance, LessonComment): + obj_type = self.OBJ_TYPE_LESSON + elif isinstance(instance, CourseComment): + obj_type = self.OBJ_TYPE_COURSE + serializer = self.get_serializer(instance) + pusher().trigger(f'comments_{obj_type}_{obj_id}', 'delete', serializer.data) + instance.delete() + class AuthorRequestViewSet(ExtendedModelViewSet): queryset = AuthorRequest.objects.all() diff --git a/apps/course/templates/course/lesson.html b/apps/course/templates/course/lesson.html index 18e51e78..9e79279d 100644 --- a/apps/course/templates/course/lesson.html +++ b/apps/course/templates/course/lesson.html @@ -96,7 +96,7 @@
Задавайте вопросы:
-
-
-
-
Задавайте вопросы:
-
- {% if request.user.is_authenticated %} -
-
- -
-
-
- -
- -
-
- {% else %} -
Только зарегистрированные пользователи могут оставлять комментарии.
- {% endif %} -
- {% include "templates/blocks/comments.html" with object=lesson %} -
-
-
-
{% include 'templates/blocks/share.html' %} diff --git a/project/pusher.py b/project/pusher.py new file mode 100644 index 00000000..af6c74a8 --- /dev/null +++ b/project/pusher.py @@ -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) diff --git a/project/settings.py b/project/settings.py index 9323745c..80c9e4ce 100644 --- a/project/settings.py +++ b/project/settings.py @@ -194,6 +194,13 @@ TWILIO_FROM_PHONE = os.getenv('TWILIO_FROM_PHONE', '+37128914409') ACTIVE_LINK_STRICT = True +# PUSHER settings + +PUSHER_APP_ID = u"" +PUSHER_KEY = u"" +PUSHER_SECRET = u"" +PUSHER_CLUSTER = u"" + # DRF settings REST_FRAMEWORK = { diff --git a/project/templates/lilcity/index.html b/project/templates/lilcity/index.html index 5d7b9d2d..187cd913 100644 --- a/project/templates/lilcity/index.html +++ b/project/templates/lilcity/index.html @@ -38,6 +38,7 @@ {% endcompress %} + + + diff --git a/web/src/components/CommentForm.vue b/web/src/components/CommentForm.vue new file mode 100644 index 00000000..80041646 --- /dev/null +++ b/web/src/components/CommentForm.vue @@ -0,0 +1,42 @@ + + + + diff --git a/web/src/components/Comments.vue b/web/src/components/Comments.vue index dcbf2a0d..40c7ea60 100644 --- a/web/src/components/Comments.vue +++ b/web/src/components/Comments.vue @@ -1,97 +1,142 @@ + + diff --git a/web/src/js/modules/api.js b/web/src/js/modules/api.js index 003153a3..7aa95c8a 100644 --- a/web/src/js/modules/api.js +++ b/web/src/js/modules/api.js @@ -513,11 +513,18 @@ export const api = { } }); }, - addComment: (objId, objType, commentJson, accessToken) => { + addObjComment: (objId, objType, commentJson, accessToken) => { let data = commentJson; data.obj_id = objId; data.obj_type = objType; - return api.post('/api/v1/comments/', data, { + return api.post('/api/v1/obj-comments/', data, { + headers: { + 'Authorization': `Token ${accessToken}`, + } + }); + }, + removeComment: (commentId, accessToken) => { + return api.delete(`/api/v1/comments/${commentId}/`, { headers: { 'Authorization': `Token ${accessToken}`, } diff --git a/web/webpack.config.js b/web/webpack.config.js index 3d47d057..8cd8b8f4 100644 --- a/web/webpack.config.js +++ b/web/webpack.config.js @@ -9,7 +9,6 @@ module.exports = { entry: { app: "./src/js/app.js", courseRedactor: "./src/js/course-redactor.js", - comments_vue: "./src/js/modules/comments_vue.js", mixpanel: "./src/js/third_party/mixpanel-2-latest.js", sprite: glob('./src/icons/*.svg'), images: glob('./src/img/*'), @@ -118,7 +117,8 @@ module.exports = { watch: NODE_ENV === 'development', watchOptions: { - poll: true, + ignored: "/node_modules/", + poll: 2000, }, devtool: NODE_ENV === 'development' ? 'source-map' : false