diff --git a/pythonpro/cohorts/admin.py b/pythonpro/cohorts/admin.py
index 3bed0b41..e5e60767 100644
--- a/pythonpro/cohorts/admin.py
+++ b/pythonpro/cohorts/admin.py
@@ -1,9 +1,22 @@
from django.contrib import admin
+from django.utils.safestring import mark_safe
-from pythonpro.cohorts.models import Cohort
+from pythonpro.cohorts.models import Cohort, LiveClass
+
+
+class ClassInline(admin.TabularInline):
+ extra = 1
+ model = LiveClass
@admin.register(Cohort)
class ModuleAdmin(admin.ModelAdmin):
- list_display = 'title start end'.split()
+ inlines = [ClassInline]
+ prepopulated_fields = {'slug': ('title',)}
+ list_display = 'title start end page_link'.split()
ordering = ('-start',)
+
+ def page_link(self, cohort):
+ return mark_safe(f'See on Page')
+
+ page_link.short_description = 'page'
diff --git a/pythonpro/cohorts/facade.py b/pythonpro/cohorts/facade.py
index 44c3e072..7385a9fa 100644
--- a/pythonpro/cohorts/facade.py
+++ b/pythonpro/cohorts/facade.py
@@ -1,5 +1,15 @@
-from pythonpro.cohorts.models import Cohort as _Cohort
+from django.db.models import Prefetch
+
+from pythonpro.cohorts.models import Cohort as _Cohort, LiveClass
def get_all_cohorts_desc():
return tuple(_Cohort.objects.order_by('-start'))
+
+
+def find_cohort(slug):
+ return _Cohort.objects.filter(slug=slug).prefetch_related(Prefetch(
+ 'liveclass_set',
+ queryset=LiveClass.objects.order_by('start'),
+ to_attr='classes'
+ )).get()
diff --git a/pythonpro/cohorts/migrations/0002_liveclass.py b/pythonpro/cohorts/migrations/0002_liveclass.py
new file mode 100644
index 00000000..90c467a1
--- /dev/null
+++ b/pythonpro/cohorts/migrations/0002_liveclass.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.0.6 on 2018-06-04 17:53
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('cohorts', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='LiveClass',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('start', models.DateTimeField()),
+ ('vimeo_id', models.CharField(blank=True, max_length=11)),
+ ('cohort', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cohorts.Cohort')),
+ ],
+ ),
+ ]
diff --git a/pythonpro/cohorts/models.py b/pythonpro/cohorts/models.py
index 38c8dc86..219f2d40 100644
--- a/pythonpro/cohorts/models.py
+++ b/pythonpro/cohorts/models.py
@@ -23,3 +23,9 @@ def get_absolute_url(self):
class CohortStudent(models.Model):
cohort = models.ForeignKey(Cohort, on_delete=models.DO_NOTHING)
user = models.ForeignKey(get_user_model(), on_delete=models.DO_NOTHING)
+
+
+class LiveClass(models.Model):
+ start = models.DateTimeField()
+ vimeo_id = models.CharField(max_length=11, db_index=False, blank=True)
+ cohort = models.ForeignKey(Cohort, models.CASCADE)
diff --git a/pythonpro/cohorts/templates/cohorts/cohort_detail.html b/pythonpro/cohorts/templates/cohorts/cohort_detail.html
index 02eaa96a..73d67ccd 100644
--- a/pythonpro/cohorts/templates/cohorts/cohort_detail.html
+++ b/pythonpro/cohorts/templates/cohorts/cohort_detail.html
@@ -38,7 +38,28 @@
Intruções
Passo 2
Se apresente no post do fórum
Passo 3
- Entre no nosso grupo do Telegram para tirar dúvidas e interagir!
+ Entre no nosso grupo do
+ Telegram para tirar dúvidas e interagir!
+
+
+
+
+
+
Aulas ao Vivo
+ {% for class in cohort.classes %}
+
{{ class.start }}
+
+ {% if class.vimeo_id %}
+
+
+
+ {% else %}
+ Upload de Vídeo Pendente
+ {% endif %}
+
+ {% endfor %}
diff --git a/pythonpro/cohorts/tests/__init__.py b/pythonpro/cohorts/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/pythonpro/cohorts/tests.py b/pythonpro/cohorts/tests/test_cohorts.py
similarity index 72%
rename from pythonpro/cohorts/tests.py
rename to pythonpro/cohorts/tests/test_cohorts.py
index 5e5ba8d9..2358de62 100644
--- a/pythonpro/cohorts/tests.py
+++ b/pythonpro/cohorts/tests/test_cohorts.py
@@ -1,3 +1,5 @@
+import operator
+from datetime import datetime, timedelta
from os import path
import pytest
@@ -7,7 +9,8 @@
from model_mommy import mommy
from pythonpro import settings
-from pythonpro.cohorts.models import Cohort
+from pythonpro.cohorts import facade
+from pythonpro.cohorts.models import Cohort, LiveClass
from pythonpro.django_assertions import dj_assert_contains, dj_assert_not_contains
_img_path = path.join(settings.BASE_DIR, 'pythonpro', 'core', 'static', 'img', 'instructors', 'renzo-nuccitelli.png')
@@ -82,3 +85,33 @@ def test_cohort_start(cohort: Cohort, resp):
def test_cohort_end(cohort: Cohort, resp):
dj_assert_contains(resp, date(cohort.end))
+
+
+@pytest.fixture
+def live_classes(cohort):
+ now = datetime.now()
+ return [
+ mommy.make(LiveClass, cohort=cohort, vimeo_id=str(i), start=now + timedelta(days=i)) for i in range(100, 105)
+ ]
+
+
+@pytest.fixture
+def resp_with_classes(live_classes, cohort, client):
+ assert len(live_classes) > 0
+ return client.get(reverse('cohorts:detail', kwargs={'slug': cohort.slug}), secure=True)
+
+
+def test_live_classes_are_sorted(live_classes: list, cohort):
+ live_classes.sort(key=operator.attrgetter('start'))
+ db_cohort = facade.find_cohort(slug=cohort.slug)
+ assert live_classes == db_cohort.classes
+
+
+def test_live_classes_datetime(resp_with_classes, live_classes):
+ for live_class in live_classes:
+ dj_assert_contains(resp_with_classes, date(live_class.start))
+
+
+def test_live_classes_vimeo(resp_with_classes, live_classes):
+ for live_class in live_classes:
+ dj_assert_contains(resp_with_classes, live_class.vimeo_id)
diff --git a/pythonpro/cohorts/views.py b/pythonpro/cohorts/views.py
index 13ae33d8..104c4de9 100644
--- a/pythonpro/cohorts/views.py
+++ b/pythonpro/cohorts/views.py
@@ -1,10 +1,9 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
-# Create your views here.
-from pythonpro.cohorts.models import Cohort
+from pythonpro.cohorts import facade
@login_required
def detail(request, slug):
- return render(request, 'cohorts/cohort_detail.html', {'cohort': Cohort.objects.get(slug=slug)})
+ return render(request, 'cohorts/cohort_detail.html', {'cohort': facade.find_cohort(slug=slug)})
diff --git a/pythonpro/modules/admin.py b/pythonpro/modules/admin.py
index d4ec764b..a3ee8c08 100644
--- a/pythonpro/modules/admin.py
+++ b/pythonpro/modules/admin.py
@@ -1,26 +1,34 @@
from django.contrib import admin
+from django.utils.safestring import mark_safe
from ordered_model.admin import OrderedModelAdmin
from pythonpro.modules.models import Section, Module, Chapter, Topic
-class ModuleAdmin(OrderedModelAdmin):
- list_display = 'title slug order move_up_down_links'.split()
+class BaseAdmin(OrderedModelAdmin):
+ prepopulated_fields = {'slug': ('title',)}
+ def page_link(self, content):
+ return mark_safe(f'See on Page')
-class SectionAdmin(OrderedModelAdmin):
- list_display = 'title slug module order move_up_down_links'.split()
+ page_link.short_description = 'page'
-class ChapterAdmin(OrderedModelAdmin):
- list_display = 'title slug section order move_up_down_links'.split()
+@admin.register(Module)
+class ModuleAdmin(BaseAdmin):
+ list_display = 'title slug order move_up_down_links page_link'.split()
-class TopicAdmin(OrderedModelAdmin):
- list_display = 'title slug chapter order move_up_down_links'.split()
+@admin.register(Section)
+class SectionAdmin(BaseAdmin):
+ list_display = 'title slug module order move_up_down_links page_link'.split()
-admin.site.register(Module, ModuleAdmin)
-admin.site.register(Section, SectionAdmin)
-admin.site.register(Chapter, ChapterAdmin)
-admin.site.register(Topic, TopicAdmin)
+@admin.register(Chapter)
+class ChapterAdmin(BaseAdmin):
+ list_display = 'title slug section order move_up_down_links page_link'.split()
+
+
+@admin.register(Topic)
+class TopicAdmin(BaseAdmin):
+ list_display = 'title slug chapter order move_up_down_links page_link'.split()