add backoffice tool to add recording URLs (#683)
This commit is contained in:
parent
fbda2b4b53
commit
4d32a9deb9
|
@ -2,6 +2,16 @@ from django import forms
|
||||||
from program.models import Event, Speaker
|
from program.models import Event, Speaker
|
||||||
|
|
||||||
|
|
||||||
|
class AddRecordingForm(forms.ModelForm):
|
||||||
|
recording_url = forms.URLField(
|
||||||
|
label="Recording URL", help_text="Add a URL to the recording.", required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Event
|
||||||
|
fields = ["video_recording", "recording_url"]
|
||||||
|
|
||||||
|
|
||||||
class AutoScheduleValidateForm(forms.Form):
|
class AutoScheduleValidateForm(forms.Form):
|
||||||
schedule = forms.ChoiceField(
|
schedule = forms.ChoiceField(
|
||||||
choices=(
|
choices=(
|
||||||
|
|
32
src/backoffice/templates/add_recording.html
Normal file
32
src/backoffice/templates/add_recording.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load bornhack %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="h2">BackOffice - Add Event recordings</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="lead">
|
||||||
|
The Content team can add video links to all events that are configured to be recorded
|
||||||
|
</div>
|
||||||
|
{% if event_list %}
|
||||||
|
<form method="post">
|
||||||
|
{{ formset.management_form }}
|
||||||
|
{% csrf_token %}
|
||||||
|
{% for form, event in formset|zip:event_list %}
|
||||||
|
{% include "includes/eventrecording_detail_panel.html" %}
|
||||||
|
{% endfor %}
|
||||||
|
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Submit</button>
|
||||||
|
<a href="{% url 'backoffice:index' camp_slug=camp.slug %}" class="btn btn-primary"><i class="fas fa-undo"></i> Cancel</a>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<div class="lead">There is no events missing links to recordings.</div>
|
||||||
|
<a href="{% url 'backoffice:index' camp_slug=camp.slug %}" class="btn btn-primary"><i class="fas fa-undo"></i> Cancel</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
|
|
|
@ -107,6 +107,10 @@
|
||||||
<h4 class="list-group-item-heading">SpeakerProposals</h4>
|
<h4 class="list-group-item-heading">SpeakerProposals</h4>
|
||||||
<p class="list-group-item-text">Use these views to see all SpeakerProposals</p>
|
<p class="list-group-item-text">Use these views to see all SpeakerProposals</p>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="{% url 'backoffice:add_eventrecording' camp_slug=camp.slug %}" class="list-group-item">
|
||||||
|
<h4 class="list-group-item-heading">Add Recordings</h4>
|
||||||
|
<p class="list-group-item-text">Use this view to add recordings to events</p>
|
||||||
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if perms.camps.orgateam_permission %}
|
{% if perms.camps.orgateam_permission %}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
|
|
||||||
from .views import (
|
from .views import (
|
||||||
|
AddRecordingView,
|
||||||
ApproveFeedbackView,
|
ApproveFeedbackView,
|
||||||
ApproveNamesView,
|
ApproveNamesView,
|
||||||
AutoScheduleApplyView,
|
AutoScheduleApplyView,
|
||||||
|
@ -537,6 +538,8 @@ urlpatterns = [
|
||||||
ApproveFeedbackView.as_view(),
|
ApproveFeedbackView.as_view(),
|
||||||
name="approve_event_feedback",
|
name="approve_event_feedback",
|
||||||
),
|
),
|
||||||
|
# add recording url objects
|
||||||
|
path("add_recording", AddRecordingView.as_view(), name="add_eventrecording",),
|
||||||
# economy
|
# economy
|
||||||
path(
|
path(
|
||||||
"economy/",
|
"economy/",
|
||||||
|
|
|
@ -49,6 +49,8 @@ from program.models import (
|
||||||
EventType,
|
EventType,
|
||||||
Speaker,
|
Speaker,
|
||||||
SpeakerProposal,
|
SpeakerProposal,
|
||||||
|
Url,
|
||||||
|
UrlType,
|
||||||
)
|
)
|
||||||
from program.utils import save_speaker_availability
|
from program.utils import save_speaker_availability
|
||||||
from shop.models import Order, OrderProductRelation
|
from shop.models import Order, OrderProductRelation
|
||||||
|
@ -62,6 +64,7 @@ from .forms import (
|
||||||
AutoScheduleValidateForm,
|
AutoScheduleValidateForm,
|
||||||
EventScheduleForm,
|
EventScheduleForm,
|
||||||
SpeakerForm,
|
SpeakerForm,
|
||||||
|
AddRecordingForm,
|
||||||
)
|
)
|
||||||
from .mixins import (
|
from .mixins import (
|
||||||
ContentTeamPermissionMixin,
|
ContentTeamPermissionMixin,
|
||||||
|
@ -191,6 +194,68 @@ class ApproveFeedbackView(CampViewMixin, ContentTeamPermissionMixin, FormView):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AddRecordingView(CampViewMixin, ContentTeamPermissionMixin, FormView):
|
||||||
|
"""
|
||||||
|
This view shows a list of events that is set to be recorded, but without a recording URL attached.
|
||||||
|
"""
|
||||||
|
|
||||||
|
model = Event
|
||||||
|
template_name = "add_recording.html"
|
||||||
|
|
||||||
|
def setup(self, *args, **kwargs):
|
||||||
|
super().setup(*args, **kwargs)
|
||||||
|
self.queryset = Event.objects.filter(
|
||||||
|
track__camp=self.camp, video_recording=True
|
||||||
|
).exclude(
|
||||||
|
urls__url_type__name="Recording"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.form_class = modelformset_factory(
|
||||||
|
Event,
|
||||||
|
form=AddRecordingForm,
|
||||||
|
min_num=self.queryset.count(),
|
||||||
|
validate_min=True,
|
||||||
|
max_num=self.queryset.count(),
|
||||||
|
validate_max=True,
|
||||||
|
extra=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Include the queryset used for the modelformset_factory so we have
|
||||||
|
some idea which object is which in the template
|
||||||
|
Why the hell do the forms in the formset not include the object?
|
||||||
|
"""
|
||||||
|
context = super().get_context_data(*args, **kwargs)
|
||||||
|
context["event_list"] = self.queryset
|
||||||
|
context["formset"] = self.form_class(queryset=self.queryset)
|
||||||
|
return context
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
form.save()
|
||||||
|
|
||||||
|
for event_data in form.cleaned_data:
|
||||||
|
if event_data['recording_url']:
|
||||||
|
url = event_data['recording_url']
|
||||||
|
if not event_data['id'].urls.filter(url=url).exists():
|
||||||
|
recording_url = Url()
|
||||||
|
recording_url.event = event_data['id']
|
||||||
|
recording_url.url = url
|
||||||
|
recording_url.url_type = UrlType.objects.get(name="Recording")
|
||||||
|
recording_url.save()
|
||||||
|
|
||||||
|
if form.changed_objects:
|
||||||
|
messages.success(
|
||||||
|
self.request, f"Updated {len(form.changed_objects)} Event"
|
||||||
|
)
|
||||||
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
|
def get_success_url(self, *args, **kwargs):
|
||||||
|
return reverse(
|
||||||
|
"backoffice:add_eventrecording", kwargs={"camp_slug": self.camp.slug}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
# MANAGE FACILITIES VIEWS
|
# MANAGE FACILITIES VIEWS
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load commonmark %}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<span class="h3">Recording for Event: {{ event.title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<tr>
|
||||||
|
<th>Camp</th>
|
||||||
|
<td>{{ event.track.camp.title }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Track</th>
|
||||||
|
<td>{{ event.track.name }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Type</th>
|
||||||
|
<td>{{ event.event_type.name }}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>URLs</th>
|
||||||
|
<td>
|
||||||
|
{% if event.urls.exists %}
|
||||||
|
{% for url in event.urls.all %}
|
||||||
|
<p><i class="{{ url.url_type.icon }}"></i> <b>{{ url.url_type }}</b>: <a href="{{ url.url }}" target="_blank" data-toggle="tooltip" title="{{ url.url_type }}">{{ url.url }}</a></p>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<p><i>No URLs found.</i></p>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Video URL (legacy)</th>
|
||||||
|
<td>{{ event.video_url }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% if form %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
{% elif buttoninclude %}
|
||||||
|
{% include buttoninclude %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -823,7 +823,7 @@ class Command(BaseCommand):
|
||||||
year = camp.camp.lower.year
|
year = camp.camp.lower.year
|
||||||
self.output("Creating event_tracks for {}...".format(year))
|
self.output("Creating event_tracks for {}...".format(year))
|
||||||
tracks[1] = EventTrack.objects.create(
|
tracks[1] = EventTrack.objects.create(
|
||||||
camp=camp, name="BornHack", slug=camp.slug
|
camp=camp, name="BornHack {}".format(year), slug=camp.slug
|
||||||
)
|
)
|
||||||
|
|
||||||
return tracks
|
return tracks
|
||||||
|
|
Loading…
Reference in a new issue