Merge branch 'master' into fixed_jquery

This commit is contained in:
Tom Price
2016-03-17 17:10:35 +00:00
16 changed files with 144 additions and 40 deletions

View File

@@ -1,5 +1,5 @@
# TEC PA & Lighting - PyRIGS # # TEC PA & Lighting - PyRIGS #
[![wercker status](https://app.wercker.com/status/b26100ecccdfb46a9a9056553daac5b7/m/master "wercker status")](https://app.wercker.com/project/bykey/b26100ecccdfb46a9a9056553daac5b7) [![wercker status](https://app.wercker.com/status/2dbe0517c3d83859c985ffc5a55a2802/m "wercker status")](https://app.wercker.com/project/bykey/2dbe0517c3d83859c985ffc5a55a2802)
Welcome to TEC PA & Lightings PyRIGS program. This is a reimplementation of the existing Rig Information Gathering System (RIGS) that was developed using Ruby on Rails. Welcome to TEC PA & Lightings PyRIGS program. This is a reimplementation of the existing Rig Information Gathering System (RIGS) that was developed using Ruby on Rails.
@@ -75,4 +75,4 @@ python manage.py runserver
Please refer to Django documentation for a full list of options available here. Please refer to Django documentation for a full list of options available here.
### Committing, pushing and testing ### ### Committing, pushing and testing ###
Feel free to commit as you wish, on your own branch. On my branch (master for development) do not commit code that you either know doesn't work or don't know works. If you must commit this code, please make sure you say in the commit message that it isn't working, and if you can why it isn't working. If and only if you absolutely must push, then please don't leave it as the HEAD for too long, it's not much to ask but when you are done just make sure you haven't broken the HEAD for the next person. Feel free to commit as you wish, on your own branch. On my branch (master for development) do not commit code that you either know doesn't work or don't know works. If you must commit this code, please make sure you say in the commit message that it isn't working, and if you can why it isn't working. If and only if you absolutely must push, then please don't leave it as the HEAD for too long, it's not much to ask but when you are done just make sure you haven't broken the HEAD for the next person.

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('RIGS', '0023_auto_20150529_0048'),
]
operations = [
migrations.AlterField(
model_name='event',
name='based_on',
field=models.ForeignKey(related_name='future_events', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='RIGS.Event', null=True),
),
]

View File

@@ -301,7 +301,7 @@ class Event(models.Model, RevisionMixin):
status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL) status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL)
dry_hire = models.BooleanField(default=False) dry_hire = models.BooleanField(default=False)
is_rig = models.BooleanField(default=True) is_rig = models.BooleanField(default=True)
based_on = models.ForeignKey('Event', related_name='future_events', blank=True, null=True) based_on = models.ForeignKey('Event', on_delete=models.SET_NULL, related_name='future_events', blank=True, null=True)
# Timing # Timing
start_date = models.DateField() start_date = models.DateField()

View File

@@ -37,6 +37,12 @@ class RigboardIndex(generic.TemplateView):
class WebCalendar(generic.TemplateView): class WebCalendar(generic.TemplateView):
template_name = 'RIGS/calendar.html' template_name = 'RIGS/calendar.html'
def get_context_data(self, **kwargs):
context = super(WebCalendar, self).get_context_data(**kwargs)
context['view'] = kwargs.get('view','')
context['date'] = kwargs.get('date','')
return context
class EventDetail(generic.DetailView): class EventDetail(generic.DetailView):
model = models.Event model = models.Event

View File

@@ -11,6 +11,7 @@ fonts_dir = "fonts"
# You can select your preferred output style here (can be overridden via the command line): # You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed # output_style = :expanded or :nested or :compact or :compressed
output_style = :compressed
# To enable relative paths to assets via compass helper functions. Uncomment: # To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true # relative_assets = true

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -75,6 +75,16 @@ textarea {
} }
} }
del {
background-color: #f2dede;
border-radius: 3px;
}
ins {
background-color: #dff0d8;
border-radius: 3px;
}
.loading-animation { .loading-animation {
position: relative; position: relative;
margin: 30px auto 0; margin: 30px auto 0;

View File

@@ -14,8 +14,28 @@
<script src="{% static "js/moment.min.js" %}"></script> <script src="{% static "js/moment.min.js" %}"></script>
<script src="{% static "js/fullcalendar.js" %}"></script> <script src="{% static "js/fullcalendar.js" %}"></script>
<script> <script>
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
$(document).ready(function() { $(document).ready(function() {
viewToUrl = {
'agendaWeek':'week',
'agendaDay':'day',
'month':'month'
}
viewFromUrl = {
'week':'agendaWeek',
'day':'agendaDay',
'month':'month'
}
$('#calendar').fullCalendar({ $('#calendar').fullCalendar({
editable: false, editable: false,
eventLimit: true, // allow "more" link when too many events eventLimit: true, // allow "more" link when too many events
@@ -114,8 +134,11 @@
$('#day-button').addClass('active'); $('#day-button').addClass('active');
break; break;
} }
history.replaceState(null,null,'{% url 'web_calendar' %}'+viewToUrl[view.name]+'/'+view.intervalStart.format('YYYY-MM-DD')+'/');
} }
}); });
// set some button listeners // set some button listeners
@@ -146,6 +169,18 @@
} }
}); });
// Go to the initial settings, if they're valid
view = viewFromUrl['{{view}}'];
$('#calendar').fullCalendar( 'changeView', view);
day = moment('{{date}}');
if(day.isValid()){
$('#calendar').fullCalendar( 'gotoDate', day);
}else{
console.log('Supplied date is invalid - using default')
}
}); });
</script> </script>

View File

@@ -1,40 +1,21 @@
{% for change in version.field_changes %} {% for change in version.field_changes %}
<button title="Changes to {{ change.field.verbose_name }}" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content=' <button title="Changes to {{ change.field.verbose_name }}" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content='{% spaceless %}
{% include "RIGS/version_changes_change.html" %}
{% if change.new %} {% endspaceless %}'>{{ change.field.verbose_name }}</button>
<div class="alert alert-success {% if change.long %}overflow-ellipsis{% endif %}">
{% if change.linebreaks %}
{{change.new|linebreaksbr}}
{% else %}
{{change.new}}
{% endif %}
</div>
{% endif %}
{% if change.old %}
<div class="alert alert-danger {% if change.long %}overflow-ellipsis{% endif %}">
{% if change.linebreaks %}
{{change.old|linebreaksbr}}
{% else %}
{{change.old}}
{% endif %}
</div>
{% endif %}
'>{{ change.field.verbose_name }}</button>
{% endfor %} {% endfor %}
{% for itemChange in version.item_changes %} {% for itemChange in version.item_changes %}
<button title="Changes to item '{% if itemChange.new %}{{ itemChange.new.name }}{% else %}{{ itemChange.old.name }}{% endif %}'" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content=' <button title="Changes to item '{% if itemChange.new %}{{ itemChange.new.name }}{% else %}{{ itemChange.old.name }}{% endif %}'" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content='{% spaceless %}
<ul class="list-group">
{% for change in itemChange.changes %} {% for change in itemChange.changes %}
<h4>{{ change.field.verbose_name }}</h4> <li class="list-group-item">
<h4 class="list-group-item-heading">{{ change.field.verbose_name }}</h4>
{% if change.new %}<div class="alert alert-success">{{change.new|linebreaksbr}}</div>{% endif %} {% include "RIGS/version_changes_change.html" %}
{% if change.old %}<div class="alert alert-danger">{{change.old|linebreaksbr}}</div>{% endif %} </li>
{% endfor %} {% endfor %}
</ul>
'>item '{% if itemChange.new %}{{ itemChange.new.name }}{% else %}{{ itemChange.old.name }}{% endif %}'</button> {% endspaceless %}'>item '{% if itemChange.new %}{{ itemChange.new.name }}{% else %}{{ itemChange.old.name }}{% endif %}'</button>
{% endfor %} {% endfor %}

View File

