Creating device objects

This commit is contained in:
Raphael Michel
2018-09-17 18:27:29 +02:00
parent f08e4b41c4
commit ddb645aeea
7 changed files with 252 additions and 5 deletions

View File

@@ -6,7 +6,7 @@ from django.utils.translation import ugettext_lazy as _
from i18nfield.forms import I18nFormField, I18nTextarea
from pretix.base.forms import I18nModelForm, SettingsForm
from pretix.base.models import Organizer, Team
from pretix.base.models import Device, Organizer, Team
from pretix.control.forms import ExtFileField, MultipleLanguagesWidget
from pretix.multidomain.models import KnownDomain
from pretix.presale.style import get_fonts
@@ -107,7 +107,7 @@ class TeamForm(forms.ModelForm):
data = super().clean()
if self.instance.pk and not data['can_change_teams']:
if not self.instance.organizer.teams.exclude(pk=self.instance.pk).filter(
can_change_teams=True, members__isnull=False
can_change_teams=True, members__isnull=False
).exists():
raise ValidationError(_('The changes could not be saved because there would be no remaining team with '
'the permission to change teams and permissions.'))
@@ -115,6 +115,23 @@ class TeamForm(forms.ModelForm):
return data
class DeviceForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
organizer = kwargs.pop('organizer')
super().__init__(*args, **kwargs)
self.fields['limit_events'].queryset = organizer.events.all()
class Meta:
model = Device
fields = ['name', 'all_events', 'limit_events']
widgets = {
'limit_events': forms.CheckboxSelectMultiple(attrs={
'data-inverse-dependency': '#id_all_events'
}),
}
class OrganizerSettingsForm(SettingsForm):
organizer_info_text = I18nFormField(

View File

@@ -33,6 +33,13 @@
</a>
</li>
{% endif %}
{% if 'can_change_organizer_settings' in request.orgapermset %}
<li {% if "organizer.device" in url_name %}class="active"{% endif %}>
<a href="{% url "control:organizer.devices" organizer=organizer.slug %}">
{% trans "Devices" %}
</a>
</li>
{% endif %}
{% for nav in nav_organizer %}
<li {% if nav.active %}class="active"{% endif %}>
<a href="{{ nav.url }}">

View File

@@ -0,0 +1,7 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block inner %}
<legend>{% trans "Connect to device:" %} {{ device.name }}</legend>
{% endblock %}

View File

@@ -0,0 +1,23 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block inner %}
{% if device %}
<legend>{% trans "Device:" %} {{ device.name }}</legend>
{% else %}
<legend>{% trans "Connect a new device" %}</legend>
{% endif %}
<form class="form-horizontal" action="" method="post">
{% csrf_token %}
{% bootstrap_form_errors form %}
{% bootstrap_field form.name layout="control" %}
{% bootstrap_field form.all_events layout="control" %}
{% bootstrap_field form.limit_events layout="control" %}
<div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,90 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block inner %}
<legend>
{% trans "Connected devices" %}
</legend>
{% if devices|length == 0 %}
<div class="empty-collection">
<p>
{% blocktrans trimmed %}
You haven't connected any hardware devices yet.
{% endblocktrans %}
</p>
<a href="{% url "control:organizer.device.add" organizer=request.organizer.slug %}"
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Connect a device" %}</a>
</div>
{% else %}
<p>
<a href="{% url "control:organizer.device.add" organizer=request.organizer.slug %}"
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Connect a device" %}</a>
</p>
<div class="table-responsive">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>{% trans "Device ID" %}</th>
<th>{% trans "Name" %}</th>
<th>{% trans "Hardware model" %}</th>
<th>{% trans "Software" %}</th>
<th>{% trans "Setup date" %}</th>
<th>{% trans "Events" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for d in devices %}
<tr>
<td>
{{ d.device_id }}
</td>
<td>
{{ d.name }}
</td>
<td>
{{ d.hardware_brand|default_if_none:"" }} {{ d.hardware_model|default_if_none:"" }}
</td>
<td>
{{ d.software_brand|default_if_none:"" }} {{ d.software_version|default_if_none:"" }}
</td>
<td>
{% if d.initialized %}
{{ d.initialized|date:"SHORT_DATETIME_FORMAT" }}
{% else %}
<em>{% trans "Not yet initialized" %}</em>
{% endif %}
</td>
<td>
{% if d.all_events %}
{% trans "All" %}
{% else %}
<ul>
{% for e in d.limit_events.all %}
<li>
<a href="{% url "control:event.index" organizer=request.organizer.slug event=e.slug %}">
{{ e }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
</td>
<td class="text-right">
{% if not d.initialized %}
<a href="{% url "control:organizer.device.connect" organizer=request.organizer.slug device=d.id %}"
class="btn btn-primary btn-sm"><i class="fa fa-link"></i>
{% trans "Connect" %}</a>
{% endif %}
<a href="{% url "control:organizer.device.edit" organizer=request.organizer.slug device=d.id %}"
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% include "pretixcontrol/pagination.html" %}
{% endif %}
{% endblock %}

