Skip to content

Commit 9bbc142

Browse files
authored
Merge pull request #89 from pythonkr/feature/lightning-talk
라이트닝 토크 신청 기능 추가
2 parents 13e2704 + 83c224b commit 9bbc142

11 files changed

+254
-10
lines changed

program/admin.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from import_export.admin import ImportExportModelAdmin, ImportMixin
1212
from .models import (Room, Program, ProgramTime, ProgramDate, ProgramCategory,
1313
Speaker, Preference, Proposal, TutorialProposal, SprintProposal,
14-
TutorialCheckin, SprintCheckin, OpenReview)
14+
TutorialCheckin, SprintCheckin, OpenReview, LightningTalk)
1515

1616

1717
class RoomAdmin(SummernoteModelAdmin, TranslationAdmin):
@@ -145,3 +145,17 @@ def user(self, o):
145145

146146

147147
admin.site.register(OpenReview, OpenReviewAdmin)
148+
149+
150+
class LightningTalkAdminForm(forms.ModelForm):
151+
class Meta:
152+
model = LightningTalk
153+
fields = '__all__'
154+
155+
156+
class LightningTalkAdmin(admin.ModelAdmin):
157+
form = LightningTalkAdminForm
158+
list_display = ('owner', 'title', 'day', 'accepted', 'created_at')
159+
160+
161+
admin.site.register(LightningTalk, LightningTalkAdmin)

program/forms.py

+20-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from django_summernote.widgets import SummernoteInplaceWidget
88
from django.utils.translation import ugettext_lazy as _
99
from django.core.files.images import get_image_dimensions
10-
from .models import Speaker, Program, Proposal, OpenReview, SprintProposal, TutorialProposal, ProgramCategory
10+
from .models import Speaker, Program, Proposal, OpenReview, SprintProposal, TutorialProposal, ProgramCategory, LightningTalk
1111

1212
from constance import config
1313

