Add user management of their speaker bios and talks

This commit is contained in:
Michael Hall 2018-04-24 10:22:16 -04:00
parent e45c0370a1
commit 5f16e176f9
18 changed files with 625 additions and 15 deletions

View file

@ -133,7 +133,17 @@ class TopicAdmin(admin.ModelAdmin):
exclude = ('slug', )
admin.site.register(Topic, TopicAdmin)
admin.site.register(Speaker)
admin.site.register(Talk)
admin.site.register(Presentation)
class SpeakerAdmin(admin.ModelAdmin):
list_display = ('title', 'user', 'avatar')
admin.site.register(Speaker, SpeakerAdmin)
class TalkAdmin(admin.ModelAdmin):
list_display = ('title', 'speaker', 'category')
list_filter = ('category',)
admin.site.register(Talk, TalkAdmin)
class PresentationAdmin(admin.ModelAdmin):
list_display = ('talk', 'status', 'event')
list_filter = ('status',)
admin.site.register(Presentation, PresentationAdmin)

View file

@ -6,8 +6,17 @@ from django.utils import timezone
from django.contrib.auth.models import User
from .models.locale import Country, SPR, City
from .models.profiles import Team, UserProfile
from .models.events import Event, EventComment ,CommonEvent, EventSeries, Place, EventPhoto
from .models.profiles import Team, UserProfile, Speaker, Talk
from .models.events import (
Event,
EventComment,
CommonEvent,
EventSeries,
Place,
EventPhoto,
Presentation,
SpeakerRequest,
)
import recurrence
import pytz
@ -329,3 +338,21 @@ class NewCommonEventForm(forms.ModelForm):
'end_time': DateTimeWidget
}
class SpeakerBioForm(forms.ModelForm):
class Meta:
model = Speaker
fields = ['avatar', 'title', 'bio', 'categories']
class UserTalkForm(forms.ModelForm):
class Meta:
model = Talk
fields = ['speaker', 'title', 'abstract', 'talk_type', 'web_url', 'category']
class DeleteTalkForm(forms.Form):
confirm = forms.BooleanField(label="Yes, delete series", required=True)
class SchedulePresentationForm(forms.ModelForm):
class Meta:
model = Presentation
fields = ['start_time']

View file

@ -1,7 +1,9 @@
# Generated by Django 2.0 on 2018-04-21 14:26
# Generated by Django 2.0 on 2018-04-22 21:23
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import imagekit.models.fields
class Migration(migrations.Migration):
@ -15,14 +17,19 @@ class Migration(migrations.Migration):
name='Presentation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('start_time', models.DateTimeField(db_index=True, verbose_name='Start Time')),
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.Event')),
('status', models.SmallIntegerField(choices=[(-1, 'Declined'), (0, 'Proposed'), (1, 'Accepted')], db_index=True, default=0)),
('start_time', models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='Start Time')),
('created_time', models.DateTimeField(db_index=True, default=django.utils.timezone.now)),
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='events.UserProfile')),
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='presentations', to='events.Event')),
],
),
migrations.CreateModel(
name='Speaker',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('avatar', imagekit.models.fields.ProcessedImageField(blank=True, upload_to='avatars', verbose_name='Photo Image')),
('title', models.CharField(blank=True, max_length=256, null=True)),
('bio', models.TextField(blank=True)),
],
),
@ -108,6 +115,6 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='presentation',
name='talk',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='events.Talk'),
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='presentations', to='events.Talk'),
),
]

View file

@ -381,9 +381,22 @@ class SpeakerRequest(models.Model):
topics = models.ManyToManyField('Topic', blank=True)
class Presentation(models.Model):
DECLINED=-1
PROPOSED=0
ACCEPTED=1
STATUSES = [
(DECLINED, _("Declined")),
(PROPOSED, _("Proposed")),
(ACCEPTED, _("Accepted")),
]
event = models.ForeignKey(Event, related_name='presentations', on_delete=models.CASCADE)
talk = models.ForeignKey(Talk, related_name='presentations', on_delete=models.SET_NULL, blank=False, null=True)
start_time = models.DateTimeField(verbose_name=_('Start Time'), db_index=True)
status = models.SmallIntegerField(choices=STATUSES, default=PROPOSED, db_index=True)
start_time = models.DateTimeField(verbose_name=_('Start Time'), db_index=True, null=True, blank=True)
created_by = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True, blank=False)
created_time = models.DateTimeField(default=timezone.now, db_index=True)
def __str__(self):
return '%s at %s' % (self.talk.title, self.event.name)