View File

@@ -68,6 +68,13 @@ urlpatterns = [
url(r'^organizer/(?P<organizer>[^/]+)/edit$', organizer.OrganizerUpdate.as_view(), name='organizer.edit'),
url(r'^organizer/(?P<organizer>[^/]+)/settings/display$', organizer.OrganizerDisplaySettings.as_view(),
name='organizer.display'),
url(r'^organizer/(?P<organizer>[^/]+)/devices$', organizer.DeviceListView.as_view(), name='organizer.devices'),
url(r'^organizer/(?P<organizer>[^/]+)/device/add$', organizer.DeviceCreateView.as_view(),
name='organizer.device.add'),
url(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/edit', organizer.DeviceUpdateView.as_view(),
name='organizer.device.edit'),
url(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/connect', organizer.DeviceConnectView.as_view(),
name='organizer.device.connect'),
url(r'^organizer/(?P<organizer>[^/]+)/teams$', organizer.TeamListView.as_view(), name='organizer.teams'),
url(r'^organizer/(?P<organizer>[^/]+)/team/add$', organizer.TeamCreateView.as_view(), name='organizer.team.add'),
url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/$', organizer.TeamMemberView.as_view(),

View File

@@ -13,14 +13,14 @@ from django.views.generic import (
CreateView, DeleteView, DetailView, FormView, ListView, UpdateView,
)
from pretix.base.models import Organizer, Team, TeamInvite, User
from pretix.base.models import Device, Organizer, Team, TeamInvite, User
from pretix.base.models.event import EventMetaProperty
from pretix.base.models.organizer import TeamAPIToken
from pretix.base.services.mail import SendMailException, mail
from pretix.control.forms.filter import OrganizerFilterForm
from pretix.control.forms.organizer import (
EventMetaPropertyForm, OrganizerDisplaySettingsForm, OrganizerForm,
OrganizerSettingsForm, OrganizerUpdateForm, TeamForm,
DeviceForm, EventMetaPropertyForm, OrganizerDisplaySettingsForm,
OrganizerForm, OrganizerSettingsForm, OrganizerUpdateForm, TeamForm,
)
from pretix.control.permissions import OrganizerPermissionRequiredMixin
from pretix.control.signals import nav_organizer
@@ -576,3 +576,99 @@ class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
'organizer': self.request.organizer.slug,
'team': self.object.pk
})
class DeviceListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
model = Device
template_name = 'pretixcontrol/organizers/devices.html'
permission = 'can_change_organizer_settings'
context_object_name = 'devices'
def get_queryset(self):
return self.request.organizer.devices.prefetch_related('limit_events')
class DeviceCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView):
model = Device
template_name = 'pretixcontrol/organizers/device_edit.html'
permission = 'can_change_organizer_settings'
form_class = DeviceForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['organizer'] = self.request.organizer
return kwargs
def get_success_url(self):
return reverse('control:organizer.device.connect', kwargs={
'organizer': self.request.organizer.slug,
'device': self.object.pk
})
def form_valid(self, form):
form.instance.organizer = self.request.organizer
ret = super().form_valid(form)
form.instance.members.add(self.request.user)
form.instance.log_action('pretix.device.created', user=self.request.user, data={
k: getattr(self.object, k) if k != 'limit_events' else [e.id for e in getattr(self.object, k).all()]
for k in form.changed_data
})
return ret
def form_invalid(self, form):
messages.error(self.request, _('Your changes could not be saved.'))
return super().form_invalid(form)
class DeviceUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView):
model = Device
template_name = 'pretixcontrol/organizers/device_edit.html'
permission = 'can_change_organizer_settings'
context_object_name = 'device'
form_class = DeviceForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['organizer'] = self.request.organizer
return kwargs
def get_object(self, queryset=None):
return get_object_or_404(Device, organizer=self.request.organizer, pk=self.kwargs.get('device'))
def get_success_url(self):
return reverse('control:organizer.devices', kwargs={
'organizer': self.request.organizer.slug,
})
def form_valid(self, form):
if form.has_changed():
self.object.log_action('pretix.device.changed', user=self.request.user, data={
k: getattr(self.object, k) if k != 'limit_events' else [e.id for e in getattr(self.object, k).all()]
for k in form.changed_data
})
messages.success(self.request, _('Your changes have been saved.'))
return super().form_valid(form)
def form_invalid(self, form):
messages.error(self.request, _('Your changes could not be saved.'))
return super().form_invalid(form)
class DeviceConnectView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView):
model = Device
template_name = 'pretixcontrol/organizers/device_connect.html'
permission = 'can_change_organizer_settings'
context_object_name = 'device'
form_class = DeviceForm
def get_object(self, queryset=None):
return get_object_or_404(Device, organizer=self.request.organizer, pk=self.kwargs.get('device'))
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if self.object.initialized:
messages.error(request, _('This device already has been connected.'))
return redirect(reverse('control:organizer.devices', kwargs={
'organizer': self.request.organizer.slug,
}))
return super().get(request, *args, **kwargs)