mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-30 03:42:15 +00:00
Add ability to edit checkins, more validation
This commit is contained in:
@@ -232,3 +232,10 @@ class EventCheckInForm(forms.ModelForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = models.EventCheckIn
|
model = models.EventCheckIn
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
exclude = ['end_time']
|
||||||
|
|
||||||
|
|
||||||
|
class EditCheckInForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = models.EventCheckIn
|
||||||
|
fields = '__all__'
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ class Profile(AbstractUser):
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def current_event(self):
|
def current_event(self):
|
||||||
return EventCheckIn.objects.filter(person=self).latest('time') or None
|
q = EventCheckIn.objects.filter(person=self, end_time=None)
|
||||||
|
return q.latest('time') if q.exists() else None
|
||||||
|
|
||||||
|
|
||||||
class ContactableManager(models.Manager):
|
class ContactableManager(models.Manager):
|
||||||
@@ -919,6 +920,10 @@ class EventCheckIn(models.Model):
|
|||||||
vehicle = models.CharField(max_length=100, blank=True)
|
vehicle = models.CharField(max_length=100, blank=True)
|
||||||
end_time = models.DateTimeField(null=True)
|
end_time = models.DateTimeField(null=True)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
if self.end_time < self.time:
|
||||||
|
raise ValidationError("May not check out before you've checked in. Please invent time travel and retry.")
|
||||||
|
|
||||||
def active(self):
|
def active(self):
|
||||||
return end_time is not None
|
return end_time is not None
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
|
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
|
||||||
|
|
||||||
{% load markdown_tags %}
|
{% load markdown_tags %}
|
||||||
|
{% load button from filters %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row my-3 py-3">
|
<div class="row my-3 py-3">
|
||||||
@@ -52,6 +53,43 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if not event.dry_hire %}
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="card mt-3">
|
||||||
|
<div class="card-header">Crew Record</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Crewmember</th>
|
||||||
|
<th scope="col">Vehicle</th>
|
||||||
|
<th scope="col">Start Time</th>
|
||||||
|
<th scope="col">Role</th>
|
||||||
|
<th scope="col">End Time</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="crewmemberst">
|
||||||
|
{% for crew in object.crew.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{crew.person}}</td>
|
||||||
|
<td>{{crew.vehicle|default:"None"}}</td>
|
||||||
|
<td>{{crew.time}}</td>
|
||||||
|
<td>{{crew.role}}</td>
|
||||||
|
<td>{% if crew.end_time %}{{crew.end_time}}{% else %}<span class="text-success fas fa-clock" data-toggle="tooltip" title="This person is currently checked into this event"></span>{% endif %}</td>
|
||||||
|
<td>{% if crew.end_time %}{% if crew.person.pk == request.user.pk or crew.event.mic.pk == request.user.pk %}{% button 'edit' 'edit_checkin' crew.pk clazz='btn-sm modal-href' %}{% endif %}{%endif%}</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="text-center bg-warning">Apparently this event happened by magic...</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
{% if not request.is_ajax and perms.RIGS.view_event %}
|
{% if not request.is_ajax and perms.RIGS.view_event %}
|
||||||
<div class="col-sm-12 text-right">
|
<div class="col-sm-12 text-right">
|
||||||
{% include 'partials/event_detail_buttons.html' %}
|
{% include 'partials/event_detail_buttons.html' %}
|
||||||
|
|||||||
@@ -68,37 +68,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
|
||||||
<div class="card-header">Crew Record</div>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-sm">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Crewmember</th>
|
|
||||||
<th scope="col">Vehicle</th>
|
|
||||||
<th scope="col">Start Time</th>
|
|
||||||
<th scope="col">Role</th>
|
|
||||||
<th scope="col">End Time</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody id="crewmemberst">
|
|
||||||
{% for crew in object.event.crew.all %}
|
|
||||||
<tr>
|
|
||||||
<td>{{crew.person}}</td>
|
|
||||||
<td>{{crew.vehicle|default:"None"}}</td>
|
|
||||||
<td>{{crew.time}}</td>
|
|
||||||
<td>{{crew.role}}</td>
|
|
||||||
<td>{{crew.end_time}}</td>
|
|
||||||
</tr>
|
|
||||||
{% empty %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="5" class="text-center bg-warning">Apparently this event happened by magic...</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 text-right">
|
<div class="col-12 text-right">
|
||||||
{% button 'edit' url='ec_edit' pk=object.pk %}
|
{% button 'edit' url='ec_edit' pk=object.pk %}
|
||||||
{% button 'view' url='event_detail' pk=object.pk text="Event" %}
|
{% button 'view' url='event_detail' pk=object.pk text="Event" %}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
{% include 'form_errors.html' %}
|
{% include 'form_errors.html' %}
|
||||||
<form id="checkin" role="form" method="POST" action="{% url 'event_checkin' pk=event.pk %}">
|
<form id="checkin" role="form" method="POST" action="{{ form.action|default:request.path }}">
|
||||||
<input type="hidden" name="{{ form.event.name }}" id="{{ form.event.id_for_label }}"
|
<input type="hidden" name="{{ form.event.name }}" id="{{ form.event.id_for_label }}"
|
||||||
value="{{event.pk}}"/>
|
value="{{event.pk}}"/>
|
||||||
<input type="hidden" name="{{ form.person.name }}" id="{{ form.person.id_for_label }}"
|
<input type="hidden" name="{{ form.person.name }}" id="{{ form.person.id_for_label }}"
|
||||||
@@ -20,30 +20,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="{{ form.vehicle.id_for_label }}" class="col col-form-label">What is your role?</label>
|
<label for="{{ form.role.id_for_label }}" class="col col-form-label">Role</label>
|
||||||
<div class="col-12">
|
<div class="row pl-3">
|
||||||
<button type="button" class="btn btn-primary" onclick="document.getElementById('id_role').value='MIC'">MIC</button>
|
<div class="col">
|
||||||
<button type="button" class="btn btn-danger" onclick="document.getElementById('id_role').value='Power MIC'">Power MIC</button>
|
<button type="button" class="btn btn-primary" onclick="document.getElementById('id_role').value='MIC'">MIC</button>
|
||||||
<button type="button" class="btn btn-info" onclick="document.getElementById('id_role').value='Crew'">Crew</button>
|
<button type="button" class="btn btn-danger" onclick="document.getElementById('id_role').value='Power MIC'">Power MIC</button>
|
||||||
<br/>
|
<button type="button" class="btn btn-info" onclick="document.getElementById('id_role').value='Crew'">Crew</button>
|
||||||
<p class="mt-2">Other (enter text)</p>
|
</div>
|
||||||
</div>
|
<div class="col">
|
||||||
<div class="col-sm-8">
|
{% render_field form.role class+="form-control" placeholder="Other (enter text)" %}
|
||||||
{% render_field form.role class+="form-control" %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="{{ form.vehicle.id_for_label }}" class="col col-form-label">Did you drive? If so, what did you drive?</label>
|
<label for="{{ form.vehicle.id_for_label }}" class="col col-form-label">Vehicle (if applicable)</label>
|
||||||
<div class="col-12">
|
<div class="row pl-3">
|
||||||
<button type="button" class="btn btn-primary" onclick="document.getElementById('id_vehicle').value='Virgil'"><span class="fas fa-truck-moving"></span> Virgil</button>
|
<div class="col">
|
||||||
<button type="button" class="btn btn-secondary" onclick="document.getElementById('id_vehicle').value='Virgil + Erms'"><span class="fas fa-trailer"></span><span class="fas fa-truck-moving"></span> Virgil + Erms</button>
|
<button type="button" class="btn btn-primary" onclick="document.getElementById('id_vehicle').value='Virgil'"><span class="fas fa-truck-moving"></span> Virgil</button>
|
||||||
<br/>
|
<button type="button" class="btn btn-secondary" onclick="document.getElementById('id_vehicle').value='Virgil + Erms'"><span class="fas fa-trailer"></span><span class="fas fa-truck-moving"></span> Virgil + Erms</button>
|
||||||
<p class="mt-2">Other (enter text)</p>
|
</div>
|
||||||
</div>
|
<div class="col">
|
||||||
<div class="col-sm-8">
|
{% render_field form.vehicle class+="form-control" placeholder="Other (enter text)" %}
|
||||||
{% render_field form.vehicle class+="form-control" %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if edit %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="{{ form.end_time.id_for_label }}"
|
||||||
|
class="col-sm-4 col-form-label">End Time</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
{% render_field form.end_time class+="form-control" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% if not request.is_ajax %}
|
{% if not request.is_ajax %}
|
||||||
<div class="row mt-3">
|
<div class="row mt-3">
|
||||||
<div class="col-sm-12 text-right">
|
<div class="col-sm-12 text-right">
|
||||||
@@ -57,6 +66,7 @@
|
|||||||
|
|
||||||
{% block footer %}
|
{% block footer %}
|
||||||
<div class="col-sm-12 text-right pr-0">
|
<div class="col-sm-12 text-right pr-0">
|
||||||
<button type="submit" class="btn btn-primary" title="Save" form="checkin"><span class="fas fa-save align-middle"></span> <span class="d-none d-sm-inline align-middle">Save</span></button>
|
<button type="submit" class="btn btn-primary" title="Save" form="checkin"
|
||||||
|
><span class="fas fa-save align-middle"></span> <span class="d-none d-sm-inline align-middle">Save</span></button>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -49,6 +49,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<a href="https://docs.google.com/forms/d/e/1FAIpQLSf-TBOuJZCTYc2L8DWdAaC3_Werq0ulsUs8-6G85I6pA9WVsg/viewform" class="btn btn-danger"><span class="fas fa-file-invoice-dollar"></span> <span class="d-none d-sm-inline">Subhire Insurance Form</span></a>
|
<a href="https://docs.google.com/forms/d/e/1FAIpQLSf-TBOuJZCTYc2L8DWdAaC3_Werq0ulsUs8-6G85I6pA9WVsg/viewform" class="btn btn-danger"><span class="fas fa-file-invoice-dollar"></span> <span class="d-none d-sm-inline">Subhire Insurance Form</span></a>
|
||||||
<a href="{% url 'event_checkin' event.pk %}" class="btn btn-success modal-href"><span class="fas fa-user-clock"></span> <span class="d-none d-sm-inline">Check In</span></a>
|
|
||||||
|
{% if not event.dry_hire %}
|
||||||
|
<a href="{% url 'event_checkin' event.pk %}" class="btn btn-success modal-href {% if request.user.current_event %}disabled{%endif%}"><span class="fas fa-user-clock"></span> <span class="d-none d-sm-inline">Check In</span></a>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -103,6 +103,10 @@ urlpatterns = [
|
|||||||
|
|
||||||
path('event/<int:pk>/checkin/', permission_required_with_403('RIGS.add_eventcheckin')(views.EventCheckIn.as_view()),
|
path('event/<int:pk>/checkin/', permission_required_with_403('RIGS.add_eventcheckin')(views.EventCheckIn.as_view()),
|
||||||
name='event_checkin'),
|
name='event_checkin'),
|
||||||
|
path('event/checkout/', permission_required_with_403('RIGS.change_eventcheckin')(views.EventCheckOut.as_view()),
|
||||||
|
name='event_checkout'),
|
||||||
|
path('event/<int:pk>/checkin/edit/', permission_required_with_403('RIGS.change_eventcheckin')(views.EventCheckInEdit.as_view()),
|
||||||
|
name='edit_checkin'),
|
||||||
|
|
||||||
# Finance
|
# Finance
|
||||||
path('invoice/', permission_required_with_403('RIGS.view_invoice')(views.InvoiceIndex.as_view()),
|
path('invoice/', permission_required_with_403('RIGS.view_invoice')(views.InvoiceIndex.as_view()),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from reversion import revisions as reversion
|
|||||||
|
|
||||||
from RIGS import models, forms
|
from RIGS import models, forms
|
||||||
from RIGS.views.rigboard import get_related
|
from RIGS.views.rigboard import get_related
|
||||||
from PyRIGS.views import PrintView
|
from PyRIGS.views import PrintView, ModalURLMixin
|
||||||
|
|
||||||
|
|
||||||
class HSCreateView(generic.CreateView):
|
class HSCreateView(generic.CreateView):
|
||||||
@@ -228,14 +228,43 @@ class RAPrint(PrintView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class EventCheckIn(generic.CreateView):
|
class EventCheckIn(generic.CreateView, ModalURLMixin):
|
||||||
model = models.EventCheckIn
|
model = models.EventCheckIn
|
||||||
template_name = 'hs/eventcheckin_form.html'
|
template_name = 'hs/eventcheckin_form.html'
|
||||||
form_class = forms.EventCheckInForm
|
form_class = forms.EventCheckInForm
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return self.get_close_url('event_detail', 'event_detail') # Well, that's one way of doing that...!
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['event'] = models.Event.objects.get(pk=self.kwargs.get('pk'))
|
context['event'] = models.Event.objects.get(pk=self.kwargs.get('pk'))
|
||||||
context['page_title'] = f'Check In to Event {context["event"].display_id}'
|
context['page_title'] = f'Check In to Event {context["event"].display_id}'
|
||||||
# get_related(context['form'], context)
|
# get_related(context['form'], context)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class EventCheckInEdit(generic.UpdateView, ModalURLMixin):
|
||||||
|
model = models.EventCheckIn
|
||||||
|
template_name = 'hs/eventcheckin_form.html'
|
||||||
|
form_class = forms.EditCheckInForm
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return self.get_close_url('event_detail', 'event_detail') # Well, that's one way of doing that...!
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context['event'] = self.object.event
|
||||||
|
context['page_title'] = f'Edit Check In for Event {context["event"].display_id}'
|
||||||
|
context['edit'] = True
|
||||||
|
# get_related(context['form'], context)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class EventCheckOut(generic.RedirectView):
|
||||||
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
|
checkin = self.request.user.current_event()
|
||||||
|
if checkin:
|
||||||
|
checkin.end_time = timezone.now()
|
||||||
|
checkin.save()
|
||||||
|
return reverse_lazy('event_detail', kwargs={'pk': checkin.event.pk})
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<a class="skip-link" href='#main'>Skip to content</a>
|
<a class="skip-link" href='#main'>Skip to content</a>
|
||||||
{% block navbar %}
|
{% block navbar %}
|
||||||
{% if request.user.current_event %}
|
{% if request.user.current_event %}
|
||||||
<div class="bg-primary d-flex justify-content-between align-items-center"><span class="ml-2">You are currently checked in to <a href="{{request.user.current_event.event.get_absolute_url}}" class="text-white">{{request.user.current_event.event}}</a></span><a href="#" class="btn btn-warning">Check Out</a></div>
|
<div class="bg-primary d-flex justify-content-between align-items-center"><span class="ml-2">You are currently checked in to <a href="{{request.user.current_event.event.get_absolute_url}}" class="text-white">{{request.user.current_event.event}}</a></span><a href="{% url 'event_checkout'%}" class="btn btn-warning">Check Out</a></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark" role="navigation">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark" role="navigation">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
Reference in New Issue
Block a user