@@ -192,4 +192,22 @@ class Meta:
192192
fields = ('comment', )
193193
labels = {
194194
'comment': _('Comment')
195-
}
195+
}
196+
197+
198+
class LightningTalkForm(forms.ModelForm):
199+
def __init__(self, *args, **kwargs):
200+
super(LightningTalkForm, self).__init__(*args, **kwargs)
201+
self.helper = FormHelper()
202+
self.helper.form_method = 'post'
203+
self.helper.add_input(Submit('submit', _('Submit')))
204+
205+
class Meta:
206+
model = LightningTalk
207+
fields = ('title', 'slide_url', 'day', 'comment',)
208+
labels = {
209+
'title': _('발표 제목'),
210+
'slide_url': _('발표 슬라이드 URL'),
211+
'day': _('발표 요일'),
212+
'comment': _('준비위원회에게 남기고 싶은 말'),
213+
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Generated by Django 2.2.13 on 2020-07-12 09:05
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12+
('program', '0003_auto_20200706_1634'),
13+
]
14+
15+
operations = [
16+
migrations.CreateModel(
17+
name='LightningTalk',
18+
fields=[
19+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20+
('title', models.CharField(help_text='라이트닝 토크 제목', max_length=255, null=True)),
21+
('slide_url', models.CharField(max_length=511, null=True)),
22+
('day', models.IntegerField(choices=[(1, '토요일'), (2, '일요일')])),
23+
('comment', models.TextField(blank=True, default='')),
24+
('accepted', models.BooleanField(default=False)),
25+
('created_at', models.DateTimeField(auto_now_add=True)),
26+
('owner', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
27+
],
28+
options={
29+
'ordering': ['created_at'],
30+
},
31+
),
32+
]

program/models.py

+21
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from django.contrib.auth import get_user_model
55
from registration.models import Option
66
from django.urls import reverse
7+
78
User = get_user_model()
89

910

@@ -339,3 +340,23 @@ class SprintCheckin(models.Model):
339340

340341
class Meta:
341342
unique_together = ('user', 'sprint')
343+
344+
345+
class LightningTalk(models.Model):
346+
class Meta:
347+
ordering = ['created_at', ]
348+
349+
title = models.CharField(max_length=255, null=True, help_text='라이트닝 토크 제목')
350+
owner = models.OneToOneField(User, blank=True, null=True, on_delete=models.SET_NULL)
351+
slide_url = models.CharField(max_length=511, null=True)
352+
day = models.IntegerField(choices=(
353+
(1, _('토요일')),
354+
(2, _('일요일')),
355+
))
356+
comment = models.TextField(blank=True, default='')
357+
358+
accepted = models.BooleanField(default=False)
359+
created_at = models.DateTimeField(auto_now_add=True)
360+
361+
def __str__(self):
362+
return self.title

program/urls.py

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from .views import schedule, youngcoder, child_care, tutorial_join, sprint_join
1010

1111
from django.contrib import admin
12+
1213
admin.autodiscover()
1314

1415
urlpatterns = [

program/views.py

+93-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
from django.views.generic.edit import ModelFormMixin
99

1010
from .models import Program, ProgramCategory, Preference, Speaker, Room, Proposal, OpenReview, \
11-
TutorialProposal, SprintProposal
11+
TutorialProposal, SprintProposal, LightningTalk
1212
from .forms import SpeakerForm, SprintProposalForm, TutorialProposalForm, ProposalForm, \
13-
OpenReviewCategoryForm, OpenReviewCommentForm, ProgramForm
13+
OpenReviewCategoryForm, OpenReviewCommentForm, ProgramForm, LightningTalkForm
1414

1515
import constance
1616
import datetime
@@ -592,3 +592,94 @@ def is_proposal_opened(request):
592592
flag = 1
593593

594594
return flag
595+
596+
597+
def is_lightning_talk_proposable(request):
598+
KST = datetime.timezone(datetime.timedelta(hours=9))
599+
now = datetime.datetime.now(tz=KST)
600+
LT_open_at = constance.config.LIGHTNING_TALK_OPEN.replace(tzinfo=KST)
601+
LT_close_at = constance.config.LIGHTNING_TALK_CLOSE.replace(tzinfo=KST)
602+
if LT_open_at < now < LT_close_at:
603+
return True
604+
else:
605+
return False
606+
607+
608+
class LightningTalkHome(TemplateView):
609+
template_name = "pyconkr/lightning_talk_home.html"
610+
611+
def get_context_data(self, **kwargs):
612+
context = super().get_context_data(**kwargs)
613+
614+
KST = datetime.timezone(datetime.timedelta(hours=9))
615+
context['LT_open_at'] = constance.config.LIGHTNING_TALK_OPEN.replace(tzinfo=KST)
616+
context['LT_close_at'] = constance.config.LIGHTNING_TALK_CLOSE.replace(tzinfo=KST)
617+
context['is_proposable'] = is_lightning_talk_proposable(self.request)
618+
619+
return context
620+
621+
622+
class LightningTalkCreate(CreateView):
623+
form_class = LightningTalkForm
624+
template_name = "pyconkr/lightning_talk_form.html"
625+
626+
def form_valid(self, form):
627+
form.instance.owner = self.request.user
628+
form.save()
629+
return super(LightningTalkCreate, self).form_valid(form)
630+
631+
def get(self, request, *args, **kwargs):
632+
return super(LightningTalkCreate, self).get(request, *args, **kwargs)
633+
634+
def dispatch(self, request, *args, **kwargs):
635+
if request.user.profile.name == '':
636+
return redirect('profile_edit')
637+
638+
if not is_lightning_talk_proposable(self.request):
639+
return redirect('lightning-talk')
640+
641+
if LightningTalk.objects.filter(owner=self.request.user).exists():
642+
return redirect('lightning-talk-detail')
643+
644+
return super(LightningTalkCreate, self).dispatch(request, *args, **kwargs)
645+
646+
def get_success_url(self):
647+
return reverse('lightning-talk-detail')
648+
649+
650+
class LightningTalkDetail(TemplateView):
651+
template_name = "pyconkr/lightning_talk_detail.html"
652+
653+
def dispatch(self, request, *args, **kwargs):
654+
if not LightningTalk.objects.filter(owner=self.request.user).exists():
655+
return redirect('lightning-talk')
656+
return super(LightningTalkDetail, self).dispatch(request, *args, **kwargs)
657+
658+
def get_context_data(self, **kwargs):
659+
context = super(LightningTalkDetail, self).get_context_data(**kwargs)
660+
context['title'] = _("Lightning Talk Proposal")
661+
context['talk'] = LightningTalk.objects.get(owner=self.request.user)
662+
context['is_editable'] = is_lightning_talk_proposable(self.request)
663+
return context
664+
665+
666+
class LightningTalkUpdate(UpdateView):
667+
model = LightningTalk
668+
form_class = LightningTalkForm
669+
template_name = "pyconkr/lightning_talk_form.html"
670+
671+
def dispatch(self, request, *args, **kwargs):
672+
if not LightningTalk.objects.filter(owner=self.request.user).exists() or not is_lightning_talk_proposable(
673+
self.request):
674+
return redirect('lightning-talk')
675+
if LightningTalk.objects.get(id=self.kwargs['pk']).owner != self.request.user:
676+
return redirect('lightning-talk')
677+
678+
return super(LightningTalkUpdate, self).dispatch(request, *args, **kwargs)
679+
680+
def get_context_data(self, **kwargs):
681+
context = super(LightningTalkUpdate, self).get_context_data(**kwargs)
682+
return context
683+
684+
def get_success_url(self):
685+
return reverse('lightning-talk-detail')

pyconkr/context_processors.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def default(request):
5757
'submenu': OrderedDict([
5858
('keynote', {'title': _('Keynotes'), 'disable': True}),
5959
('talks', {'title': _('Talks')}),
60-
('lightning-talk', {'title': _('Lightning Talk'), 'disable': True}),
60+
('lightning-talk', {'title': _('Lightning Talk')}),
6161
('openspace', {'title': _('Open Spaces'), 'disable': True}),
6262
('tutorial', {'title': _('Tutorial'), 'disable': True}),
6363
('sprint', {'title': _('Sprint'), 'disable': True}),
@@ -85,8 +85,8 @@ def default(request):
8585
('cfp', {'title': _('Proposing a Talk')}),
8686
('review-talk-proposal',
8787
{'title': _('Review Talk Proposal')}),
88-
('proposing-tutorial',
89-
{'title': _('Proposing a Tutorial'), 'disable': True}),
88+
('lightning-talk/home',
89+
{'title': _('Proposing a Lightning Talk')}),
9090
('recommending-keynote',
9191
{'title': _('Recommending Keynote')}),
9292
('volunteer', {'title': _('Volunteer'), 'disable': True}),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{% extends "base.html" %}
2+
{% load i18n %}
3+
4+
{% block content %}
5+
<div class="row proposal-detail">
6+
<h3>
7+
{{ talk.title }}
8+
</h3>
9+
<br>
10+
<div>
11+
<h4>{% trans "Slide URL" %}</h4>
12+
{{ talk.slide_url }}
13+
</div>
14+
{% if is_editable %}
15+
<div class="a_btn_container">
16+
<a class="a_btn" href="{% url 'lightning-talk-edit' talk.id %}">{% trans "수정하기" %}</a>
17+
</div>
18+
{% endif %}
19+
</div>
20+
{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{% extends "base.html" %}
2+
{% load crispy_forms_tags i18n %}
3+
4+
{% block title %}
5+
{% trans "라이트닝 토크 신청하기" %}
6+
{% endblock %}
7+
8+
{% block content %}
9+
{% crispy form %}
10+
{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{% extends "base.html" %}
2+
{% load i18n %}
3+
4+
{% block title %}
5+
{% trans "Proposing a Lightning Talk" %}
6+
{% endblock %}
7+
8+
{% block content %}
9+
<p>
10+
{% trans "누구나 파이콘 한국 2020에 제출된 발표 제안 내용들을 검토하고 의견을 남겨주실 수 있습니다." %}
11+
</p>
12+
<p>
13+
{% trans "여러분의 손으로 풍성한 파이콘 한국을 만들어주세요 :)" %}
14+
</p>
15+
16+
<h2>{% trans "일정" %}</h2>
17+
<p>
18+
{{ LT_open_at|date:_("Y년 F j일 (D) H:i") }} - {{ LT_close_at|date:_("Y년 F j일 (D) H:i") }}
19+
</p>
20+
21+
<h2>{% trans "문의" %}</h2>
22+
<p><a href="mailto:[email protected]" target="_blank">[email protected]</a></p>
23+
24+
{% if is_proposable %}
25+
<div class="a_btn_container">
26+
<a class="a_btn large" href="{% url 'lightning-talk-propose' %}">{% trans "신청하기" %}</a>
27+
</div>
28+
{% endif %}
29+
{% endblock %}

pyconkr/urls.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
from .views import login, logout
1313
from .views import PatronList
1414

15-
from program.views import ProposalCreate, OpenReviewUpdate
16-
from program.views import OpenReviewList, OpenReviewHome, ContributionHome
15+
from program.views import ProposalCreate, OpenReviewUpdate, OpenReviewList, OpenReviewHome, ContributionHome, \
16+
LightningTalkCreate, LightningTalkHome, LightningTalkDetail, LightningTalkUpdate
1717

1818
from django.contrib import admin
1919

@@ -53,6 +53,14 @@
5353
login_required(OpenReviewList.as_view()), name='openreview-list'),
5454
re_path(r'^2020/contribution/review-talk-proposal/review/(?P<pk>\d+)$',
5555
login_required(OpenReviewUpdate.as_view()), name='openreview-update'),
56+
re_path(r'^2020/contribution/lightning-talk/home/$',
57+
login_required(LightningTalkHome.as_view()), name='lightning-talk'),
58+
re_path(r'^2020/contribution/lightning-talk/propose/$',
59+
login_required(LightningTalkCreate.as_view()), name='lightning-talk-propose'),
60+
re_path(r'^2020/contribution/lightning-talk/detail/$',
61+
login_required(LightningTalkDetail.as_view()), name='lightning-talk-detail'),
62+
re_path(r'^2020/contribution/lightning-talk/edit/(?P<pk>\d+)$',
63+
login_required(LightningTalkUpdate.as_view()), name='lightning-talk-edit'),
5664

5765
# for flatpages
5866
re_path(r'^(?P<url>.*/)$', views.flatpage, name='flatpage'),

0 commit comments

Comments
 (0)