mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-03-07 20:48:24 +00:00
Compare commits
15 Commits
assets
...
auth_fixes
| Author | SHA1 | Date | |
|---|---|---|---|
| 081a9eadfe | |||
| 01a87e0e0b | |||
|
|
7c876348d7 | ||
|
ddc23ce4e5
|
|||
|
602ccc15ea
|
|||
|
|
b77615b9b9 | ||
|
|
228d72b7b2 | ||
|
62541194ee
|
|||
|
0d8fd99d92
|
|||
|
9d51a82f31
|
|||
|
c059227d5d
|
|||
|
2c334196d5
|
|||
| 4f036af85a | |||
|
8e27dae895
|
|||
|
22ef6b8e3a
|
1
Procfile
1
Procfile
@@ -1 +1,2 @@
|
||||
release: python manage.py migrate
|
||||
web: gunicorn PyRIGS.wsgi --log-file -
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-10 align-left">
|
||||
<a href="{% url 'event_history' object.pk %}" title="View Revision History">
|
||||
Last edited at {{ object.last_edited_at }} by {{ object.last_edited_by.name }}
|
||||
Last edited at {{ object.last_edited_at|default:'never' }} by {{ object.last_edited_by.name|default:'nobody' }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<p>
|
||||
Your event <b>N{{ object.event.pk|stringformat:"05d" }}</b> has been successfully authorised
|
||||
for <b>£{{ object.amount }}</b>
|
||||
by <b>{{ object.name }}</b> as of <b>{{ object.last_edited_at }}</b>.
|
||||
by <b>{{ object.name }}</b> as of <b>{{ object.event.last_edited_at }}</b>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Hi {{ to_name|default:"there" }},
|
||||
Hi {{ to_name|default_if_none:"there" }},
|
||||
|
||||
Your event N{{object.event.pk|stringformat:"05d"}} has been successfully authorised for £{{object.amount}} by {{object.name}} as of {{object.last_edited_at}}.
|
||||
Your event N{{object.event.pk|stringformat:"05d"}} has been successfully authorised for £{{object.amount}} by {{object.name}} as of {{object.event.last_edited_at}}.
|
||||
|
||||
{% if object.event.organisation and object.event.organisation.union_account %}{# internal #}
|
||||
Your event is now fully booked and payment will be processed by the finance department automatically.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Hi {{object.event.mic.get_full_name|default_if_none:"somebody"}},
|
||||
|
||||
Just to let you know your event N{{object.event.pk|stringformat:"05d"}} has been successfully authorised for £{{object.amount}} by {{object.name}} as of {{object.last_edited_at}}.
|
||||
Just to let you know your event N{{object.event.pk|stringformat:"05d"}} has been successfully authorised for £{{object.amount}} by {{object.name}} as of {{object.event.last_edited_at}}.
|
||||
|
||||
The TEC Rig Information Gathering System
|
||||
|
||||
@@ -72,9 +72,8 @@
|
||||
</div>
|
||||
</div>
|
||||
{% if perms.RIGS.view_event %}
|
||||
<div class="col-sm-6" >
|
||||
<div class="col-sm-6">
|
||||
{% include 'RIGS/activity_feed.html' %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -206,17 +206,14 @@ class VersionHistory(generic.ListView):
|
||||
paginate_by = 25
|
||||
|
||||
def get_queryset(self, **kwargs):
|
||||
thisModel = self.kwargs['model']
|
||||
return RIGSVersion.objects.get_for_object(self.get_object()).select_related("revision", "revision__user").all()
|
||||
|
||||
versions = RIGSVersion.objects.get_for_object_reference(thisModel, self.kwargs['pk']).select_related("revision", "revision__user").all()
|
||||
|
||||
return versions
|
||||
def get_object(self, **kwargs):
|
||||
return get_object_or_404(self.kwargs['model'], pk=self.kwargs['pk'])
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
thisModel = self.kwargs['model']
|
||||
context = super(VersionHistory, self).get_context_data(**kwargs)
|
||||
thisObject = get_object_or_404(thisModel, pk=self.kwargs['pk'])
|
||||
context['object'] = thisObject
|
||||
context['object'] = self.get_object()
|
||||
|
||||
return context
|
||||
|
||||
|
||||
@@ -30,8 +30,3 @@ class AssetAdmin(admin.ModelAdmin):
|
||||
@admin.register(assets.Connector)
|
||||
class ConnectorAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', '__str__', 'current_rating', 'voltage_rating', 'num_pins']
|
||||
|
||||
|
||||
admin.AdminSite.site_header = 'PyAssets - TEC\'s Asset System'
|
||||
admin.AdminSite.site_title = 'PyAssets Admin'
|
||||
admin.AdminSite.index_title = 'System Administration'
|
||||
|
||||
@@ -7,6 +7,7 @@ class AssetForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = models.Asset
|
||||
fields = '__all__'
|
||||
exclude = ['asset_id_prefix', 'asset_id_number']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import random
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.utils import timezone
|
||||
|
||||
from assets import models
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class Command(BaseCommand):
|
||||
suppliers = models.Supplier.objects.all()
|
||||
|
||||
for i in range(100):
|
||||
asset = models.Asset.objects.create(
|
||||
asset = models.Asset(
|
||||
asset_id='{}'.format(models.Asset.get_available_asset_id()),
|
||||
description=random.choice(asset_description),
|
||||
category=random.choice(categories),
|
||||
@@ -62,11 +62,12 @@ class Command(BaseCommand):
|
||||
|
||||
if i % 3 == 0:
|
||||
asset.purchased_from = random.choice(suppliers)
|
||||
|
||||
asset.clean()
|
||||
asset.save()
|
||||
|
||||
def create_cables(self):
|
||||
asset_description = ['The worm', 'Harting without a cap', 'Heavy cable', 'Extension lead', 'IEC cable that we should remember to prep']
|
||||
asset_prefixes = ["C", "C4P", "CBNC", "CDMX", "CDV", "CRCD", "CSOCA", "CXLR"]
|
||||
|
||||
csas = [0.75, 1.00, 1.25, 2.5, 4]
|
||||
lengths = [1, 2, 5, 10, 15, 20, 25, 30, 50, 100]
|
||||
@@ -78,7 +79,7 @@ class Command(BaseCommand):
|
||||
connectors = models.Connector.objects.all()
|
||||
|
||||
for i in range(100):
|
||||
asset = models.Asset.objects.create(
|
||||
asset = models.Asset(
|
||||
asset_id='{}'.format(models.Asset.get_available_asset_id()),
|
||||
description=random.choice(asset_description),
|
||||
category=random.choice(categories),
|
||||
@@ -94,12 +95,17 @@ class Command(BaseCommand):
|
||||
cores=random.choice(circuits)
|
||||
)
|
||||
|
||||
if i % 5 == 0:
|
||||
prefix = random.choice(asset_prefixes)
|
||||
asset.asset_id = prefix + str(models.Asset.get_available_asset_id(wanted_prefix=prefix))
|
||||
|
||||
if i % 4 == 0:
|
||||
asset.parent = models.Asset.objects.order_by('?').first()
|
||||
|
||||
if i % 3 == 0:
|
||||
asset.purchased_from = random.choice(suppliers)
|
||||
|
||||
asset.clean()
|
||||
asset.save()
|
||||
|
||||
def create_connectors(self):
|
||||
|
||||
51
assets/migrations/0008_auto_20191206_2124.py
Normal file
51
assets/migrations/0008_auto_20191206_2124.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# Generated by Django 2.0.13 on 2019-12-06 21:24
|
||||
|
||||
from django.db import migrations, models, transaction
|
||||
import re
|
||||
|
||||
def forwards(apps, schema_editor):
|
||||
AssetModel = apps.get_model('assets', 'Asset')
|
||||
with transaction.atomic():
|
||||
for row in AssetModel.objects.all():
|
||||
|
||||
row.asset_id = row.asset_id.upper()
|
||||
asset_search = re.search("^([A-Z0-9]*?[A-Z]?)([0-9]+)$", row.asset_id)
|
||||
if asset_search is None: # If the asset_id doesn't have a number at the end
|
||||
row.asset_id += "1"
|
||||
|
||||
asset_search = re.search("^([A-Z0-9]*?[A-Z]?)([0-9]+)$", row.asset_id)
|
||||
row.asset_id_prefix = asset_search.group(1)
|
||||
row.asset_id_number = int(asset_search.group(2))
|
||||
|
||||
row.save(update_fields=['asset_id', 'asset_id_prefix', 'asset_id_number'])
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0007_auto_20190108_0202_squashed_0014_auto_20191017_2052'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='asset',
|
||||
options={'ordering': ['asset_id_prefix', 'asset_id_number'], 'permissions': (('asset_finance', 'Can see financial data for assets'), ('view_asset', 'Can view an asset'))},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='asset_id_number',
|
||||
field=models.IntegerField(default=1),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='asset_id_prefix',
|
||||
field=models.CharField(default='', max_length=8),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='asset_id',
|
||||
field=models.CharField(max_length=15, unique=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=forwards,
|
||||
reverse_code=migrations.operations.special.RunPython.noop,
|
||||
),
|
||||
]
|
||||
@@ -3,6 +3,14 @@ from django.core.exceptions import ValidationError
|
||||
from django.db import models, connection
|
||||
from django.urls import reverse
|
||||
|
||||
from django.db.models.signals import pre_save
|
||||
from django.dispatch.dispatcher import receiver
|
||||
|
||||
from reversion import revisions as reversion
|
||||
from reversion.models import Version
|
||||
|
||||
from RIGS.models import RevisionMixin
|
||||
|
||||
|
||||
class AssetCategory(models.Model):
|
||||
class Meta:
|
||||
@@ -21,13 +29,15 @@ class AssetStatus(models.Model):
|
||||
verbose_name_plural = 'Asset Statuses'
|
||||
|
||||
name = models.CharField(max_length=80)
|
||||
should_show = models.BooleanField(default=True, help_text="Should this be shown by default in the asset list.")
|
||||
should_show = models.BooleanField(
|
||||
default=True, help_text="Should this be shown by default in the asset list.")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Supplier(models.Model):
|
||||
@reversion.register
|
||||
class Supplier(models.Model, RevisionMixin):
|
||||
name = models.CharField(max_length=80)
|
||||
|
||||
class Meta:
|
||||
@@ -52,16 +62,18 @@ class Connector(models.Model):
|
||||
return self.description
|
||||
|
||||
|
||||
class Asset(models.Model):
|
||||
@reversion.register
|
||||
class Asset(models.Model, RevisionMixin):
|
||||
class Meta:
|
||||
ordering = ['asset_id']
|
||||
ordering = ['asset_id_prefix', 'asset_id_number']
|
||||
permissions = (
|
||||
('asset_finance', 'Can see financial data for assets'),
|
||||
('view_asset', 'Can view an asset')
|
||||
)
|
||||
|
||||
parent = models.ForeignKey(to='self', related_name='asset_parent', blank=True, null=True, on_delete=models.SET_NULL)
|
||||
asset_id = models.CharField(max_length=10, unique=True)
|
||||
parent = models.ForeignKey(to='self', related_name='asset_parent',
|
||||
blank=True, null=True, on_delete=models.SET_NULL)
|
||||
asset_id = models.CharField(max_length=15, unique=True)
|
||||
description = models.CharField(max_length=120)
|
||||
category = models.ForeignKey(to=AssetCategory, on_delete=models.CASCADE)
|
||||
status = models.ForeignKey(to=AssetStatus, on_delete=models.CASCADE)
|
||||
@@ -76,25 +88,35 @@ class Asset(models.Model):
|
||||
|
||||
# Cable assets
|
||||
is_cable = models.BooleanField(default=False)
|
||||
plug = models.ForeignKey(Connector, on_delete=models.SET_NULL, related_name='plug', blank=True, null=True)
|
||||
socket = models.ForeignKey(Connector, on_delete=models.SET_NULL, related_name='socket', blank=True, null=True)
|
||||
length = models.DecimalField(decimal_places=1, max_digits=10, blank=True, null=True, help_text='m')
|
||||
csa = models.DecimalField(decimal_places=2, max_digits=10, blank=True, null=True, help_text='mm^2')
|
||||
plug = models.ForeignKey(Connector, on_delete=models.SET_NULL,
|
||||
related_name='plug', blank=True, null=True)
|
||||
socket = models.ForeignKey(Connector, on_delete=models.SET_NULL,
|
||||
related_name='socket', blank=True, null=True)
|
||||
length = models.DecimalField(decimal_places=1, max_digits=10,
|
||||
blank=True, null=True, help_text='m')
|
||||
csa = models.DecimalField(decimal_places=2, max_digits=10,
|
||||
blank=True, null=True, help_text='mm^2')
|
||||
circuits = models.IntegerField(blank=True, null=True)
|
||||
cores = models.IntegerField(blank=True, null=True)
|
||||
|
||||
def get_available_asset_id():
|
||||
# Hidden asset_id components
|
||||
# For example, if asset_id was "C1001" then asset_id_prefix would be "C" and number "1001"
|
||||
asset_id_prefix = models.CharField(max_length=8, default="")
|
||||
asset_id_number = models.IntegerField(default=1)
|
||||
|
||||
def get_available_asset_id(wanted_prefix=""):
|
||||
sql = """
|
||||
SELECT MIN(CAST(a.asset_id AS int))+1
|
||||
SELECT a.asset_id_number+1
|
||||
FROM assets_asset a
|
||||
LEFT OUTER JOIN assets_asset b ON
|
||||
(CAST(a.asset_id AS int) + 1 = CAST(b.asset_id AS int))
|
||||
WHERE b.asset_id IS NULL AND CAST(a.asset_id AS int) >= %s;
|
||||
(a.asset_id_number + 1 = b.asset_id_number AND
|
||||
a.asset_id_prefix = b.asset_id_prefix)
|
||||
WHERE b.asset_id IS NULL AND a.asset_id_number >= %s AND a.asset_id_prefix = %s;
|
||||
"""
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(sql, [9000])
|
||||
cursor.execute(sql, [9000, wanted_prefix])
|
||||
row = cursor.fetchone()
|
||||
if row[0] is None:
|
||||
if row is None or row[0] is None:
|
||||
return 9000
|
||||
else:
|
||||
return row[0]
|
||||
@@ -114,8 +136,10 @@ class Asset(models.Model):
|
||||
errdict["date_sold"] = ["Cannot sell an item before it is acquired"]
|
||||
|
||||
self.asset_id = self.asset_id.upper()
|
||||
if re.search("^[a-zA-Z0-9]+$", self.asset_id) is None:
|
||||
errdict["asset_id"] = ["An Asset ID can only consist of letters and numbers"]
|
||||
asset_search = re.search("^([a-zA-Z0-9]*?[a-zA-Z]?)([0-9]+)$", self.asset_id)
|
||||
if asset_search is None:
|
||||
errdict["asset_id"] = [
|
||||
"An Asset ID can only consist of letters and numbers, with a final number"]
|
||||
|
||||
if self.purchase_price and self.purchase_price < 0:
|
||||
errdict["purchase_price"] = ["A price cannot be negative"]
|
||||
@@ -139,3 +163,14 @@ class Asset(models.Model):
|
||||
|
||||
if errdict != {}: # If there was an error when validation
|
||||
raise ValidationError(errdict)
|
||||
|
||||
|
||||
@receiver(pre_save, sender=Asset)
|
||||
def pre_save_asset(sender, instance, **kwargs):
|
||||
"""Automatically fills in hidden members on database access"""
|
||||
asset_search = re.search("^([a-zA-Z0-9]*?[a-zA-Z]?)([0-9]+)$", instance.asset_id)
|
||||
if asset_search is None:
|
||||
instance.asset_id += "1"
|
||||
asset_search = re.search("^([a-zA-Z0-9]*?[a-zA-Z]?)([0-9]+)$", instance.asset_id)
|
||||
instance.asset_id_prefix = asset_search.group(1)
|
||||
instance.asset_id_number = int(asset_search.group(2))
|
||||
|
||||
92
assets/templates/asset_activity_table.html
Normal file
92
assets/templates/asset_activity_table.html
Normal file
@@ -0,0 +1,92 @@
|
||||
{% extends request.is_ajax|yesno:"base_ajax.html,base_assets.html" %}
|
||||
{% load static %}
|
||||
{% load paginator from filters %}
|
||||
{% load to_class_name from filters %}
|
||||
|
||||
{% block title %}Asset Activity Stream{% endblock %}
|
||||
|
||||
{# TODO: Find a way to reduce code duplication...can't just include the content because of the IDs... #}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static "js/tooltip.js" %}"></script>
|
||||
<script src="{% static "js/popover.js" %}"></script>
|
||||
<script src="{% static "js/moment.min.js" %}"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
$('[data-toggle="popover"]').popover().click(function(){
|
||||
if($(this).attr('href')){
|
||||
window.location.href = $(this).attr('href');
|
||||
}
|
||||
});
|
||||
|
||||
// This keeps timeago values correct, but uses an insane amount of resources
|
||||
// $(function () {
|
||||
// setInterval(function() {
|
||||
// $('.date').each(function (index, dateElem) {
|
||||
// var $dateElem = $(dateElem);
|
||||
// var formatted = moment($dateElem.attr('data-date')).fromNow();
|
||||
// $dateElem.text(formatted);
|
||||
// })
|
||||
// });
|
||||
// }, 10000);
|
||||
|
||||
|
||||
$('.date').each(function (index, dateElem) {
|
||||
var $dateElem = $(dateElem);
|
||||
var formatted = moment($dateElem.attr('data-date')).fromNow();
|
||||
$dateElem.text(formatted);
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-sm-12">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3>Asset Activity Stream</h3>
|
||||
</div>
|
||||
<div class="text-right col-sm-12">{% paginator %}</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Date</td>
|
||||
<td>Object</td>
|
||||
<td>Version ID</td>
|
||||
<td>User</td>
|
||||
<td>Changes</td>
|
||||
<td>Comment</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for version in object_list %}
|
||||
|
||||
<tr>
|
||||
<td>{{ version.revision.date_created }}</td>
|
||||
<td><a href="{{ version.changes.new.get_absolute_url }}">{{version.changes.new|to_class_name}} {{ version.changes.new.asset_id|default:version.changes.new.pk }}</a></td>
|
||||
<td>{{ version.pk }}|{{ version.revision.pk }}</td>
|
||||
<td>{{ version.revision.user.name }}</td>
|
||||
<td>
|
||||
{% if version.changes.old == None %}
|
||||
{{version.changes.new|to_class_name}} Created
|
||||
{% else %}
|
||||
{% include 'RIGS/version_changes.html' %}
|
||||
{% endif %} </td>
|
||||
<td>{{ version.changes.revision.comment }}</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div class="align-right">{% paginator %}</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -25,12 +25,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
{% if perms.asset.asset_financial %}
|
||||
{% if perms.assets.asset_finance %}
|
||||
<div class="col-md-6">
|
||||
{% include 'partials/purchasedetails_form.html' %}
|
||||
</div>
|
||||
{%endif%}
|
||||
<div class="col-md-6"
|
||||
<div class="col-md-6"
|
||||
{% if not object.is_cable %} hidden="true" {% endif %} id="cable-table">
|
||||
{% include 'partials/cable_form.html' %}
|
||||
</div>
|
||||
@@ -45,6 +45,16 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if not edit %}
|
||||
<div class="col-sm-12 text-right">
|
||||
<div>
|
||||
<a href="{% url 'asset_history' object.asset_id %}" title="View Revision History">
|
||||
Last edited at {{ object.last_edited_at|default:'never' }} by {{ object.last_edited_by.name|default:'nobody' }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js%}
|
||||
|
||||
68
assets/templates/asset_version_history.html
Normal file
68
assets/templates/asset_version_history.html
Normal file
@@ -0,0 +1,68 @@
|
||||
{% extends request.is_ajax|yesno:"base_ajax.html,base_assets.html" %}
|
||||
{% load to_class_name from filters %}
|
||||
{% load paginator from filters %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{{object|to_class_name}} {{ object.asset_id }} - Revision History{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static "js/tooltip.js" %}"></script>
|
||||
<script src="{% static "js/popover.js" %}"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
$('[data-toggle="popover"]').popover().click(function(){
|
||||
if($(this).attr('href')){
|
||||
window.location.href = $(this).attr('href');
|
||||
}
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-sm-12">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3><a href="{{ object.get_absolute_url }}">{{object|to_class_name}} {{ object.asset_id|default:object.pk }}</a> - Revision History</h3>
|
||||
</div>
|
||||
<div class="text-right col-sm-12">{% paginator %}</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Date</td>
|
||||
<td>Version ID</td>
|
||||
<td>User</td>
|
||||
<td>Changes</td>
|
||||
<td>Comment</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for version in object_list %}
|
||||
|
||||
<tr>
|
||||
<td>{{ version.revision.date_created }}</td>
|
||||
<td>{{ version.pk }}|{{ version.revision.pk }}</td>
|
||||
<td>{{ version.revision.user.name }}</td>
|
||||
<td>
|
||||
{% if version.changes.old is None %}
|
||||
{{object|to_class_name}} Created
|
||||
{% else %}
|
||||
{% include 'RIGS/version_changes.html' %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ version.revision.comment }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="align-right">{% paginator %}</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -20,7 +20,6 @@
|
||||
<td style="vertical-align: middle;">{{ item.category }}</td>
|
||||
<td style="vertical-align: middle;">{{ item.status }}</td>
|
||||
<td class="hidden-xs">
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<a type="button" class="btn btn-default btn-sm" href="{% url 'asset_detail' item.asset_id %}"><i class="glyphicon glyphicon-eye-open"></i> View</a>
|
||||
{% if perms.assets.change_asset %}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<td>{{ item.name }}</td>
|
||||
<td>
|
||||
<a href="{% url 'supplier_update' item.pk %}" class="btn btn-default"><i class="glyphicon glyphicon-edit"></i> Edit</a>
|
||||
<a href="{% url 'supplier_history' item.pk %}" class="btn btn-default"><i class="glyphicon glyphicon-time"></i> History</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from django.conf.urls import url
|
||||
from django.urls import path
|
||||
from assets import views
|
||||
from assets import views, models
|
||||
from RIGS import versioning
|
||||
|
||||
from PyRIGS.decorators import permission_required_with_403
|
||||
|
||||
@@ -7,16 +9,27 @@ urlpatterns = [
|
||||
path('', views.AssetList.as_view(), name='asset_index'),
|
||||
path('asset/list/', views.AssetList.as_view(), name='asset_list'),
|
||||
path('asset/id/<str:pk>/', views.AssetDetail.as_view(), name='asset_detail'),
|
||||
path('asset/create/', permission_required_with_403('assets.create_asset')(views.AssetCreate.as_view()), name='asset_create'),
|
||||
path('asset/id/<str:pk>/edit/', permission_required_with_403('assets.change_asset')(views.AssetEdit.as_view()), name='asset_update'),
|
||||
path('asset/id/<str:pk>/duplicate/', permission_required_with_403('assets.create_asset')(views.AssetDuplicate.as_view()), name='asset_duplicate'),
|
||||
path('asset/create/', permission_required_with_403('assets.add_asset')
|
||||
(views.AssetCreate.as_view()), name='asset_create'),
|
||||
path('asset/id/<str:pk>/edit/', permission_required_with_403('assets.change_asset')
|
||||
(views.AssetEdit.as_view()), name='asset_update'),
|
||||
path('asset/id/<str:pk>/duplicate/', permission_required_with_403('assets.add_asset')
|
||||
(views.AssetDuplicate.as_view()), name='asset_duplicate'),
|
||||
path('asset/id/<str:pk>/history/', views.AssetVersionHistory.as_view(),
|
||||
name='asset_history', kwargs={'model': models.Asset}),
|
||||
path('activity', permission_required_with_403('assets.view_asset')
|
||||
(views.ActivityTable.as_view()), name='asset_activity_table'),
|
||||
|
||||
path('asset/search/', views.AssetSearch.as_view(), name='asset_search_json'),
|
||||
|
||||
path('supplier/list', views.SupplierList.as_view(), name='supplier_list'),
|
||||
path('supplier/<int:pk>', views.SupplierDetail.as_view(), name='supplier_detail'),
|
||||
path('supplier/create', permission_required_with_403('assets.create_supplier')(views.SupplierCreate.as_view()), name='supplier_create'),
|
||||
path('supplier/<int:pk>/edit', permission_required_with_403('assets.edit_supplier')(views.SupplierUpdate.as_view()), name='supplier_update'),
|
||||
path('supplier/create', permission_required_with_403('assets.add_supplier')
|
||||
(views.SupplierCreate.as_view()), name='supplier_create'),
|
||||
path('supplier/<int:pk>/edit', permission_required_with_403('assets.change_supplier')
|
||||
(views.SupplierUpdate.as_view()), name='supplier_update'),
|
||||
path('supplier/<str:pk>/history/', views.SupplierVersionHistory.as_view(),
|
||||
name='supplier_history', kwargs={'model': models.Supplier}),
|
||||
|
||||
path('supplier/search/', views.SupplierSearch.as_view(), name='supplier_search_json'),
|
||||
]
|
||||
|
||||
@@ -5,7 +5,9 @@ from django.views.decorators.csrf import csrf_exempt
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.urls import reverse
|
||||
from django.db.models import Q
|
||||
from django.shortcuts import get_object_or_404
|
||||
from assets import models, forms
|
||||
from RIGS import versioning
|
||||
|
||||
|
||||
@method_decorator(csrf_exempt, name='dispatch')
|
||||
@@ -36,7 +38,8 @@ class AssetList(LoginRequiredMixin, generic.ListView):
|
||||
if len(query_string) == 0:
|
||||
queryset = self.model.objects.all()
|
||||
elif len(query_string) >= 3:
|
||||
queryset = self.model.objects.filter(Q(asset_id__exact=query_string) | Q(description__icontains=query_string))
|
||||
queryset = self.model.objects.filter(
|
||||
Q(asset_id__exact=query_string) | Q(description__icontains=query_string))
|
||||
else:
|
||||
queryset = self.model.objects.filter(Q(asset_id__exact=query_string))
|
||||
|
||||
@@ -46,7 +49,8 @@ class AssetList(LoginRequiredMixin, generic.ListView):
|
||||
if len(form.cleaned_data['status']) > 0:
|
||||
queryset = queryset.filter(status__in=form.cleaned_data['status'])
|
||||
elif self.hide_hidden_status:
|
||||
queryset = queryset.filter(status__in=models.AssetStatus.objects.filter(should_show=True))
|
||||
queryset = queryset.filter(
|
||||
status__in=models.AssetStatus.objects.filter(should_show=True))
|
||||
|
||||
return queryset
|
||||
|
||||
@@ -203,3 +207,24 @@ class SupplierUpdate(generic.UpdateView):
|
||||
model = models.Supplier
|
||||
form_class = forms.SupplierForm
|
||||
template_name = 'supplier_update.html'
|
||||
|
||||
|
||||
class SupplierVersionHistory(versioning.VersionHistory):
|
||||
template_name = "asset_version_history.html"
|
||||
|
||||
|
||||
# TODO: Reduce SQL queries
|
||||
class AssetVersionHistory(versioning.VersionHistory):
|
||||
def get_object(self, **kwargs):
|
||||
return get_object_or_404(models.Asset, asset_id=self.kwargs['pk'])
|
||||
|
||||
|
||||
class ActivityTable(versioning.ActivityTable):
|
||||
model = versioning.RIGSVersion
|
||||
template_name = "asset_activity_table.html"
|
||||
paginate_by = 25
|
||||
|
||||
def get_queryset(self):
|
||||
versions = versioning.RIGSVersion.objects.get_for_multiple_models(
|
||||
[models.Asset, models.Supplier])
|
||||
return versions
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block titleelements %}
|
||||
{% if perms.assets.view_asset%}
|
||||
{% if perms.assets.view_asset %}
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Assets<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
@@ -16,7 +16,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if perms.assets.view_supplier%}
|
||||
{% if perms.assets.view_supplier %}
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> Suppliers<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
@@ -28,4 +28,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if perms.assets.view_asset %}
|
||||
<li><a href="{% url 'asset_activity_table' %}">Recent Changes</a></li>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user