mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-17 05:22:16 +00:00
Event checklist crew works
Mostly - its not happy with timezones
This commit is contained in:
@@ -10,6 +10,7 @@ from django.contrib.auth.forms import AuthenticationForm
|
||||
from captcha.fields import ReCaptchaField
|
||||
from reversion import revisions as reversion
|
||||
import simplejson
|
||||
from datetime import datetime
|
||||
|
||||
from RIGS import models
|
||||
|
||||
@@ -172,17 +173,17 @@ class EventRiskAssessmentForm(forms.ModelForm):
|
||||
|
||||
|
||||
class EventChecklistForm(forms.ModelForm):
|
||||
# Parsed from incoming form data by clean, then saved into models when the form is saved
|
||||
items = {}
|
||||
|
||||
# There's probably a thousand better ways to do this, but this one is mine
|
||||
def clean(self):
|
||||
vehicles = {key: val for key, val in self.data.items()
|
||||
if key.startswith('vehicle')}
|
||||
drivers = {key: val for key, val in self.data.items()
|
||||
if key.startswith('driver')}
|
||||
for key in vehicles:
|
||||
pk = int(key.split('_')[1])
|
||||
driver_key = 'driver_' + str(pk)
|
||||
if(drivers[driver_key] == ''):
|
||||
if(self.data[driver_key] == ''):
|
||||
raise forms.ValidationError('Add a driver to vehicle ' + str(pk), code='vehicle_mismatch')
|
||||
else:
|
||||
try:
|
||||
@@ -191,10 +192,36 @@ class EventChecklistForm(forms.ModelForm):
|
||||
item = models.EventChecklistVehicle()
|
||||
|
||||
item.vehicle = vehicles['vehicle_' + str(pk)]
|
||||
item.driver = models.Profile.objects.get(pk=drivers['driver_' + str(pk)])
|
||||
item.driver = models.Profile.objects.get(pk=self.data[driver_key])
|
||||
item.full_clean('checklist')
|
||||
|
||||
# item does not have a database pk yet as it isn't saved
|
||||
self.items[pk] = item
|
||||
self.items['v' + str(pk)] = item
|
||||
|
||||
crewmembers = {key: val for key, val in self.data.items()
|
||||
if key.startswith('crewmember')}
|
||||
other_fields = ['start','role','end']
|
||||
for key in crewmembers:
|
||||
pk = int(key.split('_')[1])
|
||||
|
||||
for field in other_fields:
|
||||
value = self.data['{}_{}'.format(field,pk)]
|
||||
if value == '':
|
||||
raise forms.ValidationError('Add a {} to crewmember {}'.format(field, pk), code='{}_mismatch'.format(field))
|
||||
|
||||
try:
|
||||
item = models.EventChecklistCrew.objects.get(pk=pk)
|
||||
except models.EventChecklistCrew.DoesNotExist:
|
||||
item = models.EventChecklistCrew()
|
||||
|
||||
item.crewmember = models.Profile.objects.get(pk=self.data['crewmember_' + str(pk)])
|
||||
item.start = self.data['start_' + str(pk)]
|
||||
item.role = self.data['role_' + str(pk)]
|
||||
item.end = self.data['end_' + str(pk)]
|
||||
item.full_clean('checklist')
|
||||
|
||||
# item does not have a database pk yet as it isn't saved
|
||||
self.items['c' + str(pk)] = item
|
||||
|
||||
return super(EventChecklistForm, self).clean()
|
||||
|
||||
@@ -203,15 +230,18 @@ class EventChecklistForm(forms.ModelForm):
|
||||
if (commit):
|
||||
# Remove all existing, to be recreated from the form
|
||||
checklist.vehicles.all().delete()
|
||||
checklist.save()
|
||||
checklist.crew.all().delete()
|
||||
|
||||
for key in self.items:
|
||||
item = self.items[key]
|
||||
reversion.add_to_revision(item)
|
||||
# finish and save new database items
|
||||
item.checklist = checklist
|
||||
item.full_clean()
|
||||
item.save()
|
||||
|
||||
checklist.save()
|
||||
|
||||
self.items.clear()
|
||||
|
||||
return checklist
|
||||
|
||||
31
RIGS/migrations/0047_auto_20200829_2105.py
Normal file
31
RIGS/migrations/0047_auto_20200829_2105.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Generated by Django 3.1 on 2020-08-29 20:05
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('RIGS', '0046_auto_20200828_1246'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='eventchecklistvehicle',
|
||||
name='driver',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vehicles', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EventChecklistCrew',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('role', models.CharField(max_length=255, null=True)),
|
||||
('start', models.DateTimeField(blank=True, null=True)),
|
||||
('end', models.DateTimeField(blank=True, null=True)),
|
||||
('checklist', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='crew', to='RIGS.eventchecklist')),
|
||||
('crewmember', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='crewed', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -635,7 +635,7 @@ class RiskAssessment(models.Model, RevisionMixin):
|
||||
return "%i - %s" % (self.pk, self.event)
|
||||
|
||||
|
||||
@reversion.register(follow=['vehicles', ])
|
||||
@reversion.register(follow=['vehicles', 'crew'])
|
||||
class EventChecklist(models.Model, RevisionMixin):
|
||||
event = models.OneToOneField('Event', on_delete=models.CASCADE)
|
||||
|
||||
@@ -680,9 +680,23 @@ class EventChecklist(models.Model, RevisionMixin):
|
||||
class EventChecklistVehicle(models.Model):
|
||||
checklist = models.ForeignKey('EventChecklist', related_name='vehicles', blank=True, on_delete=models.CASCADE)
|
||||
vehicle = models.CharField(max_length=255)
|
||||
driver = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='drivers', on_delete=models.CASCADE)
|
||||
driver = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='vehicles', on_delete=models.CASCADE)
|
||||
|
||||
reversion_hide = True
|
||||
|
||||
def __str__(self):
|
||||
return "{} driven by {}".format(self.vehicle, str(self.driver))
|
||||
|
||||
|
||||
@reversion.register
|
||||
class EventChecklistCrew(models.Model):
|
||||
checklist = models.ForeignKey('EventChecklist', related_name='crew', blank=True, on_delete=models.CASCADE)
|
||||
crewmember = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='crewed', on_delete=models.CASCADE)
|
||||
role = models.CharField(max_length=255)
|
||||
start = models.DateTimeField()
|
||||
end = models.DateTimeField()
|
||||
|
||||
reversion_hide = True
|
||||
|
||||
def __str__(self):
|
||||
return "{} ({})".format(str(self.crewmember), self.role)
|
||||
|
||||
@@ -61,6 +61,16 @@
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card card-default mb-3">
|
||||
<div class="card-header">Crew Record</div>
|
||||
<div class="card-body">
|
||||
<ul>
|
||||
{% for i in object.crew.all %}
|
||||
<li>{{i}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card card-default mb-3">
|
||||
<div class="card-header">Power</div>
|
||||
<div class="card-body">
|
||||
|
||||
@@ -35,9 +35,11 @@
|
||||
{% if object.medium_event %}
|
||||
$('#small-event').slideUp();
|
||||
$('#medium-event').slideDown();
|
||||
$('#size-selector button[data-event-size=1]').addClass('active');
|
||||
{% else %}
|
||||
$('#small-event').slideDown();
|
||||
$('#medium-event').slideUp();
|
||||
$('#size-selector button[data-event-size=0]').addClass('active');
|
||||
{% endif%}
|
||||
{% endif %}
|
||||
$('#size-selector button').on('click', function () {
|
||||
@@ -53,24 +55,29 @@
|
||||
$('#medium-event').slideUp();
|
||||
}
|
||||
});
|
||||
$('#vehicle-add').on('click', function (event) {
|
||||
$('button[data-action=add]').on('click', function (event) {
|
||||
event.preventDefault();
|
||||
var newID = Number($('#vehiclest').attr('data-pk'));
|
||||
$('#vehicles_new').clone().attr('style', "").attr('id', 'vehicles_' + newID).appendTo('#vehiclest');
|
||||
$('#vehicles_' + newID).find('select,input').attr('name', function(){
|
||||
return this.name.split('_')[0] + '_' + newID;
|
||||
//Disabled prevents the hidden row being sent to the form
|
||||
}).removeAttr('disabled');
|
||||
$('#vehicles_' + newID).find('button[data-action=delete]').attr('data-id', newID);
|
||||
$('#vehicles_' + newID).find('select').addClass('selectpicker');
|
||||
$('#vehicles_' + newID).find('.selectpicker').selectpicker('refresh');
|
||||
var target = $($(this).attr('data-target'));
|
||||
var newID = Number(target.attr('data-pk'));
|
||||
var newRow = $($(this).attr('data-clone'))
|
||||
.clone().attr('style', "")
|
||||
.attr('id', function(i, val){
|
||||
return val.split("_")[0] + '_' + newID;
|
||||
})
|
||||
.appendTo(target);
|
||||
newRow.find('select,input').attr('name', function(i, val){
|
||||
return val.split("_")[0] + '_' + newID;
|
||||
})//Disabled is to prevent the hidden row being sent to the form
|
||||
.removeAttr('disabled');
|
||||
newRow.find('button[data-action=delete]').attr('data-id', newID);
|
||||
newRow.find('select').addClass('selectpicker');
|
||||
newRow.find('.selectpicker').selectpicker('refresh');
|
||||
$(".selectpicker").each(function(){initPicker($(this))});
|
||||
$('#vehiclest').attr('data-pk', newID - 1);
|
||||
$(target).attr('data-pk', newID - 1);
|
||||
});
|
||||
$('button[data-action=delete]').on('click', function(event) {
|
||||
event.preventDefault();
|
||||
console.log($(this).attr('data-id'));
|
||||
$('#vehicles_' + $(this).attr('data-id')).remove();
|
||||
$($(this).attr('data-target') + '_' + $(this).attr('data-id')).remove();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -124,11 +131,8 @@
|
||||
<tbody id="vehiclest" data-pk="-1">
|
||||
<tr id="vehicles_new" style="display: none;">
|
||||
<td><input type="text" class="form-control" name="vehicle_new" disabled="true"/></td>
|
||||
<td>
|
||||
<select class="form-control" data-live-search="true" data-sourceurl="{% url 'api_secure' model='profile' %}?fields=first_name,last_name,initials" name="driver_new" disabled="true">
|
||||
</select>
|
||||
</td>
|
||||
<td><button class="btn btn-danger" data-action='delete'><span class="fas fa-times"></span></button</td>
|
||||
<td><select class="form-control" data-live-search="true" data-sourceurl="{% url 'api_secure' model='profile' %}?fields=first_name,last_name,initials" name="driver_new" disabled="true"></select></td>
|
||||
<td><button class="btn btn-danger" data-action='delete' data-target='#vehicle'><span class="fas fa-times"></span></button</td>
|
||||
</tr>
|
||||
{# TODO Add required to all fields on row when one is edited #}
|
||||
{% for i in object.vehicles.all %}
|
||||
@@ -141,13 +145,13 @@
|
||||
{% endif %}
|
||||
</select>
|
||||
</td>
|
||||
<td><button class="btn btn-danger" data-id='{{i.pk}}' data-action='delete'><span class="fas fa-times"></span></button</td>
|
||||
<td><button class="btn btn-danger" data-id='{{i.pk}}' data-action='delete' data-target='#vehicle'><span class="fas fa-times"></span></button</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="text-right">
|
||||
<button class="btn btn-secondary" id="vehicle-add"><span class="fas fa-plus"></span> Add Vehicle</button>
|
||||
<button class="btn btn-secondary" id="vehicle-add" data-action='add' data-target='#vehiclest' data-clone='#vehicles_new'><span class="fas fa-plus"></span> Add Vehicle</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -184,23 +188,38 @@
|
||||
<th scope="col">Start Time</th>
|
||||
<th scope="col">Role</th>
|
||||
<th scope="col">End Time</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for i in '012'|make_list %}
|
||||
<tr>
|
||||
|
||||
<th scope="row">
|
||||
</th>
|
||||
<td><input type="time" class="form-control"/></td>
|
||||
<td><input type="text" class="form-control"/></td>
|
||||
<td><input type="time" class="form-control"/></td>
|
||||
<tbody id="crewmemberst" data-pk="-1">
|
||||
<tr id="crew_new" style="display: none;">
|
||||
<td>
|
||||
<select name="crewmember_new" class="form-control" data-live-search="true" data-sourceurl="{% url 'api_secure' model='profile' %}?fields=first_name,last_name,initials" disabled="true"></select>
|
||||
</td>
|
||||
<td><input name="start_new" type="datetime-local" class="form-control" value="{{ i.start }}" disabled="true"/></td>
|
||||
<td><input name="role_new" type="text" class="form-control" value="{{ i.role }}" disabled="true"/></td>
|
||||
<td><input name="end_new" type="datetime-local" class="form-control" value="{{ i.end }}" disabled="true" /></td>
|
||||
<td><button class="btn btn-danger" data-id='{{crew.pk}}' data-action='delete' data-target='#crewmember'><span class="fas fa-times"></span></button</td>
|
||||
</tr>
|
||||
{% for crew in object.crew.all %}
|
||||
<tr id="crew_{{crew.pk}}">
|
||||
<td>
|
||||
<select name="crewmember_{{crew.pk}}" class="form-control selectpicker" data-live-search="true" data-sourceurl="{% url 'api_secure' model='profile' %}?fields=first_name,last_name,initials">
|
||||
{% if crew.crewmember != '' %}
|
||||
<option value="{{crew.crewmember.pk}}" selected="selected">{{ crew.crewmember.name }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</td>
|
||||
<td><input name="start_{{crew.pk}}" type="datetime-local" class="form-control" value="{{ crew.start|date:'Y-m-d' }}T{{ crew.start|date:'H:i:s' }}"/></td>
|
||||
<td><input name="role_{{crew.pk}}" type="text" class="form-control" value="{{ crew.role }}"/></td>
|
||||
<td><input name="end_{{crew.pk}}" type="datetime-local" class="form-control" value="{{ crew.end|date:'Y-m-d' }}T{{ crew.end|date:'H:i:s' }}"/></td>
|
||||
<td><button class="btn btn-danger" data-id='{{crew.pk}}' data-action='delete' data-target='#crewmember'><span class="fas fa-times"></span></button</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="text-right">
|
||||
<button class="btn btn-secondary"><span class="fas fa-plus"></span> Add Crewmember</button>
|
||||
<button class="btn btn-secondary" data-action='add' data-target='#crewmemberst' data-clone='#crew_new'><span class="fas fa-plus"></span> Add Crewmember</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user