View file

@ -86,6 +86,10 @@ class UserProfile(models.Model):
def moderating(self):
return [member.team for member in Member.objects.filter(user=self, role__in=(Member.ADMIN, Member.MODERATOR))]
@property
def talks(self):
return Talk.objects.filter(speaker__user=self)
def can_create_event(self, team):
try:
if self.user.is_superuser:
@ -304,12 +308,26 @@ class Topic(models.Model):
class Speaker(models.Model):
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
bio = models.TextField(blank=True)
avatar = ProcessedImageField(verbose_name=_("Photo Image"),
upload_to='avatars',
processors=[ResizeToFill(128, 128)],
format='PNG',
blank=True)
title = models.CharField(max_length=256, blank=True, null=True)
bio = models.TextField(verbose_name=_('Biography'), blank=True)
categories = models.ManyToManyField('Category', blank=True)
topics = models.ManyToManyField('Topic', blank=True)
def headshot(self):
if self.avatar:
return self.avatar
else:
return self.user.avatar
def __str__(self):
if self.title:
return self.title
return self.user.__str__()
class Talk(models.Model):
@ -327,7 +345,7 @@ class Talk(models.Model):
(QANDA, _("Q & A")),
(DEMO, _("Demonstration")),
]
speaker = models.ForeignKey(Speaker, on_delete=models.CASCADE)
speaker = models.ForeignKey(Speaker, verbose_name=_('Speaker Bio'), on_delete=models.CASCADE)
title = models.CharField(max_length=256)
abstract = models.TextField()
talk_type = models.SmallIntegerField(_("Type"), choices=TYPES, default=PRESENTATION)
@ -336,6 +354,14 @@ class Talk(models.Model):
category = models.ForeignKey('Category', on_delete=models.SET_NULL, blank=False, null=True)
topics = models.ManyToManyField('Topic', blank=True)
@property
def future_presentations(self):
return self.presentations.filter(status__gte=0, event__start_time__gt=timezone.now())
@property
def past_presentations(self):
return self.presentations.filter(status=1, event__start_time__lte=timezone.now())
def __str__(self):
return self.title

View file

@ -94,6 +94,7 @@
</button>
<div class="dropdown-menu" aria-labelledby="editMenuButton">
<a href="{% url 'edit-event' event.id %}" class="dropdown-item">Event Details</a>
<a href="{% url 'edit-event' event.id %}" class="dropdown-item">Speakers</a>
</div>
</div>
{% endif %}
@ -146,6 +147,15 @@
</tr>
{% endif %}
<tr>
<td width="120px"><b>Presentations:</b></td>
<td>
{% for presentation in presentation_list %}
<div><a href="{% url 'show-talk' presentation.talk.id %}">{{presentation.talk.title}}</a> by <a href="{% url 'show-profile' presentation.talk.speaker.user.id %}">{{presentation.talk.speaker}}</a></div>
{% endfor %}
<a class="btn btn-primary btn-sm" href="{% url 'propose-event-talk' event.id %}">Propose a talk</a>
</td>
</tr>
</table>
<div class="container mt-3">

View file

@ -0,0 +1,20 @@
{% extends "get_together/base.html" %}
{% load static %}
{% block content %}
<h2>New Speaker</h2>
<form enctype="multipart/form-data" action="{% url "add-speaker" %}" method="post">
{% csrf_token %}
<div class="form-group">
<table class="table">
<tr><th></th><td><img src="{{speaker.headshot.url}}"/></td></tr>
{{speaker_form}}
</table>
<br />
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
{% endblock %}

View file

@ -0,0 +1,31 @@
{% extends "get_together/base.html" %}
{% load static %}
{% block content %}
<h2>New Talk</h2>
<form action="{% url "add-talk" %}" method="post">
{% csrf_token %}
<div class="form-group">
<table class="table">
{{talk_form}}
</table>
<br />
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
{% endblock %}
{% block javascript %}
<script type="text/javascript">
$(document).ready(function(){
$("#id_speaker").selectmenu()
$("#id_talk_type").selectmenu()
$("#id_category").selectmenu()
});
</script>
{% endblock %}

