Commit b1acadc0 authored by Matheus Miranda's avatar Matheus Miranda

Merge branch 'develop' into 'master'

Add courses components

See merge request !40
parents e8d75c73 c1b458ee
......@@ -2,12 +2,16 @@ from django.contrib.auth import get_user_model
from rest_framework import serializers
from .videos.serializers import VideoSerializer
from courses_learning_objects.serializers import LearningObjectSerializer as ActivitySerializer
from .models import (
Course,
CourseProfessor,
ProfessorMessage,
ProfessorMessageRead,
CourseTrack,
CourseStudent,
Unit,
Lesson
)
......@@ -33,15 +37,19 @@ class CourseSerializer(serializers.ModelSerializer):
is_user_coordinator = serializers.SerializerMethodField()
is_assistant_or_coordinator = serializers.SerializerMethodField()
track = serializers.SerializerMethodField()
is_user_enrolled = serializers.SerializerMethodField()
enroll_course_url = serializers.SerializerMethodField()
user_done_units = serializers.SerializerMethodField()
class Meta:
model = Course
fields = ("id", "slug", "name", "intro_video", "application", "requirement",
"abstract", "structure", "workload", "status", "is_public",
"thumbnail_url", "home_thumbnail_url", "home_position",
"start_date", "home_published", "authors_names", "has_started",
"min_percent_to_complete", "is_user_assistant", "is_user_coordinator",
"is_assistant_or_coordinator", 'professors', 'track',)
fields = ('id', 'slug', 'name', 'intro_video', 'application', 'requirement',
'abstract', 'structure', 'workload', 'status', 'is_public',
'thumbnail_url', 'home_thumbnail_url', 'home_position',
'start_date', 'home_published', 'authors_names', 'has_started',
'min_percent_to_complete', 'is_user_assistant', 'is_user_coordinator',
'is_assistant_or_coordinator', 'professors', 'track', 'forum_id',
'is_user_enrolled', 'enroll_course_url', 'user_done_units')
@staticmethod
def get_home_thumbnail_url(obj):
......@@ -58,6 +66,45 @@ class CourseSerializer(serializers.ModelSerializer):
def get_is_assistant_or_coordinator(self, obj):
return obj.is_assistant_or_coordinator(self.context['request'].user)
def get_is_user_enrolled(self, obj):
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
return CourseStudent.objects.filter(course=obj, user=user).exists()
def get_user_done_units(self, obj):
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
if CourseStudent.objects.filter(course=obj, user=user).exists():
return CourseStudent.objects.filter(course=obj, user=user).first().units_done
def get_enroll_course_url(self, obj):
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
else:
return ''
course = obj
if course.is_enrolled(user):
return 'resume_course'
if course.status == 'draft':
return 'courses'
if user.accepted_terms or not settings.TERMS_ACCEPTANCE_REQUIRED:
course.enroll_student(user)
if course.has_started and course.first_lesson():
return 'lesson'
else:
return 'course_home'
else:
'accept_terms'
def get_track(self, obj):
course_track = CourseTrack.objects.filter(courses=obj)
if course_track:
......@@ -159,3 +206,83 @@ class ProfessorMessageSerializer(serializers.ModelSerializer):
return read_state.is_read
except ProfessorMessageRead.DoesNotExist as e:
return False
class UnitSerializer(serializers.ModelSerializer):
video = VideoSerializer(required=False, allow_null=True)
activities = ActivitySerializer(many=True, required=False, allow_null=True)
class Meta:
model = Unit
fields = ('id', 'title', 'video', 'activities', 'side_notes', 'position', 'chat_room',)
class LessonSerializer(serializers.ModelSerializer):
units = UnitSerializer(many=True)
is_course_last_lesson = serializers.BooleanField(read_only=True)
thumbnail_url = serializers.ReadOnlyField()
class Meta:
model = Lesson
fields = ('id', 'course', 'is_course_last_lesson', 'desc',
'name', 'notes', 'position', 'slug', 'status', 'units',
'thumbnail_url')
def update(self, instance, validated_data):
units = self.update_units(self.initial_data.get('units'), instance)
for old_unit in instance.units.all():
if old_unit not in units:
old_unit.delete()
else:
new_activities = units[units.index(old_unit)].activities
if old_unit.activities != new_activities:
for activity in old_unit.activities:
if activity not in new_activities:
activity.delete()
validated_data.pop('units')
return super(LessonSerializer, self).update(instance, validated_data)
def create(self, validated_data):
units_data = validated_data.pop('units')
new_lesson = super(LessonSerializer, self).create(validated_data)
# units_data = self.initial_data.get('units')
self.update_units(units_data, new_lesson)
return new_lesson
@classmethod
def update_units(cls, units_data, lesson):
units = []
for unit_data in units_data:
activities_data = unit_data.pop('activities', None)
unit_data.pop('lesson', None)
video_data = unit_data.pop('video', None)
if video_data:
video = Video(**video_data)
video.save()
else:
video = None
unit = Unit(lesson=lesson, video=video, **unit_data)
unit.save()
if activities_data:
activities = []
for activity_data in activities_data:
activity_id = activity_data.pop('id', None)
activity, _ = Activity.objects.get_or_create(id=activity_id)
activity.comment = activity_data.get('comment', None)
activity.data = activity_data.get('data', None)
activity.expected = activity_data.get('expected', None)
activity.type = activity_data.get('type', None)
activity.unit = unit
activity.save()
activities.append(activity)
unit.activities.set(activities)
units.append(unit)
return units
......@@ -5,10 +5,11 @@ from rest_framework import routers
from .views import (
CourseViewSet, BaseCourseProfessorViewSet,
CourseBySlugViewSet,
ProfessorMessageViewSet,
ProfessorMessageReadViewSet,
ProfessorGlobalMessageViewSet,
MyCoursesViewSet
MyCoursesViewSet, LessonViewSet
)
from .course_material.views import CourseMaterialViewSet, CourseMaterialFileViewSet
from .import_export.views import ExportCourseView, ImportCourseView
......@@ -44,7 +45,10 @@ router.register(r'course', CourseViewSet, base_name='course')
router.register(r'my-courses', MyCoursesViewSet, base_name='my-courses')
router.register(r'course_material', CourseMaterialViewSet, base_name='course_material')
router.register(r'course_material_file', CourseMaterialFileViewSet, base_name='course_material_file')
router.register(r'course-by-slug', CourseBySlugViewSet, base_name='course_by_slug'),
# Lessons
router.register(r'course-lessons/(?P<course_id>[1-9][0-9]*)', LessonViewSet, base_name='lessons')
# Workspaces
router.register(r'workspaces', WorkspaceViewSet)
......
......@@ -7,10 +7,12 @@ from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import list_route
from .models import (Course, CourseProfessor, CourseStudent, ProfessorMessage, ProfessorMessageRead, Class)
from .models import (Course, CourseProfessor, CourseStudent, ProfessorMessage,
ProfessorMessageRead, Class, Lesson)
from .serializers import (CourseSerializer, BasicCourseProfessorSerializer,
ProfessorMessageSerializer, ProfessorMessageReadSerializer,
)
LessonSerializer)
from courses.workspaces.serializers import CourseGroupSerializer
......@@ -20,8 +22,9 @@ from .permissions import (
IsAdminOrReadOnly,
)
class CourseGroupViewSet(viewsets.ModelViewSet):
model = Course
queryset = Course.objects.all()
serializer_class = CourseGroupSerializer
......@@ -32,7 +35,7 @@ class CourseGroupViewSet(viewsets.ModelViewSet):
if course:
queryset = queryset.filter(groups__id = course)
return queryset
......@@ -111,6 +114,14 @@ class MyCoursesViewSet(viewsets.ModelViewSet):
return queryset
class CourseBySlugViewSet(viewsets.ModelViewSet):
model = Course
queryset = Course.objects.all()
serializer_class = CourseSerializer
permission_classes = (IsAuthenticated,)
lookup_field = 'slug'
class BaseCourseProfessorViewSet(viewsets.ModelViewSet):
model = CourseProfessor
......@@ -182,7 +193,7 @@ class ProfessorMessageViewSet(viewsets.ModelViewSet):
queryset = queryset[:int(limit_to)]
return queryset.prefetch_related('classrooms', 'classes', 'users', 'groups',).select_related('course', 'professor')
@list_route(methods=['get'], permission_classes=[IsAssistantOrCoordinatorOrAdminOrRecipient])
def count_message(self, request):
messages = self.get_queryset()
......@@ -201,7 +212,7 @@ class ProfessorGlobalMessageViewSet(ProfessorMessageViewSet):
def perform_create(self, serializer):
User = get_user_model()
users_to_be_added = []
all_students = serializer.context['request'].data.get('all_students', None)
recipients = serializer.context['request'].data.get('users', None)
groups = serializer.context['request'].data.get('groups', None)
......@@ -244,3 +255,15 @@ class ProfessorMessageReadViewSet(viewsets.ModelViewSet):
queryset = queryset[:int(limit_to)]
return queryset
class LessonViewSet(viewsets.ModelViewSet):
model = Lesson
queryset = Lesson.objects.all()
serializer_class = LessonSerializer
ordering = ('position',)
def get_queryset(self):
queryset = super(LessonViewSet, self).get_queryset()
course_id = self.kwargs['course_id']
return queryset.filter(status='published', course_id=course_id)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment