mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-21 07:22:14 +00:00
More refactoring & improvements
This commit is contained in:
@@ -184,6 +184,8 @@ USE_TZ = True
|
|||||||
|
|
||||||
DATETIME_INPUT_FORMATS = ('%Y-%m-%dT%H:%M','%Y-%m-%dT%H:%M:%S')
|
DATETIME_INPUT_FORMATS = ('%Y-%m-%dT%H:%M','%Y-%m-%dT%H:%M:%S')
|
||||||
|
|
||||||
|
RIGS_DATETIME_FORMAT = ('d/m/Y H:i')
|
||||||
|
|
||||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||||
"django.contrib.auth.context_processors.auth",
|
"django.contrib.auth.context_processors.auth",
|
||||||
"django.core.context_processors.debug",
|
"django.core.context_processors.debug",
|
||||||
|
|||||||
@@ -36,9 +36,9 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% comment "table view" %}
|
{# comment "table view" #}
|
||||||
|
|
||||||
<h2>Rigboard Activity Stream</h2>
|
<h2>Rigboard Activity Stream - Table View</h2>
|
||||||
<br>
|
<br>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -52,114 +52,40 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for version in object_list %}
|
{% for version in object_list %}
|
||||||
<tr>
|
{% if version.item_changes or version.field_changes %}
|
||||||
<td>{{ version.revision.date_created|date:"Y-m-d H:i:s" }}</td>
|
<tr>
|
||||||
<td><a href="{% url 'event_detail' version.thisVersion.object_id_int %}">N{{ version.thisVersion.object_id_int|stringformat:"05d" }}</a></td>
|
<td>{{ version.revision.date_created|date:"RIGS_DATETIME_FORMAT" }}</td>
|
||||||
<td>{{ version.pk }}|{{ version.revision.pk }}</td>
|
<td><a href="{% url 'event_detail' version.new.pk %}">N{{ version.new.pk|stringformat:"05d" }}</a></td>
|
||||||
<td>{{ version.revision.user.name }}</td>
|
<td>{{ version.version.pk }}|{{ version.revision.pk }}</td>
|
||||||
<td>{% for key, old, new in version.changes %}
|
<td>{{ version.revision.user.name }}</td>
|
||||||
<button title="Changes to {{ key }}" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content='
|
<td>
|
||||||
|
{% include 'RIGS/event_version_changes.html' %}
|
||||||
{% if new %}<div class="alert alert-success">{{new}}</div>{% endif %}
|
</td>
|
||||||
{% if old %}<div class="alert alert-danger">{{old}}</div>{% endif %}
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
'>{{ key }}</button>
|
|
||||||
{% endfor %}
|
|
||||||
{% for key, old, new in version.item_changes %}
|
|
||||||
<button title="{{ key }}" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content='
|
|
||||||
|
|
||||||
{% if new %}
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<dl>
|
|
||||||
<dt>Name</dt>
|
|
||||||
<dd>{{new.name}}</dd>
|
|
||||||
<dt>Description</dt>
|
|
||||||
<dd>{{new.description|linebreaks}}</dd>
|
|
||||||
<dt>Quantity</dt>
|
|
||||||
<dd>{{new.quantity}}</dd>
|
|
||||||
<dt>Price</dt>
|
|
||||||
<dd>{{new.cost}}
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if old %}
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<dl>
|
|
||||||
<dt>Name</dt>
|
|
||||||
<dd>{{old.name}}</dd>
|
|
||||||
<dt>Description</dt>
|
|
||||||
<dd>{{old.description|linebreaks}}</dd>
|
|
||||||
<dt>Quantity</dt>
|
|
||||||
<dd>{{old.quantity}}</dd>
|
|
||||||
<dt>Price</dt>
|
|
||||||
<dd>{{old.cost}}
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
'>{{ key }}</button>
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% endcomment %}
|
{# endcomment #}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2>Stream View</h2>
|
<br>
|
||||||
|
<h2>Rigboard Activity Stream - Stream View</h2>
|
||||||
|
<br>
|
||||||
{% for version in object_list %}
|
{% for version in object_list %}
|
||||||
<div class="well">
|
{% if version.item_changes or version.field_changes %}
|
||||||
<button title="title" type="button" class="btn btn-default btn-xs">{{ version.revision.user.first_name|default_if_none:"(unknown)" }}</button> changed
|
<div class="well">
|
||||||
{% for key, old, new in version.changes %}
|
<button title="title" type="button" class="btn btn-default btn-xs">{{ version.revision.user.first_name|default_if_none:"(unknown)" }}</button> changed
|
||||||
<button title="Changes to {{ key }}" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content='
|
|
||||||
|
|
||||||
{% if new %}<div class="alert alert-success">{{new}}</div>{% endif %}
|
|
||||||
{% if old %}<div class="alert alert-danger">{{old}}</div>{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
'>{{ key }}</button>
|
{% include 'RIGS/event_version_changes.html' %}
|
||||||
{% endfor %}
|
|
||||||
{% for key, old, new in version.item_changes %}
|
|
||||||
<button title="{{ key }}" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content='
|
|
||||||
|
|
||||||
{% if new %}
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<dl>
|
|
||||||
<dt>Name</dt>
|
|
||||||
<dd>{{new.name}}</dd>
|
|
||||||
<dt>Description</dt>
|
|
||||||
<dd>{{new.description|linebreaks}}</dd>
|
|
||||||
<dt>Quantity</dt>
|
|
||||||
<dd>{{new.quantity}}</dd>
|
|
||||||
<dt>Price</dt>
|
|
||||||
<dd>{{new.cost}}
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if old %}
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<dl>
|
|
||||||
<dt>Name</dt>
|
|
||||||
<dd>{{old.name}}</dd>
|
|
||||||
<dt>Description</dt>
|
|
||||||
<dd>{{old.description|linebreaks}}</dd>
|
|
||||||
<dt>Quantity</dt>
|
|
||||||
<dd>{{old.quantity}}</dd>
|
|
||||||
<dt>Price</dt>
|
|
||||||
<dd>{{old.cost}}
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
'>{{ key }}</button>
|
in <button title="title" type="button" class="btn btn-default btn-xs">N{{ version.new.pk|stringformat:"05d" }}</button> <small>(<span data-date='{{ version.revision.date_created|date:"Y-m-d H:i:s" }}' class="date">{{ version.revision.date_created|date:"RIGS_DATETIME_FORMAT" }}</span>)</small>
|
||||||
{% endfor %}
|
|
||||||
in <button title="title" type="button" class="btn btn-default btn-xs">N{{ version.thisVersion.object_id_int|stringformat:"05d" }}</button> <small>(<span data-date='{{ version.revision.date_created|date:"Y-m-d H:i:s" }}' class="date">{{ version.revision.date_created|date:"Y-m-d H:i:s" }}</span>)</small>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
23
RIGS/templates/RIGS/event_version_changes.html
Normal file
23
RIGS/templates/RIGS/event_version_changes.html
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{% 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='
|
||||||
|
|
||||||
|
{% if change.new %}<div class="alert alert-success">{{change.new}}</div>{% endif %}
|
||||||
|
{% if change.old %}<div class="alert alert-danger">{{change.old}}</div>{% endif %}
|
||||||
|
|
||||||
|
'>{{ change.field.verbose_name }}</button>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for itemChange in version.item_changes %}
|
||||||
|
<button title="Changes to item '{{ itemChange.new.name }}'" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-toggle="popover" data-content='
|
||||||
|
{% for change in itemChange.changes %}
|
||||||
|
<h4>{{ change.field.verbose_name }}</h4>
|
||||||
|
|
||||||
|
{% if change.new %}<div class="alert alert-success">{{change.new}}</div>{% endif %}
|
||||||
|
{% if change.old %}<div class="alert alert-danger">{{change.old}}</div>{% endif %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
'>item '{{ itemChange.new.name }}'</button>
|
||||||
|
{% endfor %}
|
||||||
@@ -27,61 +27,18 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for version in object_list %}
|
{% for version in object_list %}
|
||||||
<tr>
|
{% if version.item_changes or version.field_changes %}
|
||||||
<td>{{ version.pk }}|{{ version.revision.pk }}</td>
|
<tr>
|
||||||
<td>{{ version.revision.date_created|date:"d/m/Y H:i" }}</td>
|
<td>{{ version.version.pk }}|{{ version.revision.pk }}</td>
|
||||||
<td>{{ version.revision.user.name }}</td>
|
<td>{{ version.revision.date_created|date:"d/m/Y H:i" }}</td>
|
||||||
<td>{% for key, old, new in version.changes %}
|
<td>{{ version.revision.user.name }}</td>
|
||||||
<button title="Changes to {{ key }}" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-placement='left' data-toggle="popover" data-content='
|
<td>
|
||||||
|
{% include 'RIGS/event_version_changes.html' %}
|
||||||
{% if new %}<div class="alert alert-success">{{new}}</div>{% endif %}
|
</td>
|
||||||
{% if old %}<div class="alert alert-danger">{{old}}</div>{% endif %}
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
'>{{ key }}</button>
|
|
||||||
{% endfor %}
|
|
||||||
{% for key, old, new in version.item_changes %}
|
|
||||||
<button title="{{ key }}" type="button" class="btn btn-default btn-xs" data-container="body" data-html="true" data-trigger='hover' data-placement='left' data-toggle="popover" data-content='
|
|
||||||
|
|
||||||
{% if new %}
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<dl>
|
|
||||||
<dt>Name</dt>
|
|
||||||
<dd>{{new.name}}</dd>
|
|
||||||
<dt>Description</dt>
|
|
||||||
<dd>{{new.description|linebreaks}}</dd>
|
|
||||||
<dt>Quantity</dt>
|
|
||||||
<dd>{{new.quantity}}</dd>
|
|
||||||
<dt>Price</dt>
|
|
||||||
<dd>£ {{new.cost|default:0|floatformat:2}}
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if old %}
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<dl>
|
|
||||||
<dt>Name</dt>
|
|
||||||
<dd>{{old.name}}</dd>
|
|
||||||
<dt>Description</dt>
|
|
||||||
<dd>{{old.description|linebreaks}}</dd>
|
|
||||||
<dt>Quantity</dt>
|
|
||||||
<dd>{{old.quantity}}</dd>
|
|
||||||
<dt>Price</dt>
|
|
||||||
<dd>£ {{old.cost|default:0|floatformat:2}}
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
'>{{ key }}</button>
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
{{ thediff }}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -22,87 +22,74 @@ import re
|
|||||||
logger = logging.getLogger('tec.pyrigs')
|
logger = logging.getLogger('tec.pyrigs')
|
||||||
|
|
||||||
|
|
||||||
def compare_events(obj1, obj2, excluded_keys=[]):
|
def model_compare(oldObj, newObj, excluded_keys=[]):
|
||||||
theFields = obj1._meta.fields #This becomes deprecated in Django 1.8!!!!!!!!!!!!! (but an alternative becomes available)
|
# recieves two objects of the same model, and compares them. Returns an array of FieldCompare objects
|
||||||
|
try:
|
||||||
|
theFields = oldObj._meta.fields #This becomes deprecated in Django 1.8!!!!!!!!!!!!! (but an alternative becomes available)
|
||||||
|
except AttributeError:
|
||||||
|
theFields = newObj._meta.fields
|
||||||
|
|
||||||
d1, d2 = obj1, obj2
|
|
||||||
field, old, new = [],[],[]
|
|
||||||
|
|
||||||
for thisField in theFields:
|
class FieldCompare(object):
|
||||||
k = thisField.name
|
def __init__(self, field=None, old=None, new=None):
|
||||||
v1 = getattr(d1, k)
|
self.field = field
|
||||||
v2 = getattr(d2, k)
|
|
||||||
logger.info('k:'+str(k)+" v1:"+str(v1)+" v2:"+str(v2))
|
|
||||||
if k in excluded_keys:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
if v1 != v2:
|
|
||||||
field.append(thisField.verbose_name)
|
|
||||||
old.append(v1)
|
|
||||||
new.append(v2)
|
|
||||||
except KeyError:
|
|
||||||
field.append(thisField.verbose_name)
|
|
||||||
old.append(v1)
|
|
||||||
new.append(v2)
|
|
||||||
except TypeError:
|
|
||||||
# avoids issues with naive vs tz-aware datetimes
|
|
||||||
field.append(thisField.verbose_name)
|
|
||||||
old.append(v1)
|
|
||||||
new.append(v2)
|
|
||||||
|
|
||||||
return zip(field,old,new)
|
|
||||||
|
|
||||||
def compare_items(old, new):
|
|
||||||
|
|
||||||
item_type = ContentType.objects.get_for_model(models.EventItem)
|
|
||||||
old_items = old.revision.version_set.filter(content_type=item_type)
|
|
||||||
new_items = new.revision.version_set.filter(content_type=item_type)
|
|
||||||
|
|
||||||
class ItemCompare(object):
|
|
||||||
def __init__(self, old=None, new=None):
|
|
||||||
self.old = old
|
self.old = old
|
||||||
self.new = new
|
self.new = new
|
||||||
|
|
||||||
# Build some dicts of what we have
|
changes = []
|
||||||
item_dict = {}
|
|
||||||
for item in old_items:
|
for thisField in theFields:
|
||||||
compare = ItemCompare(old=item)
|
name = thisField.name
|
||||||
compare.old.field_dict['event_id'] = compare.old.field_dict.pop('event')
|
oldValue = getattr(oldObj, name, None)
|
||||||
item_dict[item.object_id] = compare
|
newValue = getattr(newObj, name, None)
|
||||||
|
|
||||||
|
if name in excluded_keys:
|
||||||
|
continue # if we're excluding this field, skip over it
|
||||||
|
|
||||||
for item in new_items:
|
|
||||||
try:
|
try:
|
||||||
compare = item_dict[item.object_id]
|
if oldValue != newValue:
|
||||||
compare.new = item
|
compare = FieldCompare(thisField,oldValue,newValue)
|
||||||
except KeyError:
|
changes.append(compare)
|
||||||
compare = ItemCompare(new=item)
|
except TypeError: # logs issues with naive vs tz-aware datetimes
|
||||||
compare.new.field_dict['event_id'] = compare.new.field_dict.pop('event')
|
logger.error('TypeError when comparing models')
|
||||||
item_dict[item.object_id] = compare
|
|
||||||
|
return changes
|
||||||
|
|
||||||
# calculate changes
|
def compare_event_items(old, new):
|
||||||
key, old, new = [], [], []
|
# Recieves two event version objects and compares their items, returns an array of ItemCompare objects
|
||||||
for (_, items) in item_dict.items():
|
|
||||||
if items.new is None:
|
|
||||||
key.append("Deleted \"%s\"" % items.old.field_dict['name'])
|
|
||||||
old.append(models.EventItem(**items.old.field_dict))
|
|
||||||
new.append(None)
|
|
||||||
|
|
||||||
elif items.old is None:
|
item_type = ContentType.objects.get_for_model(models.EventItem)
|
||||||
key.append("Added \"%s\"" % items.new.field_dict['name'])
|
old_item_versions = old.revision.version_set.filter(content_type=item_type)
|
||||||
old.append(None)
|
new_item_versions = new.revision.version_set.filter(content_type=item_type)
|
||||||
new.append(models.EventItem(**items.new.field_dict))
|
|
||||||
|
|
||||||
elif items.old.field_dict != items.new.field_dict:
|
class ItemCompare(object):
|
||||||
if items.old.field_dict['name'] == items.new.field_dict['name']:
|
def __init__(self, old=None, new=None, changes=None):
|
||||||
change_text = "\"%s\"" % items.old.field_dict['name']
|
self.old = old
|
||||||
else:
|
self.new = new
|
||||||
change_text = "\"%s\" to \"%s\"" % (items.old.field_dict['name'], items.new.field_dict['name'])
|
self.changes = changes
|
||||||
key.append("Changed %s" % change_text)
|
|
||||||
|
|
||||||
old.append(models.EventItem(**items.old.field_dict))
|
# Build some dicts of what we have
|
||||||
new.append(models.EventItem(**items.new.field_dict))
|
item_dict = {} # build a list of items, key is the item_pk
|
||||||
|
for version in old_item_versions: # put all the old versions in a list
|
||||||
|
compare = ItemCompare(old=version.object_version.object)
|
||||||
|
item_dict[version.object_id] = compare
|
||||||
|
|
||||||
return zip(key,old,new)
|
for version in new_item_versions: # go through the new versions
|
||||||
|
try:
|
||||||
|
compare = item_dict[version.object_id] # see if there's a matching old version
|
||||||
|
compare.new = version.object_version.object # then add the new version to the dictionary
|
||||||
|
except KeyError: # there's no matching old version, so add this item to the dictionary by itself
|
||||||
|
compare = ItemCompare(new=version.object_version.object)
|
||||||
|
|
||||||
|
item_dict[version.object_id] = compare # update the dictionary with the changes
|
||||||
|
|
||||||
|
changes = []
|
||||||
|
for (_, compare) in item_dict.items():
|
||||||
|
if compare.old != compare.new: # has it changed at all (or been created/deleted)
|
||||||
|
compare.changes = model_compare(compare.old, compare.new, ['id','event','order']) # see what's changed
|
||||||
|
changes.append(compare) # transfer into a sequential array to make it easier to deal with later
|
||||||
|
|
||||||
|
return changes
|
||||||
|
|
||||||
def get_versions_for_model(model):
|
def get_versions_for_model(model):
|
||||||
content_type = ContentType.objects.get_for_model(model)
|
content_type = ContentType.objects.get_for_model(model)
|
||||||
@@ -125,29 +112,25 @@ def get_previous_version(version):
|
|||||||
else: #this is probably the initial version
|
else: #this is probably the initial version
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_changes_for_version(thisVersion, previousVersion=None):
|
def get_changes_for_version(newVersion, oldVersion=None):
|
||||||
#Pass in a previous version if you already know it (for efficiency)
|
#Pass in a previous version if you already know it (for efficiancy)
|
||||||
#if not provided then it will be looked up in the database
|
#if not provided then it will be looked up in the database
|
||||||
|
|
||||||
if previousVersion == None:
|
if oldVersion == None:
|
||||||
previousVersion = get_previous_version(thisVersion)
|
oldVersion = get_previous_version(newVersion)
|
||||||
|
|
||||||
compare = {}
|
compare = {}
|
||||||
compare['pk'] = thisVersion.pk
|
compare['revision'] = newVersion.revision
|
||||||
compare['thisVersion'] = thisVersion
|
compare['new'] = newVersion.object_version.object
|
||||||
compare['prevVersion'] = previousVersion
|
compare['version'] = newVersion
|
||||||
compare['revision'] = thisVersion.revision
|
|
||||||
|
|
||||||
if previousVersion:
|
if oldVersion:
|
||||||
compare['changes'] = compare_events(previousVersion.object_version.object, thisVersion.object_version.object)
|
compare['old'] = oldVersion.object_version.object
|
||||||
compare['item_changes'] = compare_items(previousVersion, thisVersion)
|
compare['field_changes'] = model_compare(compare['old'], compare['new'])
|
||||||
else:
|
compare['item_changes'] = compare_event_items(oldVersion, newVersion)
|
||||||
compare['changes'] = [["(initial version)",None,"Event Created"]]
|
|
||||||
|
|
||||||
return compare
|
return compare
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class EventRevisions(generic.ListView):
|
class EventRevisions(generic.ListView):
|
||||||
model = reversion.revisions.Version
|
model = reversion.revisions.Version
|
||||||
template_name = "RIGS/event_version_list.html"
|
template_name = "RIGS/event_version_list.html"
|
||||||
@@ -161,7 +144,7 @@ class EventRevisions(generic.ListView):
|
|||||||
thisItem = get_changes_for_version(thisVersion, None)
|
thisItem = get_changes_for_version(thisVersion, None)
|
||||||
else:
|
else:
|
||||||
thisItem = get_changes_for_version(thisVersion, versions[versionNo+1])
|
thisItem = get_changes_for_version(thisVersion, versions[versionNo+1])
|
||||||
|
|
||||||
items.append(thisItem)
|
items.append(thisItem)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
|
|||||||
Reference in New Issue
Block a user