View file

@ -0,0 +1,20 @@
{% extends "get_together/base.html" %}
{% block content %}
<h2>Confirm deletion</h2>
{% if talk.future_presentations.count > 0 %}
<div class="alerts">
<div class="alert alert-danger">This talk has {{ talk.future_presentations.count }} pending event!</div>
</div>
{% endif %}
Are you sure you want to delete <strong>{{talk.title}}</strong>?
<form action="{% url "delete-talk" talk.id %}" method="post">
{% csrf_token %}
<div class="form-group">
{{ delete_form }}
<br />
<button type="submit" class="btn btn-danger">Delete Talk</button>
</div>
</form>
{% endblock %}

View file

@ -0,0 +1,46 @@
{% extends "get_together/base.html" %}
{% load static %}
{% block content %}
<h2>Edit Speaker</h2>
<form enctype="multipart/form-data" action="{% url "edit-speaker" speaker.id %}" method="post">
{% csrf_token %}
<div class="form-group">
<table class="table">
<tr><th></th><td><img src="{{speaker.headshot.url}}"/></td></tr>
{{speaker_form}}
</table>
<br />
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
{% endblock %}
{% block javascript %}
<script type="text/javascript">
$(document).ready(function(){
$("#city_select").lookup({
search: function(searchText, callback) {
if (searchText.length < 3) return callback(searchText, []);
$.getJSON("/api/cities/?q="+searchText, function(data) {
var m = this.url.match(/q=([^&]+)/);
var q = "";
if (m && m.length > 0) {
q = this.url.match(/q=([^&]+)/)[1]
}
return callback(q, data);
});
},
select: function( event, ui ) {
$("#id_tz").val(ui.data.tz);
$("#id_tz").selectmenu("refresh");
}
});
$("#id_categories").selectmenu()
});
</script>
{% endblock %}

View file

@ -0,0 +1,32 @@
{% extends "get_together/base.html" %}
{% load static %}
{% block content %}
<h2>Edit Talk</h2>
<form action="{% url "edit-talk" talk.id %}" method="post">
{% csrf_token %}
<div class="form-group">
<table class="table">
{{talk_form}}
</table>
<br />
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
<a href="{% url 'delete-talk' talk.id %}" class="btn btn-danger">Delete</a>
{% endblock %}
{% block javascript %}
<script type="text/javascript">
$(document).ready(function(){
$("#id_speaker").selectmenu()
$("#id_talk_type").selectmenu()
$("#id_category").selectmenu()
});
</script>
{% endblock %}

View file

