diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml
index 41aded15..84d49acd 100644
--- a/.github/workflows/django.yml
+++ b/.github/workflows/django.yml
@@ -12,6 +12,7 @@ jobs:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ PYTHONDONTWRITEBYTECODE: 1
steps:
- uses: actions/checkout@v3
- name: Set up Python
@@ -41,8 +42,8 @@ jobs:
pipenv run python3 manage.py makemigrations --check --dry-run
pipenv run python3 manage.py collectstatic --noinput
- name: Run Tests
- run: pipenv run pytest -n auto -vv --cov
- - uses: actions/upload-artifact@v2
+ run: pipenv run pytest -n auto --cov
+ - uses: actions/upload-artifact@v3
if: failure()
with:
name: failure-screenshots ${{ matrix.test-group }}
diff --git a/Pipfile b/Pipfile
index 2cbc2f2c..23fecb62 100644
--- a/Pipfile
+++ b/Pipfile
@@ -93,7 +93,7 @@ pytest = "*"
pytest-reverse = "*"
[requires]
-python_version = "3.9"
+python_version = "3.10"
[dev-packages.pytest-xdist]
extras = [ "psutil",]
diff --git a/Pipfile.lock b/Pipfile.lock
index e5d41286..ce535346 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,11 +1,11 @@
{
"_meta": {
"hash": {
- "sha256": "9865ac4d5b85c2b9461dcfe9391f319bce4416b009ced82b8f8fe2ea5b7d9d7a"
+ "sha256": "71377846d2282aa2f5352819eb31260cbbb04f41c2c3462b5c3ca2c8bc602b34"
},
"pipfile-spec": 6,
"requires": {
- "python_version": "3.9"
+ "python_version": "3.10"
},
"sources": [
{
@@ -263,7 +263,7 @@
"sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df",
"sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"
],
- "markers": "python_version >= '3.7'",
+ "markers": "python_full_version >= '3.7.0'",
"version": "==3.1.0"
},
"configparser": {
@@ -1006,11 +1006,11 @@
},
"sentry-sdk": {
"hashes": [
- "sha256:5932c092c6e6035584eb74d77064e4bce3b7935dfc4a331349719a40db265840",
- "sha256:cf89a5063ef84278d186aceaed6fb595bfe67d099298e537634a323664265669"
+ "sha256:0bbcecda9f51936904c1030e7fef0fe693e633888f02a14d1cb68646a50e83b3",
+ "sha256:56d6d9d194c898d853a7c1dd99bed92ce82334ee1282292c15bcc967ff1a49b5"
],
"index": "pypi",
- "version": "==1.22.2"
+ "version": "==1.24.0"
},
"setuptools": {
"hashes": [
@@ -1206,11 +1206,11 @@
},
"urllib3": {
"hashes": [
- "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305",
- "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"
+ "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f",
+ "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"
],
"index": "pypi",
- "version": "==1.26.15"
+ "version": "==1.26.16"
},
"webencodings": {
"hashes": [
@@ -1232,7 +1232,7 @@
"sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065",
"sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"
],
- "markers": "python_version >= '3.7'",
+ "markers": "python_full_version >= '3.7.0'",
"version": "==1.2.0"
},
"yolk": {
@@ -1552,7 +1552,7 @@
"sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df",
"sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"
],
- "markers": "python_version >= '3.7'",
+ "markers": "python_full_version >= '3.7.0'",
"version": "==3.1.0"
},
"coverage": {
@@ -1765,11 +1765,11 @@
},
"pytest-cov": {
"hashes": [
- "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b",
- "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"
+ "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6",
+ "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"
],
"index": "pypi",
- "version": "==4.0.0"
+ "version": "==4.1.0"
},
"pytest-django": {
"hashes": [
@@ -1800,11 +1800,11 @@
"psutil"
],
"hashes": [
- "sha256:1849bd98d8b242b948e472db7478e090bf3361912a8fed87992ed94085f54727",
- "sha256:37290d161638a20b672401deef1cba812d110ac27e35d213f091d15b8beb40c9"
+ "sha256:d5ee0520eb1b7bcca50a60a518ab7a7707992812c578198f8b44fdfac78e8c93",
+ "sha256:ff9daa7793569e6a68544850fd3927cd257cc03a7ef76c95e86915355e82b5f2"
],
"index": "pypi",
- "version": "==3.2.1"
+ "version": "==3.3.1"
},
"requests": {
"hashes": [
@@ -1878,18 +1878,18 @@
},
"urllib3": {
"hashes": [
- "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305",
- "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"
+ "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f",
+ "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"
],
"index": "pypi",
- "version": "==1.26.15"
+ "version": "==1.26.16"
},
"wsproto": {
"hashes": [
"sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065",
"sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"
],
- "markers": "python_version >= '3.7'",
+ "markers": "python_full_version >= '3.7.0'",
"version": "==1.2.0"
},
"zope.component": {
@@ -1900,6 +1900,22 @@
"index": "pypi",
"version": "==4.6.2"
},
+ "zope.deferredimport": {
+ "hashes": [
+ "sha256:57b2345e7b5eef47efcd4f634ff16c93e4265de3dcf325afc7315ade48d909e1",
+ "sha256:9a0c211df44aa95f1c4e6d2626f90b400f56989180d3ef96032d708da3d23e0a"
+ ],
+ "index": "pypi",
+ "version": "==4.3.1"
+ },
+ "zope.deprecation": {
+ "hashes": [
+ "sha256:0d453338f04bacf91bbfba545d8bcdf529aa829e67b705eac8c1a7fdce66e2df",
+ "sha256:f1480b74995958b24ce37b0ef04d3663d2683e5d6debc96726eff18acf4ea113"
+ ],
+ "index": "pypi",
+ "version": "==4.4.0"
+ },
"zope.event": {
"hashes": [
"sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42",
@@ -2011,6 +2027,52 @@
],
"index": "pypi",
"version": "==5.2.0"
+ },
+ "zope.proxy": {
+ "hashes": [
+ "sha256:00573dfa755d0703ab84bb23cb6ecf97bb683c34b340d4df76651f97b0bab068",
+ "sha256:092049280f2848d2ba1b57b71fe04881762a220a97b65288bcb0968bb199ec30",
+ "sha256:0cbd27b4d3718b5ec74fc65ffa53c78d34c65c6fd9411b8352d2a4f855220cf1",
+ "sha256:17fc7e16d0c81f833a138818a30f366696653d521febc8e892858041c4d88785",
+ "sha256:19577dfeb70e8a67249ba92c8ad20589a1a2d86a8d693647fa8385408a4c17b0",
+ "sha256:207aa914576b1181597a1516e1b90599dc690c095343ae281b0772e44945e6a4",
+ "sha256:219a7db5ed53e523eb4a4769f13105118b6d5b04ed169a283c9775af221e231f",
+ "sha256:2b50ea79849e46b5f4f2b0247a3687505d32d161eeb16a75f6f7e6cd81936e43",
+ "sha256:5903d38362b6c716e66bbe470f190579c530a5baf03dbc8500e5c2357aa569a5",
+ "sha256:5c24903675e271bd688c6e9e7df5775ac6b168feb87dbe0e4bcc90805f21b28f",
+ "sha256:5ef6bc5ed98139e084f4e91100f2b098a0cd3493d4e76f9d6b3f7b95d7ad0f06",
+ "sha256:61b55ae3c23a126a788b33ffb18f37d6668e79a05e756588d9e4d4be7246ab1c",
+ "sha256:63ddb992931a5e616c87d3d89f5a58db086e617548005c7f9059fac68c03a5cc",
+ "sha256:6943da9c09870490dcfd50c4909c0cc19f434fa6948f61282dc9cb07bcf08160",
+ "sha256:6ad40f85c1207803d581d5d75e9ea25327cd524925699a83dfc03bf8e4ba72b7",
+ "sha256:6b44433a79bdd7af0e3337bd7bbcf53dd1f9b0fa66bf21bcb756060ce32a96c1",
+ "sha256:6bbaa245015d933a4172395baad7874373f162955d73612f0b66b6c2c33b6366",
+ "sha256:7007227f4ea85b40a2f5e5a244479f6a6dfcf906db9b55e812a814a8f0e2c28d",
+ "sha256:74884a0aec1f1609190ec8b34b5d58fb3b5353cf22b96161e13e0e835f13518f",
+ "sha256:7d25fe5571ddb16369054f54cdd883f23de9941476d97f2b92eb6d7d83afe22d",
+ "sha256:7e162bdc5e3baad26b2262240be7d2bab36991d85a6a556e48b9dfb402370261",
+ "sha256:814d62678dc3a30f4aa081982d830b7c342cf230ffc9d030b020cb154eeebf9e",
+ "sha256:8878a34c5313ee52e20aa50b03138af8d472bae465710fb954d133a9bfd3c38d",
+ "sha256:a66a0d94e5b081d5d695e66d6667e91e74d79e273eee95c1747717ba9cb70792",
+ "sha256:a69f5cbf4addcfdf03dda564a671040127a6b7c34cf9fe4973582e68441b63fa",
+ "sha256:b00f9f0c334d07709d3f73a7cb8ae63c6ca1a90c790a63b5e7effa666ef96021",
+ "sha256:b6ed71e4a7b4690447b626f499d978aa13197a0e592950e5d7020308f6054698",
+ "sha256:bdf5041e5851526e885af579d2f455348dba68d74f14a32781933569a327fddf",
+ "sha256:be034360dd34e62608419f86e799c97d389c10a0e677a25f236a971b2f40dac9",
+ "sha256:cc8f590a5eed30b314ae6b0232d925519ade433f663de79cc3783e4b10d662ba",
+ "sha256:cd7a318a15fe6cc4584bf3c4426f092ed08c0fd012cf2a9173114234fe193e11",
+ "sha256:cf19b5f63a59c20306e034e691402b02055c8f4e38bf6792c23cad489162a642",
+ "sha256:cfc781ce442ec407c841e9aa51d0e1024f72b6ec34caa8fdb6ef9576d549acf2",
+ "sha256:dea9f6f8633571e18bc20cad83603072e697103a567f4b0738d52dd0211b4527",
+ "sha256:e4a86a1d5eb2cce83c5972b3930c7c1eac81ab3508464345e2b8e54f119d5505",
+ "sha256:e7106374d4a74ed9ff00c46cc00f0a9f06a0775f8868e423f85d4464d2333679",
+ "sha256:e98a8a585b5668aa9e34d10f7785abf9545fe72663b4bfc16c99a115185ae6a5",
+ "sha256:f64840e68483316eb58d82c376ad3585ca995e69e33b230436de0cdddf7363f9",
+ "sha256:f8f4b0a9e6683e43889852130595c8854d8ae237f2324a053cdd884de936aa9b",
+ "sha256:fc45a53219ed30a7f670a6d8c98527af0020e6fd4ee4c0a8fb59f147f06d816c"
+ ],
+ "index": "pypi",
+ "version": "==4.3.5"
}
}
}
diff --git a/PyRIGS/settings.py b/PyRIGS/settings.py
index 7f371f3d..54a3d228 100644
--- a/PyRIGS/settings.py
+++ b/PyRIGS/settings.py
@@ -218,8 +218,6 @@ TIME_ZONE = 'Europe/London'
FORMAT_MODULE_PATH = 'PyRIGS.formats'
-USE_I18N = True
-
USE_L10N = True
USE_TZ = True
@@ -264,3 +262,10 @@ TERMS_OF_HIRE_URL = "http://www.nottinghamtec.co.uk/terms.pdf"
AUTHORISATION_NOTIFICATION_ADDRESS = 'productions@nottinghamtec.co.uk'
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
+
+SECURE_HSTS_SECONDS = 3600
+SECURE_HSTS_INCLUDE_SUBDOMAINS = True
+SECURE_CONTENT_TYPE_NOSNIFF = True
+SESSION_COOKIE_SECURE = env('SESSION_COOKIE_SECURE_ENABLED', True)
+CSRF_COOKIE_SECURE = env('CSRF_COOKIE_SECURE_ENABLED', True)
+SECURE_HSTS_PRELOAD = True
diff --git a/PyRIGS/tests/base.py b/PyRIGS/tests/base.py
index d1669d5e..bcf1824c 100644
--- a/PyRIGS/tests/base.py
+++ b/PyRIGS/tests/base.py
@@ -63,7 +63,7 @@ def screenshot_failure(func):
if not pathlib.Path("screenshots").is_dir():
os.mkdir("screenshots")
self.driver.save_screenshot(screenshot_file)
- print("Error in test {} is at path {}".format(screenshot_name, screenshot_file), file=sys.stderr)
+ print(f"Error in test {screenshot_name} is at path {screenshot_file}", file=sys.stderr)
raise e
return wrapper_func
diff --git a/PyRIGS/tests/test_unit.py b/PyRIGS/tests/test_unit.py
index 3ab38567..12207d7d 100644
--- a/PyRIGS/tests/test_unit.py
+++ b/PyRIGS/tests/test_unit.py
@@ -59,8 +59,8 @@ class TestSampleDataGenerator(TestCase):
assert Asset.objects.all().count() > 50
assert Event.objects.all().count() > 100
call_command('deleteSampleData')
- assert Asset.objects.all().count() == 0
- assert Event.objects.all().count() == 0
+ assert not Asset.objects.all().exists()
+ assert not Event.objects.all().exists()
@override_settings(DEBUG=True)
@@ -76,9 +76,9 @@ def test_unauthenticated(client): # Nothing should be available to the unauthen
assertTemplateUsed(response, 'login_redirect.html')
else:
if "embed" in str(url):
- expected_url = "{0}?next={1}".format(reverse('login_embed'), request_url)
+ expected_url = f"{reverse('login_embed')}?next={request_url}"
else:
- expected_url = "{0}?next={1}".format(reverse('login'), request_url)
+ expected_url = f"{reverse('login')}?next={request_url}"
assertRedirects(response, expected_url)
call_command('deleteSampleData')
diff --git a/PyRIGS/views.py b/PyRIGS/views.py
index 372e1af0..c34f014e 100644
--- a/PyRIGS/views.py
+++ b/PyRIGS/views.py
@@ -48,7 +48,7 @@ class Index(generic.TemplateView): # Displays the current rig count along with
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['rig_count'] = models.Event.objects.rig_count()
- context['now'] = models.Event.objects.events_in_bounds(timezone.now(), timezone.now())
+ context['now'] = models.Event.objects.events_in_bounds(timezone.now(), timezone.now()).exclude(dry_hire=True).exclude(status=models.Event.CANCELLED)
return context
@@ -135,10 +135,11 @@ class SecureAPIRequest(generic.View):
query = reduce(operator.and_, queries)
objects = self.models[model].objects.filter(query)
for o in objects:
+ name = o.display_name if hasattr(o, 'display_name') else o.name
data = {
'pk': o.pk,
'value': o.pk,
- 'text': o.name,
+ 'text': name,
}
try: # See if there is a valid update URL
data['update'] = reverse(f"{model}_update", kwargs={'pk': o.pk})
@@ -183,7 +184,7 @@ class ModalURLMixin:
url = reverse_lazy('closemodal')
update_url = str(reverse_lazy(update, kwargs={'pk': self.object.pk}))
messages.info(self.request, "modalobject=" + serializers.serialize("json", [self.object]))
- messages.info(self.request, "modalobject[0]['update_url']='" + update_url + "'")
+ messages.info(self.request, f"modalobject[0]['update_url']='{update_url}'")
else:
url = reverse_lazy(detail, kwargs={
'pk': self.object.pk,
diff --git a/README.md b/README.md
index cd6a443c..b54c9c95 100644
--- a/README.md
+++ b/README.md
@@ -11,8 +11,9 @@ For setup information and other such helpful stuff check the [Wiki](https://gith
- PyRIGS: Base app, stores 'global' information
- RIGS: Rigboard stuff - event calendar etc
- assets: Database of our kit, testing data etc
+- training: Logs in-house training within various "departments" (sound, lighting etc).
- versioning: Our custom logic built on top of django-reversion. Semi-modular.
- users: Our custom logic for registration and profiles. Semi-modular.
-- training: SoonTM
+
[](https://forthebadge.com) [](https://forthebadge.com)
diff --git a/RIGS/forms.py b/RIGS/forms.py
index c5e5de66..9a5f60b6 100644
--- a/RIGS/forms.py
+++ b/RIGS/forms.py
@@ -131,7 +131,7 @@ class BaseClientEventAuthorisationForm(forms.ModelForm):
def clean(self):
if self.cleaned_data.get('amount') != self.instance.event.total:
self.add_error('amount', 'The amount authorised must equal the total for the event (inc VAT).')
- return super(BaseClientEventAuthorisationForm, self).clean()
+ return super().clean()
class Meta:
abstract = True
@@ -179,7 +179,7 @@ class EventRiskAssessmentForm(forms.ModelForm):
unexpected_values.append(f"
{self._meta.model._meta.get_field(field).help_text}")
if len(unexpected_values) > 0 and not self.cleaned_data.get('supervisor_consulted'):
raise forms.ValidationError(f"Your answers to these questions: {''.join([str(elem) for elem in unexpected_values])}
require consulting with a supervisor.", code='unusual_answers')
- return super(EventRiskAssessmentForm, self).clean()
+ return super().clean()
class Meta:
model = models.RiskAssessment
@@ -195,8 +195,6 @@ class EventChecklistForm(forms.ModelForm):
if field.__class__ == forms.NullBooleanField:
# Only display yes/no to user, the 'none' is only ever set in the background
field.widget = forms.CheckboxInput()
- # Parsed from incoming form data by clean, then saved into models when the form is saved
- items = {}
related_models = {
'venue': models.Venue,
@@ -216,6 +214,11 @@ class PowerTestRecordForm(forms.ModelForm):
# Only display yes/no to user, the 'none' is only ever set in the background
field.widget = forms.CheckboxInput()
+ related_models = {
+ 'venue': models.Venue,
+ 'power_mic': models.Profile,
+ }
+
class Meta:
model = models.PowerTestRecord
fields = '__all__'
diff --git a/RIGS/migrations/0049_auto_20230529_1123.py b/RIGS/migrations/0049_auto_20230529_1123.py
new file mode 100644
index 00000000..9b3fdcda
--- /dev/null
+++ b/RIGS/migrations/0049_auto_20230529_1123.py
@@ -0,0 +1,53 @@
+# Generated by Django 3.2.19 on 2023-05-29 10:23
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('RIGS', '0048_auto_20230518_1256'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='powertestrecord',
+ name='fd_earth_fault',
+ field=models.DecimalField(blank=True, decimal_places=2, help_text='Earth Fault Loop Impedance (ZS) / Ω', max_digits=6, null=True, verbose_name='Earth Fault Loop Impedance'),
+ ),
+ migrations.AlterField(
+ model_name='powertestrecord',
+ name='fd_pssc',
+ field=models.IntegerField(blank=True, help_text='Prospective Short Circuit Current / A', null=True, verbose_name='PSCC'),
+ ),
+ migrations.AlterField(
+ model_name='powertestrecord',
+ name='w1_earth_fault',
+ field=models.DecimalField(blank=True, decimal_places=2, help_text='Earth Fault Loop Impedance (ZS) / Ω', max_digits=6, null=True, verbose_name='Earth Fault Loop Impedance'),
+ ),
+ migrations.AlterField(
+ model_name='powertestrecord',
+ name='w1_voltage',
+ field=models.IntegerField(blank=True, help_text='Voltage / V', null=True),
+ ),
+ migrations.AlterField(
+ model_name='powertestrecord',
+ name='w2_earth_fault',
+ field=models.DecimalField(blank=True, decimal_places=2, help_text='Earth Fault Loop Impedance (ZS) / Ω', max_digits=6, null=True, verbose_name='Earth Fault Loop Impedance'),
+ ),
+ migrations.AlterField(
+ model_name='powertestrecord',
+ name='w2_voltage',
+ field=models.IntegerField(blank=True, help_text='Voltage / V', null=True),
+ ),
+ migrations.AlterField(
+ model_name='powertestrecord',
+ name='w3_earth_fault',
+ field=models.DecimalField(blank=True, decimal_places=2, help_text='Earth Fault Loop Impedance (ZS) / Ω', max_digits=6, null=True, verbose_name='Earth Fault Loop Impedance'),
+ ),
+ migrations.AlterField(
+ model_name='powertestrecord',
+ name='w3_voltage',
+ field=models.IntegerField(blank=True, help_text='Voltage / V', null=True),
+ ),
+ ]
diff --git a/RIGS/models.py b/RIGS/models.py
index 550b4df5..ea18e95e 100644
--- a/RIGS/models.py
+++ b/RIGS/models.py
@@ -497,7 +497,7 @@ class Event(models.Model, RevisionMixin):
earliest = datetime.datetime.combine(self.start_date, datetime.time(00, 00))
tz = pytz.timezone(settings.TIME_ZONE)
earliest = tz.localize(earliest)
- return not self.dry_hire and earliest <= timezone.now()
+ return not self.dry_hire and not self.status == Event.CANCELLED and earliest <= timezone.now()
objects = EventManager()
@@ -875,6 +875,9 @@ class EventChecklist(ReviewableModel, RevisionMixin):
@reversion.register
class PowerTestRecord(ReviewableModel, RevisionMixin):
+ earth_fault_text = "Earth Fault Loop Impedance (ZS) / Ω"
+ pssc_text = "Prospective Short Circuit Current / A"
+
event = models.ForeignKey('Event', related_name='power_tests', on_delete=models.CASCADE)
power_mic = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name='checklists',
verbose_name="Power MIC", on_delete=models.CASCADE, help_text="Who is the Power MIC?")
@@ -896,21 +899,21 @@ class PowerTestRecord(ReviewableModel, RevisionMixin):
fd_voltage_l2 = models.IntegerField(blank=True, null=True, verbose_name="First Distro Voltage L2-N", help_text="L2 - N")
fd_voltage_l3 = models.IntegerField(blank=True, null=True, verbose_name="First Distro Voltage L3-N", help_text="L3 - N")
fd_phase_rotation = models.BooleanField(blank=True, null=True, verbose_name="Phase Rotation", help_text="Phase Rotation
(if required)")
- fd_earth_fault = models.DecimalField(blank=True, null=True, max_digits=5, decimal_places=2, verbose_name="Earth Fault Loop Impedance", help_text="Earth Fault Loop Impedance (ZS)")
- fd_pssc = models.IntegerField(blank=True, null=True, verbose_name="PSCC", help_text="Prospective Short Circuit Current")
+ fd_earth_fault = models.DecimalField(blank=True, null=True, max_digits=6, decimal_places=2, verbose_name="Earth Fault Loop Impedance", help_text=earth_fault_text)
+ fd_pssc = models.IntegerField(blank=True, null=True, verbose_name="PSCC", help_text=pssc_text)
# Worst case points
w1_description = models.CharField(blank=True, default='', max_length=255, help_text="Description")
w1_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?")
- w1_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage")
- w1_earth_fault = models.DecimalField(blank=True, null=True, max_digits=5, decimal_places=2, verbose_name="Earth Fault Loop Impedance", help_text="Earth Fault Loop Impedance (ZS)")
+ w1_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage / V")
+ w1_earth_fault = models.DecimalField(blank=True, null=True, max_digits=6, decimal_places=2, verbose_name="Earth Fault Loop Impedance", help_text=earth_fault_text)
w2_description = models.CharField(blank=True, default='', max_length=255, help_text="Description")
w2_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?")
- w2_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage")
- w2_earth_fault = models.DecimalField(blank=True, null=True, max_digits=5, decimal_places=2, verbose_name="Earth Fault Loop Impedance", help_text="Earth Fault Loop Impedance (ZS)")
+ w2_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage / V")
+ w2_earth_fault = models.DecimalField(blank=True, null=True, max_digits=6, decimal_places=2, verbose_name="Earth Fault Loop Impedance", help_text=earth_fault_text)
w3_description = models.CharField(blank=True, default='', max_length=255, help_text="Description")
w3_polarity = models.BooleanField(blank=True, null=True, help_text="Polarity Checked?")
- w3_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage")
- w3_earth_fault = models.DecimalField(blank=True, null=True, max_digits=5, decimal_places=2, verbose_name="Earth Fault Loop Impedance", help_text="Earth Fault Loop Impedance (ZS)")
+ w3_voltage = models.IntegerField(blank=True, null=True, help_text="Voltage / V")
+ w3_earth_fault = models.DecimalField(blank=True, null=True, max_digits=6, decimal_places=2, verbose_name="Earth Fault Loop Impedance", help_text=earth_fault_text)
all_rcds_tested = models.BooleanField(blank=True, null=True, help_text="All circuit RCDs tested?
(using test button)")
public_sockets_tested = models.BooleanField(blank=True, null=True, help_text="Public/Performer accessible circuits tested?
(using socket tester)")
@@ -924,6 +927,9 @@ class PowerTestRecord(ReviewableModel, RevisionMixin):
def __str__(self):
return f"{self.pk} - {self.event}"
+ def get_absolute_url(self):
+ return reverse('pt_detail', kwargs={'pk': self.pk})
+
@property
def activity_feed_string(self):
return str(self.event)
diff --git a/RIGS/templates/event_form.html b/RIGS/templates/event_form.html
index afa8d5b7..108ed4e5 100644
--- a/RIGS/templates/event_form.html
+++ b/RIGS/templates/event_form.html
@@ -209,7 +209,7 @@
diff --git a/RIGS/templates/hs/event_checklist_detail.html b/RIGS/templates/hs/event_checklist_detail.html
index 705e0209..82e20020 100644
--- a/RIGS/templates/hs/event_checklist_detail.html
+++ b/RIGS/templates/hs/event_checklist_detail.html
@@ -9,6 +9,8 @@
{% button 'edit' url='ec_edit' pk=object.pk %}
{% button 'view' url='event_detail' pk=object.event.pk text="Event" %}
+
Create Power Test
{% include 'partials/review_status.html' with perm=perms.RIGS.review_eventchecklist review='ec_review' %}
@@ -71,6 +73,8 @@
{% button 'edit' url='ec_edit' pk=object.pk %}
{% button 'view' url='event_detail' pk=object.pk text="Event" %}
+
Create Power Test
{% include 'partials/review_status.html' with perm=perms.RIGS.review_eventchecklist review='ec_review' %}
diff --git a/RIGS/templates/hs/event_checklist_form.html b/RIGS/templates/hs/event_checklist_form.html
index ea8183a1..373ad306 100644
--- a/RIGS/templates/hs/event_checklist_form.html
+++ b/RIGS/templates/hs/event_checklist_form.html
@@ -24,7 +24,7 @@
{% block content %}
{% include 'form_errors.html' %}
-
+
diff --git a/RIGS/templates/hs/power_detail.html b/RIGS/templates/hs/power_detail.html
index d8253248..958a1d25 100644
--- a/RIGS/templates/hs/power_detail.html
+++ b/RIGS/templates/hs/power_detail.html
@@ -86,7 +86,7 @@
- Voltage (cube meter) |
+ Voltage (cube meter) / V |
{{ object|help_text:'fd_voltage_l1' }} |
{{ object|help_text:'fd_voltage_l2' }} |
{{ object|help_text:'fd_voltage_l3' }} |
diff --git a/RIGS/templates/hs/power_form.html b/RIGS/templates/hs/power_form.html
index 315175b7..d77ead1b 100644
--- a/RIGS/templates/hs/power_form.html
+++ b/RIGS/templates/hs/power_form.html
@@ -51,22 +51,18 @@
-
-
+
{% if venue %}
- {% elif event.venue %}
-
{% endif %}
@@ -119,7 +115,7 @@
- Voltage (cube meter) |
+ Voltage (cube meter) / V |
{{ form.fd_voltage_l1.help_text }} |
{{ form.fd_voltage_l2.help_text }} |
{{ form.fd_voltage_l3.help_text }} |
diff --git a/RIGS/templates/hs/risk_assessment_form.html b/RIGS/templates/hs/risk_assessment_form.html
index 28184cd3..0fcef1be 100644
--- a/RIGS/templates/hs/risk_assessment_form.html
+++ b/RIGS/templates/hs/risk_assessment_form.html
@@ -25,7 +25,7 @@
});
$('input[type=radio][name=outside], input[type=radio][name=generators], input[type=radio][name=other_companies_power], input[type=radio][name=nonstandard_equipment_power], input[type=radio][name=multiple_electrical_environments]').change(function() {
$('#{{ form.power_notes.id_for_label }}').prop('required', parseBool(this.value));
- $('#{{ form.power_plan.id_for_label }}').prop('required', parseBool(this.value));
+ //$('#{{ form.power_plan.id_for_label }}').prop('required', parseBool(this.value));
});
$('input[type=radio][name=special_structures]').change(function() {
$('#{{ form.persons_responsible_structures.id_for_label }}').prop('hidden', !parseBool(this.value)).prop('required', parseBool(this.value));
diff --git a/RIGS/templates/partials/event_status.html b/RIGS/templates/partials/event_status.html
index e4f1ad53..7c521de1 100644
--- a/RIGS/templates/partials/event_status.html
+++ b/RIGS/templates/partials/event_status.html
@@ -15,7 +15,7 @@
{% endif %}
{% endif %}
{% if not event.dry_hire %}
- {% if event.has_checklist %}
+ {% if event.riskassessment %}
RA:
{% else %}
RA:
diff --git a/RIGS/templatetags/filters.py b/RIGS/templatetags/filters.py
index b2480d40..73a8c148 100644
--- a/RIGS/templatetags/filters.py
+++ b/RIGS/templatetags/filters.py
@@ -171,7 +171,7 @@ def title_spaced(string):
@register.filter(needs_autoescape=True)
def namewithnotes(obj, url, autoescape=True):
if hasattr(obj, 'notes') and obj.notes is not None and len(obj.notes) > 0:
- return mark_safe(obj.name + " ".format(reverse(url, kwargs={'pk': obj.pk})))
+ return mark_safe(obj.name + f" ")
else:
return obj.name
@@ -183,7 +183,7 @@ def linkornone(target, namespace=None, autoescape=True):
link = namespace + "://" + target
else:
link = target
- return mark_safe("{}".format(link, str(target)))
+ return mark_safe(f"{target}")
else:
return "None"
diff --git a/RIGS/tests/pages.py b/RIGS/tests/pages.py
index 7745c0c1..a2765830 100644
--- a/RIGS/tests/pages.py
+++ b/RIGS/tests/pages.py
@@ -114,7 +114,7 @@ class CreateEvent(FormPage):
}
def select_event_type(self, type_name):
- self.find_element(By.XPATH, '//button[.="{}"]'.format(type_name)).click()
+ self.find_element(By.XPATH, f'//button[.="{type_name}"]').click()
def item_row(self, ID):
return rigs_regions.ItemRow(self, self.find_element(By.ID, "item-" + ID))
diff --git a/RIGS/tests/test_unit.py b/RIGS/tests/test_unit.py
index 3c038e46..2426a59a 100644
--- a/RIGS/tests/test_unit.py
+++ b/RIGS/tests/test_unit.py
@@ -259,7 +259,7 @@ class TestPrintPaperwork(TestCase):
def test_login_redirect(client, django_user_model):
request_url = reverse('event_embed', kwargs={'pk': 1})
- expected_url = "{0}?next={1}".format(reverse('login_embed'), request_url)
+ expected_url = f"{reverse('login_embed')}?next={request_url}"
# Request the page and check it redirects
response = client.get(request_url, follow=True)
@@ -372,7 +372,8 @@ def test_ra_redirect(admin_client, admin_user, ra):
class TestMarkdownTemplateTags(TestCase):
- markdown = open(os.path.join(settings.BASE_DIR, "RIGS/tests/sample.md")).read()
+ with open(os.path.join(settings.BASE_DIR, "RIGS/tests/sample.md"), encoding="utf-8") as f:
+ markdown = f.read()
def test_html_safe(self):
html = markdown_filter(self.markdown)
diff --git a/RIGS/views/hs.py b/RIGS/views/hs.py
index a2ac9786..a4a53cb6 100644
--- a/RIGS/views/hs.py
+++ b/RIGS/views/hs.py
@@ -13,31 +13,24 @@ from django.shortcuts import redirect
class HSCreateView(generic.CreateView):
- def get_form(self, **kwargs):
- form = super().get_form(**kwargs)
- epk = self.kwargs.get('pk')
- event = models.Event.objects.get(pk=epk)
- form.instance.event = event
- return form
-
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
- epk = self.kwargs.get('pk')
- event = models.Event.objects.get(pk=epk)
+ event = models.Event.objects.get(pk=self.kwargs.get('pk'))
context['event'] = event
context['page_title'] = f'Create {self.model.__name__} for Event {event.display_id}'
+ get_related(context['form'], context)
return context
-class MarkReviewed(generic.View):
- def get(self, *args, **kwargs):
+class MarkReviewed(generic.RedirectView):
+ def get_redirect_url(self, *args, **kwargs):
obj = apps.get_model('RIGS', kwargs.get('model')).objects.get(pk=kwargs.get('pk'))
with reversion.create_revision():
reversion.set_user(self.request.user)
obj.reviewed_by = self.request.user
obj.reviewed_at = timezone.now()
obj.save()
- return HttpResponseRedirect(reverse('hs_list'))
+ return self.request.META.get('HTTP_REFERER', reverse('hs_list'))
class EventRiskAssessmentCreate(HSCreateView):
@@ -55,11 +48,17 @@ class EventRiskAssessmentCreate(HSCreateView):
if ra is not None:
return HttpResponseRedirect(reverse('ra_edit', kwargs={'pk': ra.pk}))
- return super(EventRiskAssessmentCreate, self).get(self)
+ return super().get(self)
def get_success_url(self):
return reverse('ra_detail', kwargs={'pk': self.object.pk})
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ if context['event'].mic:
+ context['power_mic'] = context['event'].mic
+ return context
+
class EventRiskAssessmentEdit(generic.UpdateView):
model = models.RiskAssessment
@@ -74,7 +73,7 @@ class EventRiskAssessmentEdit(generic.UpdateView):
return reverse('ra_detail', kwargs={'pk': self.object.pk})
def get_context_data(self, **kwargs):
- context = super(EventRiskAssessmentEdit, self).get_context_data(**kwargs)
+ context = super().get_context_data(**kwargs)
rpk = self.kwargs.get('pk')
ra = models.RiskAssessment.objects.get(pk=rpk)
context['event'] = ra.event
@@ -89,7 +88,7 @@ class EventRiskAssessmentDetail(generic.DetailView):
template_name = 'hs/risk_assessment_detail.html'
def get_context_data(self, **kwargs):
- context = super(EventRiskAssessmentDetail, self).get_context_data(**kwargs)
+ context = super().get_context_data(**kwargs)
context['page_title'] = f"Risk Assessment for Event {self.object.event.display_id} {self.object.event.name}"
return context
@@ -99,7 +98,7 @@ class EventChecklistDetail(generic.DetailView):
template_name = 'hs/event_checklist_detail.html'
def get_context_data(self, **kwargs):
- context = super(EventChecklistDetail, self).get_context_data(**kwargs)
+ context = super().get_context_data(**kwargs)
context['page_title'] = f"Event Checklist for Event {self.object.event.display_id} {self.object.event.name}"
return context
@@ -117,7 +116,7 @@ class EventChecklistEdit(generic.UpdateView):
return reverse('ec_detail', kwargs={'pk': self.object.pk})
def get_context_data(self, **kwargs):
- context = super(EventChecklistEdit, self).get_context_data(**kwargs)
+ context = super().get_context_data(**kwargs)
pk = self.kwargs.get('pk')
ec = models.EventChecklist.objects.get(pk=pk)
context['event'] = ec.event
@@ -136,19 +135,22 @@ class EventChecklistCreate(HSCreateView):
def get(self, *args, **kwargs):
epk = kwargs.get('pk')
event = models.Event.objects.get(pk=epk)
-
# Check if RA exists
ra = models.RiskAssessment.objects.filter(event=event).first()
-
if ra is None:
messages.error(self.request, f'A Risk Assessment must exist prior to creating any Event Checklists for {event}! Please create one now.')
return HttpResponseRedirect(reverse('event_ra', kwargs={'pk': epk}))
-
- return super(EventChecklistCreate, self).get(self)
+ return super().get(self)
def get_success_url(self):
return reverse('ec_detail', kwargs={'pk': self.object.pk})
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ if context['event'].venue:
+ context['venue'] = context['event'].venue
+ return context
+
class PowerTestDetail(generic.DetailView):
model = models.PowerTestRecord
@@ -179,7 +181,7 @@ class PowerTestEdit(generic.UpdateView):
context['event'] = ec.event
context['edit'] = True
context['page_title'] = f'Edit Power Test Record for Event {ec.event.display_id}'
- # get_related(context['form'], context)
+ get_related(context['form'], context)
return context
@@ -191,7 +193,6 @@ class PowerTestCreate(HSCreateView):
def get(self, *args, **kwargs):
epk = kwargs.get('pk')
event = models.Event.objects.get(pk=epk)
-
# Check if RA exists
ra = models.RiskAssessment.objects.filter(event=event).first()
@@ -204,6 +205,14 @@ class PowerTestCreate(HSCreateView):
def get_success_url(self):
return reverse('pt_detail', kwargs={'pk': self.object.pk})
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ if context['event'].venue:
+ context['venue'] = context['event'].venue
+ if context['event'].riskassessment.power_mic:
+ context['power_mic'] = context['event'].riskassessment.power_mic
+ return context
+
class HSList(generic.ListView):
paginate_by = 20
@@ -211,10 +220,10 @@ class HSList(generic.ListView):
template_name = 'hs/hs_list.html'
def get_queryset(self):
- return models.Event.objects.all().exclude(status=models.Event.CANCELLED).order_by('-start_date').select_related('riskassessment').prefetch_related('checklists')
+ return models.Event.objects.all().exclude(status=models.Event.CANCELLED).exclude(dry_hire=True).order_by('-start_date').select_related('riskassessment').prefetch_related('checklists')
def get_context_data(self, **kwargs):
- context = super(HSList, self).get_context_data(**kwargs)
+ context = super().get_context_data(**kwargs)
context['page_title'] = 'H&S Overview'
return context
diff --git a/assets/migrations/0028_alter_asset_length.py b/assets/migrations/0028_alter_asset_length.py
new file mode 100644
index 00000000..78fadbdf
--- /dev/null
+++ b/assets/migrations/0028_alter_asset_length.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.19 on 2023-05-24 22:03
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('assets', '0027_asset_nickname'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='asset',
+ name='length',
+ field=models.DecimalField(blank=True, decimal_places=2, help_text='m', max_digits=10, null=True),
+ ),
+ ]
diff --git a/assets/models.py b/assets/models.py
index 32331029..3d8f70c8 100644
--- a/assets/models.py
+++ b/assets/models.py
@@ -135,7 +135,7 @@ class Asset(models.Model, RevisionMixin):
# Cable assets
is_cable = models.BooleanField(default=False)
cable_type = models.ForeignKey(to=CableType, blank=True, null=True, on_delete=models.SET_NULL)
- length = models.DecimalField(decimal_places=1, max_digits=10,
+ length = models.DecimalField(decimal_places=2, 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²')
@@ -192,5 +192,5 @@ class Asset(models.Model, RevisionMixin):
return str(self.asset_id)
@property
- def name(self):
+ def display_name(self):
return f"{self.display_id} | {self.description}"
diff --git a/assets/templates/asset_audit_list.html b/assets/templates/asset_audit_list.html
index 057d2dae..73711dbb 100644
--- a/assets/templates/asset_audit_list.html
+++ b/assets/templates/asset_audit_list.html
@@ -35,6 +35,11 @@
function onAuditClick(assetID) {
$('#' + assetID).remove();
}
+ $('#modal').on('hidden.bs.modal', function (e) {
+ searchbar = document.getElementById('id_q');
+ searchbar.value = "";
+ setTimeout(searchbar.focus(), 2000);
+ })
{% endblock %}
diff --git a/assets/templates/asset_form.html b/assets/templates/asset_form.html
index 7496875b..af61c8e4 100644
--- a/assets/templates/asset_form.html
+++ b/assets/templates/asset_form.html
@@ -12,7 +12,6 @@
{{ block.super }}
-
{% endblock %}
{% block js %}
@@ -35,9 +34,10 @@
$(document).find(".selectpicker").selectpicker().each(function(){initPicker($(this))});
});
+
{% endblock %}
diff --git a/assets/templates/partials/asset_list_table.html b/assets/templates/partials/asset_list_table.html
index d5963b00..e5136eb4 100644
--- a/assets/templates/partials/asset_list_table.html
+++ b/assets/templates/partials/asset_list_table.html
@@ -12,7 +12,7 @@
{% for item in object_list %}
-
+
| {{ item.asset_id }} |
{{ item.description }} |
{{ item.category }} |
diff --git a/assets/templates/partials/purchasedetails_form.html b/assets/templates/partials/purchasedetails_form.html
index 9fa226b9..dc627fc9 100644
--- a/assets/templates/partials/purchasedetails_form.html
+++ b/assets/templates/partials/purchasedetails_form.html
@@ -34,7 +34,7 @@
@@ -42,7 +42,7 @@
diff --git a/assets/tests/pages.py b/assets/tests/pages.py
index a9815f31..9f5afa32 100644
--- a/assets/tests/pages.py
+++ b/assets/tests/pages.py
@@ -77,7 +77,7 @@ class AssetForm(FormPage):
'description': (regions.TextBox, (By.ID, 'id_description')),
'is_cable': (regions.CheckBox, (By.ID, 'id_is_cable')),
'serial_number': (regions.TextBox, (By.ID, 'id_serial_number')),
- 'comments': (regions.SimpleMDETextArea, (By.ID, 'id_comments')),
+ 'comments': (regions.TextBox, (By.ID, 'id_comments')),
'purchase_price': (regions.TextBox, (By.ID, 'id_purchase_price')),
'replacement_cost': (regions.TextBox, (By.ID, 'id_replacement_cost')),
'date_acquired': (regions.DatePicker, (By.ID, 'id_date_acquired')),
diff --git a/package-lock.json b/package-lock.json
index 9180f996..0a2350ee 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,6 +5,7 @@
"requires": true,
"packages": {
"": {
+ "name": "PyRIGS",
"version": "1.0.0",
"license": "Custom",
"dependencies": {
diff --git a/pipeline/source_assets/js/interaction.js b/pipeline/source_assets/js/interaction.js
index 308fe5af..f18bb317 100644
--- a/pipeline/source_assets/js/interaction.js
+++ b/pipeline/source_assets/js/interaction.js
@@ -6,11 +6,6 @@ function setupItemTable(items_json) {
newitem = -1;
}
-function nl2br(str, is_xhtml) {
- var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '
' : '
';
- return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ breakTag +'$2');
-}
-
function escapeHtml(str) {
return $('').text(str).html();
}
diff --git a/templates/base_ajax.html b/templates/base_ajax.html
index 435b7607..1fd3fa46 100644
--- a/templates/base_ajax.html
+++ b/templates/base_ajax.html
@@ -17,7 +17,6 @@
e.preventDefault();
data = $(this).serialize();
action = $(this).attr('action');
- console.log(action)
$.post(action, data, function(resp) {
$('#modal').html(resp);
});
diff --git a/assets/templates/partials/form_field.html b/templates/partials/form_field.html
similarity index 52%
rename from assets/templates/partials/form_field.html
rename to templates/partials/form_field.html
index 027a2cce..b7b75418 100644
--- a/assets/templates/partials/form_field.html
+++ b/templates/partials/form_field.html
@@ -1,15 +1,15 @@
{% load widget_tweaks %}
{% load title_spaced from filters %}
{% spaceless %}
-
+{% if not nolabel %}{%endif%}
{% if append or prepend %}
-