@@ -0,0 +1,26 @@
{# pass in variable "change" to this template #}
{% if change.linebreaks and change.new and change.old %}
{% for diff in change.diff %}
{% if diff.type == "insert" %}
<ins>{{ diff.text|linebreaksbr }}</ins>
{% elif diff.type == "delete" %}
<del>{{diff.text|linebreaksbr}}</del>
{% else %}
<span>{{diff.text|linebreaksbr}}</span>
{% endif %}
{% endfor %}
{% else %}
{% if change.old %}
<del {% if change.long %}class="overflow-ellipsis"{% endif %}>
{{change.old}}
</del>
{% endif %}
{% if change.new and change.old %}
<br/>
{% endif %}
{% if change.new %}
<ins {% if change.long %}class="overflow-ellipsis"{% endif %}>
{{change.new}}
</ins>
{% endif %}
{% endif %}

View File

@@ -420,8 +420,9 @@ class EventTest(LiveServerTestCase):
e.send_keys(Keys.ENTER) e.send_keys(Keys.ENTER)
# See redirected to success page # See redirected to success page
successTitle = self.browser.find_element_by_xpath('//h1').text
event = models.Event.objects.get(name='Test Event Name') event = models.Event.objects.get(name='Test Event Name')
self.assertIn("N0000%d | Test Event Name"%event.pk, self.browser.find_element_by_xpath('//h1').text) self.assertIn("N0000%d | Test Event Name"%event.pk, successTitle)
def testEventDuplicate(self): def testEventDuplicate(self):
testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, start_date=date.today() + timedelta(days=6), description="start future no end") testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, start_date=date.today() + timedelta(days=6), description="start future no end")
@@ -608,9 +609,10 @@ class EventTest(LiveServerTestCase):
save.click() save.click()
# See redirected to success page # See redirected to success page
successTitle = self.browser.find_element_by_xpath('//h1').text
event = models.Event.objects.get(name='Test Event Name') event = models.Event.objects.get(name='Test Event Name')
self.assertIn("N0000%d | Test Event Name"%event.pk, self.browser.find_element_by_xpath('//h1').text) self.assertIn("N0000%d | Test Event Name"%event.pk, successTitle)
def testRigNonRig(self): def testRigNonRig(self):
self.browser.get(self.live_server_url + '/event/create/') self.browser.get(self.live_server_url + '/event/create/')
# Gets redirected to login and back # Gets redirected to login and back

View File

@@ -69,6 +69,8 @@ urlpatterns = patterns('',
# Rigboard # Rigboard
url(r'^rigboard/$', login_required(rigboard.RigboardIndex.as_view()), name='rigboard'), url(r'^rigboard/$', login_required(rigboard.RigboardIndex.as_view()), name='rigboard'),
url(r'^rigboard/calendar/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'), url(r'^rigboard/calendar/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
url(r'^rigboard/calendar/(?P<view>(month|week|day))/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
url(r'^rigboard/calendar/(?P<view>(month|week|day))/(?P<date>(\d{4}-\d{2}-\d{2}))/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
url(r'^rigboard/archive/$', RedirectView.as_view(permanent=True,pattern_name='event_archive')), url(r'^rigboard/archive/$', RedirectView.as_view(permanent=True,pattern_name='event_archive')),
url(r'^rigboard/activity/$', url(r'^rigboard/activity/$',
permission_required_with_403('RIGS.view_event')(versioning.ActivityTable.as_view()), permission_required_with_403('RIGS.view_event')(versioning.ActivityTable.as_view()),

View File

@@ -17,6 +17,7 @@ from reversion.models import Version
from django.contrib.contenttypes.models import ContentType # Used to lookup the content_type from django.contrib.contenttypes.models import ContentType # Used to lookup the content_type
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import ForeignKey, IntegerField, EmailField, TextField from django.db.models import ForeignKey, IntegerField, EmailField, TextField
from diff_match_patch import diff_match_patch
from RIGS import models, forms from RIGS import models, forms
import datetime import datetime
@@ -64,6 +65,25 @@ def model_compare(oldObj, newObj, excluded_keys=[]):
return True return True
return False return False
@property
def diff(self):
oldText = unicode(self.display_value(self._old)) or ""
newText = unicode(self.display_value(self._new)) or ""
dmp = diff_match_patch()
diffs = dmp.diff_main(oldText, newText)
dmp.diff_cleanupSemantic(diffs)
outputDiffs = []
for (op, data) in diffs:
if op == dmp.DIFF_INSERT:
outputDiffs.append({'type':'insert', 'text':data})
elif op == dmp.DIFF_DELETE:
outputDiffs.append({'type':'delete', 'text':data})
elif op == dmp.DIFF_EQUAL:
outputDiffs.append({'type':'equal', 'text':data})
return outputDiffs
changes = [] changes = []
for thisField in theFields: for thisField in theFields:

Binary file not shown.

View File

@@ -1,3 +1,4 @@
diff-match-patch==20121119
dj-database-url==0.3.0 dj-database-url==0.3.0
dj-static==0.0.6 dj-static==0.0.6
Django==1.8.2 Django==1.8.2