@ -0,0 +1,64 @@
{% extends "get_together/base.html" %}
{% load static tz %}
{% block styles %}
<link href="{% static 'css/bootstrap-album.css' %}" rel="stylesheet"/>
{% endblock %}
{% block content %}
<div class="container">
{% if proposed_talks %}
<div class="row">
{% for presentation in proposed_talks %}
<div class="col-md-4">
<div class="card mb-4 box-shadow" style="width: 18rem;">
<div class="card-body">
<p class="card-title" style="height: 2rem;">
<strong><a href="{% url 'show-talk' presentation.talk.id %}">{{presentation.talk.title}}</a></strong>
{% if presentation.status == -1 %}
<span class="badge badge-danger" >Declined</span>
{% elif presentation.status == 1 %}
<span class="badge badge-success" >Accepted</span>
{% else %}
<span class="badge badge-info" >Submitted</span>
{% endif %}
</p>
<div class="card-text">
<small class="text-muted mb-1">{{ presentation.talk.speaker }}</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<hr/>
{% endif %}
<div class="row">
{% for talk in available_talks %}
<form action="{% url 'propose-event-talk' event.id %}" method="POST">
{% csrf_token %}
<div class="col-md-4">
<div class="card mb-4 box-shadow" style="width: 18rem;">
<div class="card-body">
<p class="card-title" style="height: 2rem;"><strong><a href="{% url 'show-talk' talk.id %}">{{talk.title}}</a></strong></p>
<div class="card-text">
<small class="text-muted mb-1">{{ talk.speaker }}</small>
<button class="btn btn-primary" type="submit" name="talk_id" value="{{talk.id}}">Propose</a></span>
</div>
</div>
</div>
</div>
</form>
{% endfor %}
</div>
<div class="row">
<div class="col">
<a href="{{event.get_absolute_url}}" class="btn btn-secondary">Cancel</a>
<a href="{% url 'add-user-talk' %}" class="btn btn-success">New Talk</a>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,57 @@
{% extends "get_together/base.html" %}
{% load static tz %}
{% block styles %}
<link href="{% static 'css/bootstrap-album.css' %}" rel="stylesheet"/>
{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
{% for speaker in speaker_bios %}
<div class="col-md-4">
<div class="card mb-4 box-shadow" style="width: 18rem;">
<div class="card-img-top mt-1" style="text-align: center"><img src="{{speaker.headshot.url}}"/></div>
<div class="card-body">
<p class="card-title" style="height: 2rem;">
<strong><a href="{% url 'edit-speaker' speaker.id %}">{{speaker.title}}</a></strong>
</p>
<div class="card-text">
<small class="text-muted mb-1">{{ speaker.bio }}</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="row">
<div class="col">
<a href="{% url 'add-speaker' %}" class="btn btn-success"><i class="fa fa-plus"></i> Speaker Bio</a>
</div>
</div>
<hr/>
<div class="row">
{% for talk in talks %}
<div class="col-md-4">
<div class="card mb-4 box-shadow" style="width: 18rem;">
<div class="card-body">
<p class="card-title" style="height: 2rem;"><strong><a href="{% url 'edit-talk' talk.id %}">{{talk.title}}</a></strong></p>
<div class="card-text">
<small class="text-muted mb-1">{{ talk.abstract }}</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="row">
<div class="col">
<a href="{% url 'add-talk' %}" class="btn btn-success"><i class="fa fa-plus"></i> Talk</a>
</div>
</div>
</div>
{% endblock %}

View file

@ -1,4 +1,10 @@
{% extends "get_together/base.html" %}
{% load static %}
{% block styles %}
<link href="{% static 'css/bootstrap-album.css' %}" rel="stylesheet"/>
{% endblock %}
{% block content %}
@ -6,11 +12,19 @@
<div class="container">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-6">
<div class="col-md-7">
<div class="h2">
<img class="align-bottom" border="1" src="{{user.avatar_url}}" height="128px"/> {{user.user}}
{% if user.user.id == request.user.id %}
<a href="{% url 'edit-profile' %}" class="btn btn-secondary btn-sm">Edit Profile</a>
<div class="btn-group dropdown">
<button class="btn btn-sm btn-secondary dropdown-toggle" type="button" id="editMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Edit
</button>
<div class="dropdown-menu" aria-labelledby="editMenuButton">
<a href="{% url 'edit-profile' %}" class="dropdown-item">Profile</a>
<a href="{% url 'user-talks' %}" class="dropdown-item">Talks</a>
</div>
</div>
<a href="{% url 'user-event-ical' request.user.profile.secret_key %}" class="btn btn-success btn-sm">iCal</a>
{% endif %}
@ -21,6 +35,25 @@
{% if user.weburl %}
<p>Homepage: {{user.weburl}}</p>
{% endif %}
{% if user.talks %}
<h3>Talks</h3>
<div class="container">
<div class="row">
{% for talk in user.talks %}
<div class="mr-3 mb-3 col-md-5">
<div class="card box-shadow" >
<div class="card-body">
<p class="card-title"><strong><a href="{% url 'show-talk' talk.id %}">{{talk.title}}</a></strong></p>
<div class="card-text">
<small class="text-muted mb-1">{{ talk.speaker }}</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
<div class="col-md-3">
{% if teams %}

View file

@ -49,6 +49,16 @@ urlpatterns = [
path('profile/<int:user_id>/', views.show_profile, name='show-profile'),
path('profile/<str:account_secret>.ics', feeds.UserEventsCalendar(), name='user-event-ical'),
path('profile/+add-speaker', views.add_speaker, name='add-speaker'),
path('speaker/<int:speaker_id>/+edit', views.edit_speaker, name='edit-speaker'),
path('speaker/<int:speaker_id>/+delete', views.delete_speaker, name='delete-speaker'),
path('profile/+talks', views.list_user_talks, name='user-talks'),
path('profile/+add-talk', views.add_talk, name='add-talk'),
path('talk/<int:talk_id>/', views.show_talk, name='show-talk'),
path('talk/<int:talk_id>/+edit', views.edit_talk, name='edit-talk'),
path('talk/<int:talk_id>/+delete', views.delete_talk, name='delete-talk'),
path('events/', views.events_list, name='events'),
path('events/all/', views.events_list_all, name='all-events'),
path('teams/', views.teams_list, name='teams'),
@ -70,7 +80,10 @@ urlpatterns = [
path('events/<int:event_id>/+add_place/', views.add_place_to_event, name='add-place'),
path('events/<int:event_id>/+comment/', event_views.comment_event, name='comment-event'),
path('events/<int:event_id>/+photo/', views.add_event_photo, name='add-event-photo'),
path('events/<int:event_id>/+propose-talk/', views.propose_event_talk, name='propose-event-talk'),
path('events/<int:event_id>/+schedule-talks/', views.schedule_event_talks, name='schedule-event-talks'),
path('events/<int:event_id>/<str:event_slug>/', views.show_event, name='show-event'),
path('series/<int:series_id>/+edit/', views.edit_series, name='edit-series'),
path('series/<int:series_id>/+delete/', views.delete_series, name='delete-series'),
path('series/<int:series_id>/+add_place/', views.add_place_to_series, name='add-place-to-series'),

View file

@ -27,6 +27,7 @@ from .places import *
from .user import *
from .new_user import *
from .new_team import *
from .speakers import *
from .utils import *
KM_PER_DEGREE_LAT = 110.574

View file

@ -65,7 +65,7 @@ def show_event(request, event_id, event_slug):
'comment_form': comment_form,
'is_attending': request.user.profile in event.attendees.all(),
'attendee_list': Attendee.objects.filter(event=event),
'presentation_list': event.presentations.all().order_by('start_time'),
'presentation_list': event.presentations.filter(status=Presentation.ACCEPTED).order_by('start_time'),
'can_edit_event': request.user.profile.can_edit_event(event),
}
return render(request, 'get_together/events/show_event.html', context)

View file

@ -0,0 +1,200 @@
from django.utils.translation import ugettext_lazy as _
from django.contrib import messages
from django.contrib.auth import logout as logout_user
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, JsonResponse
from django.core.exceptions import ObjectDoesNotExist
from events.models.profiles import UserProfile, Speaker, Talk
from events.forms import (
SpeakerBioForm,
UserTalkForm,
DeleteTalkForm,
SchedulePresentationForm,
)
from events.models.events import Event, Presentation
import datetime
import simplejson
from .teams import *
from .events import *
@login_required
def list_user_talks(request):
profile = request.user.profile
speaker_bios = Speaker.objects.filter(user=profile)
talks = list(Talk.objects.filter(speaker__user=profile))
context = {
'speaker_bios': speaker_bios,
'talks': talks,
}
return render(request, 'get_together/speakers/list_user_talks.html', context)
def add_speaker(request):
new_speaker = Speaker(user=request.user.profile)
if request.method == 'GET':
speaker_form = SpeakerBioForm(instance=new_speaker)
context = {
'speaker': new_speaker,
'speaker_form': speaker_form,
}
return render(request, 'get_together/speakers/create_speaker.html', context)
elif request.method == 'POST':
speaker_form = SpeakerBioForm(request.POST, request.FILES, instance=new_speaker)
if speaker_form.is_valid():
new_speaker = speaker_form.save()
return redirect('show-talks')
else:
context = {
'speaker': new_speaker,
'speaker_form': speaker_form,
}
return render(request, 'get_together/speakers/create_speaker.html', context)
return redirect('home')
def edit_speaker(request, speaker_id):
speaker = get_object_or_404(Speaker, id=speaker_id)
if request.method == 'GET':
speaker_form = SpeakerBioForm(instance=speaker)
context = {
'speaker': speaker,
'speaker_form': speaker_form,
}
return render(request, 'get_together/speakers/edit_speaker.html', context)
elif request.method == 'POST':
speaker_form = SpeakerBioForm(request.POST, request.FILES, instance=speaker)
if speaker_form.is_valid():
speaker = speaker_form.save()
return redirect('user-talks')
else:
context = {
'speaker': speaker,
'speaker_form': speaker_form,
}
return render(request, 'get_together/speakers/edit_speaker.html', context)
return redirect('home')
def delete_speaker(request, speaker_id):
pass
def show_talk(request, talk_id):
pass
def add_talk(request):
new_talk = Talk()
if request.method == 'GET':
talk_form = UserTalkForm(instance=new_talk)
talk_form.fields['speaker'].queryset = request.user.profile.speaker_set
context = {
'talk': new_talk,
'talk_form': talk_form,
}
return render(request, 'get_together/speakers/create_talk.html', context)
elif request.method == 'POST':
talk_form = UserTalkForm(request.POST, instance=new_talk)
talk_form.fields['speaker'].queryset = request.user.profile.speaker_set
if talk_form.is_valid():
new_talk = talk_form.save()
return redirect('user-talks')
else:
context = {
'talk': new_talk,
'talk_form': talk_form,
}
return render(request, 'get_together/speakers/create_talk.html', context)
return redirect('home')
def edit_talk(request, talk_id):
talk = get_object_or_404(Talk, id=talk_id)
if not talk.speaker.user == request.user.profile:
messages.add_message(request, messages.WARNING, message=_('You can not make changes to this talk.'))
return redirect('show-talk', talk_id)
if request.method == 'GET':
talk_form = UserTalkForm(instance=talk)
talk_form.fields['speaker'].queryset = request.user.profile.speaker_set
context = {
'talk': talk,
'talk_form': talk_form,
}
return render(request, 'get_together/speakers/edit_talk.html', context)
elif request.method == 'POST':
talk_form = UserTalkForm(request.POST, instance=talk)
talk_form.fields['speaker'].queryset = request.user.profile.speaker_set
if talk_form.is_valid():
talk = talk_form.save()
return redirect('user-talks')
else:
context = {
'talk': talk,
'talk_form': talk_form,
}
return render(request, 'get_together/speakers/edit_talk.html', context)
return redirect('home')
def delete_talk(request, talk_id):
talk = get_object_or_404(Talk, id=talk_id)
if not talk.speaker.user == request.user.profile:
messages.add_message(request, messages.WARNING, message=_('You can not make changes to this talk.'))
return redirect('show-talk', talk_id)
if request.method == 'GET':
form = DeleteTalkForm()
context = {
'talk': talk,
'delete_form': form,
}
return render(request, 'get_together/speakers/delete_talk.html', context)
elif request.method == 'POST':
form = DeleteTalkForm(request.POST)
if form.is_valid() and form.cleaned_data['confirm']:
talk.delete()
return redirect('user-talks')
else:
context = {
'talk': talk,
'delete_form': form,
}
return render(request, 'get_together/speakers/delete_talk.html', context)
else:
return redirect('home')
@login_required
def propose_event_talk(request, event_id):
event = get_object_or_404(Event, id=event_id)
if request.method == 'GET':
profile = request.user.profile
talks = list(Talk.objects.filter(speaker__user=profile))
presentations = event.presentations.all().order_by('-status')
for presentation in presentations:
if presentation.talk in talks:
talks.remove(presentation.talk)
context = {
'event': event,
'available_talks': talks,
'proposed_talks': presentations,
}
return render(request, 'get_together/speakers/list_user_presentations.html', context)
elif request.method == 'POST':
talk = get_object_or_404(Talk, id=request.POST.get('talk_id'))
new_proposal = Presentation.objects.create(
event=event,
talk=talk,
status=Presentation.PROPOSED,
start_time=event.local_start_time,
created_by=request.user.profile,
)
messages.add_message(request, messages.SUCCESS, message=_('Your talk has been submitted to the event organizer.'))
return redirect(event.get_absolute_url())
else:
redirect('home')
def schedule_event_talks(request, event_id):
pass