Compare commits

..

18 Commits

Author SHA1 Message Date
bobbinz
409125c8a3 PSSC Values (Three Phase) (#576)
* Update ec_power_info.html

Added three phase column and made tables look the same

* Update ec_power_info.html

Fixed spelling booboo
2024-03-26 19:25:29 +00:00
dependabot[bot]
03d996eb66 Build(deps-dev): Bump follow-redirects from 1.15.4 to 1.15.6 (#574)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-25 20:19:20 +00:00
dependabot[bot]
1e40916a94 Build(deps): Bump es5-ext from 0.10.62 to 0.10.64 (#572)
Bumps [es5-ext](https://github.com/medikoo/es5-ext) from 0.10.62 to 0.10.64.
- [Release notes](https://github.com/medikoo/es5-ext/releases)
- [Changelog](https://github.com/medikoo/es5-ext/blob/main/CHANGELOG.md)
- [Commits](https://github.com/medikoo/es5-ext/compare/v0.10.62...v0.10.64)

---
updated-dependencies:
- dependency-name: es5-ext
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-03 17:14:37 +00:00
dependabot[bot]
eae3f762b7 Build(deps): Bump ip from 2.0.0 to 2.0.1 (#571)
Bumps [ip](https://github.com/indutny/node-ip) from 2.0.0 to 2.0.1.
- [Commits](https://github.com/indutny/node-ip/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: ip
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-03 17:14:29 +00:00
dependabot[bot]
7a387e8724 Build(deps): Bump axios and browser-sync (#570)
Removes [axios](https://github.com/axios/axios). It's no longer used after updating ancestor dependency [browser-sync](https://github.com/BrowserSync/browser-sync). These dependencies need to be updated together.


Removes `axios`

Updates `browser-sync` from 2.29.1 to 3.0.2
- [Release notes](https://github.com/BrowserSync/browser-sync/releases)
- [Changelog](https://github.com/BrowserSync/browser-sync/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BrowserSync/browser-sync/compare/v2.29.1...v3.0.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: indirect
- dependency-name: browser-sync
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-03 17:14:20 +00:00
dependabot[bot]
4f42219821 Build(deps-dev): Bump follow-redirects from 1.15.2 to 1.15.4 (#569)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.2 to 1.15.4.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.2...v1.15.4)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-21 19:44:08 +00:00
d7d2f93295 Fix typo in non-event display 2024-01-21 19:43:47 +00:00
2a2ce742b0 Reimplement rigboard page in a fully responsive manner (#567)
* Revive this concept for 2023

(cherry picked from commit b3939d8426)

# Conflicts:
#	pipeline/source_assets/scss/dark_screen.scss

* Update app.json

* Updates to all three layouts
2023-12-17 18:01:49 +00:00
dependabot[bot]
68d3605230 Build(deps): Bump urllib3 from 1.26.17 to 1.26.18 (#566)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.17 to 1.26.18.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.17...1.26.18)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-21 16:59:35 +01:00
1fff150566 Fix ID10T error 2023-10-21 16:57:55 +01:00
240ff25c63 Don't automatically deactivate anyone that's never logged in
That's bloody stupid
2023-10-21 16:28:29 +01:00
e265ad58a6 Tweak awaiting approval count to better ignore inactive users 2023-10-11 21:10:08 +01:00
1a32ef424b Make calendar first day Monday, not Sunday 2023-10-10 20:16:39 +01:00
dependabot[bot]
44c92fc859 Build(deps): Bump urllib3 from 1.26.16 to 1.26.17 (#563)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.16 to 1.26.17.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.16...1.26.17)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-06 23:04:13 +01:00
dependabot[bot]
1af182eaa1 Build(deps): Bump postcss from 8.4.23 to 8.4.31 (#565)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.23 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.23...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-05 16:03:39 +01:00
dependabot[bot]
425a697743 Build(deps): Bump pillow from 9.3.0 to 10.0.1 (#564)
Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.3.0 to 10.0.1.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/9.3.0...10.0.1)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-05 16:03:25 +01:00
dependabot[bot]
b7011e368b Build(deps): Bump tornado from 6.3.2 to 6.3.3 (#561)
Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.3.2 to 6.3.3.
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.3.2...v6.3.3)

---
updated-dependencies:
- dependency-name: tornado
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Arona Jones <aj@aronajones.com>
2023-09-23 19:04:36 +01:00
7d2f8d2dc8 Partial revert 769d983 which deleted more than it meant to 2023-09-23 18:54:09 +01:00
31 changed files with 800 additions and 973 deletions

View File

@@ -34,7 +34,7 @@ idna = "~=2.10"
Markdown = "~=3.3.3"
msgpack = "~=1.0.2"
pep517 = "~=0.9.1"
Pillow = "~=9.3.0"
Pillow = "~=10.0.1"
premailer = "~=3.7.0"
progress = "~=1.5"
psutil = "~=5.8.0"
@@ -57,7 +57,7 @@ static3 = "~=0.7.0"
svg2rlg = "~=0.3"
tini = "~=3.0.1"
tornado = "~=6.3"
urllib3 = "~=1.26.5"
urllib3 = "~=1.26.18"
whitenoise = "~=5.2.0"
yolk = "~=0.4.3"
zipp = "~=3.4.0"

755
Pipfile.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -121,7 +121,3 @@ def nottinghamtec_address_required(function):
return function(request, *args, **kwargs)
return wrap
def not_estates():
return user_passes_test_with_403(lambda u: not u.email.endswith('@nottingham.ac.uk'))

0
PyRIGS/forms.py Normal file
View File

View File

@@ -35,9 +35,8 @@ if DEBUG:
ALLOWED_HOSTS.append('localhost')
ALLOWED_HOSTS.append('example.com')
ALLOWED_HOSTS.append('127.0.0.1')
ALLOWED_HOSTS.append('.github.dev')
CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS
ALLOWED_HOSTS.append('.app.github.dev')
CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
if not DEBUG:

View File

@@ -6,8 +6,6 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import path
from django.views.generic import TemplateView
from PyRIGS.decorators import not_estates
from PyRIGS import views
urlpatterns = [
@@ -16,17 +14,17 @@ urlpatterns = [
path('assets/', include('assets.urls')),
path('training/', include('training.urls')),
path('', not_estates()(views.Index.as_view()), name='index'),
path('', login_required(views.Index.as_view()), name='index'),
# API
path('api/<str:model>/', not_estates()(views.SecureAPIRequest.as_view()),
path('api/<str:model>/', login_required(views.SecureAPIRequest.as_view()),
name="api_secure"),
path('api/<str:model>/<int:pk>/', not_estates()(views.SecureAPIRequest.as_view()),
path('api/<str:model>/<int:pk>/', login_required(views.SecureAPIRequest.as_view()),
name="api_secure"),
path('closemodal/', views.CloseModal.as_view(), name='closemodal'),
path('search/', not_estates()(views.Search.as_view()), name='search'),
path('search_help/', not_estates()(views.SearchHelp.as_view()), name='search_help'),
path('search/', login_required(views.Search.as_view()), name='search'),
path('search_help/', login_required(views.SearchHelp.as_view()), name='search_help'),
path('', include('users.urls')),

View File

@@ -1,18 +0,0 @@
# Generated by Django 3.2.21 on 2023-09-05 22:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('RIGS', '0051_alter_payment_method'),
]
operations = [
migrations.AddField(
model_name='venue',
name='on_campus',
field=models.BooleanField(default=False, verbose_name='Is this venue on a UoN campus?'),
),
]

View File

@@ -77,7 +77,7 @@ class Profile(AbstractUser):
@classmethod
def users_awaiting_approval_count(cls):
# last_login = None ensures we only pick up genuinely new users, not those that have been deactivated for inactivity
return Profile.objects.filter(is_approved=False, last_login=None).count()
return Profile.objects.filter(is_approved=False, last_login=None, date_joined_date=timezone.now().date()).count()
def __str__(self):
return self.name
@@ -213,7 +213,6 @@ class Venue(models.Model, RevisionMixin):
phone = models.CharField(max_length=15, blank=True, default='')
email = models.EmailField(blank=True, default='')
three_phase_available = models.BooleanField(default=False)
on_campus = models.BooleanField(default=False, verbose_name="Is this venue on a UoN campus?")
notes = models.TextField(blank=True, default='')
address = models.TextField(blank=True, default='')

View File

@@ -3,6 +3,7 @@ import urllib.error
import urllib.parse
import urllib.request
from io import BytesIO
import datetime
from PyPDF2 import PdfFileReader, PdfFileMerger
from django.conf import settings
@@ -110,7 +111,7 @@ def send_admin_awaiting_approval_email(user, request, **kwargs):
if admin.last_emailed is None or admin.last_emailed + settings.EMAIL_COOLDOWN <= timezone.now():
context = {
'request': request,
'link_suffix': reverse("admin:RIGS_profile_changelist") + '?is_approved__exact=0',
'link_suffix': reverse("admin:RIGS_profile_changelist") + f'?is_approved__exact=0&date_joined__date={timezone.now().date()}',
'number_of_users': models.Profile.users_awaiting_approval_count(),
'to_name': admin.first_name
}

View File

@@ -26,6 +26,7 @@
var calendarEl = document.getElementById('calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
firstDay: 1,
themeSystem: 'bootstrap',
aspectRatio: 1.5,
eventTimeFormat: {

View File

@@ -1,5 +0,0 @@
{% extends 'base_client.html' %}
{% block content %}
{% include 'estates/estates_event_table.html' %}
{% endblock %}

View File

@@ -1,78 +0,0 @@
{% load namewithnotes from filters %}
{% load markdown_tags %}
<div class="table-responsive">
<table class="table mb-0" id="event_table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Dates & Times</th>
<th scope="col">Event Details</th>
<th scope="col">Status</th>
<th scope="col">Member In Charge</th>
<th scope="col">Power Plan</th>
</tr>
</thead>
<tbody>
{% for event in events %}
<tr {% if event.cancelled %}style="opacity: 50% !important;"{% endif %} id="event_row">
<!---Number-->
<th scope="row" id="event_number">{{ event.display_id }}</th>
<!--Dates & Times-->
<td id="event_dates" style="text-align: justify;">
<span class="text-nowrap">Start: <strong>{{ event.start_date|date:"D d/m/Y" }}
{% if event.has_start_time %}
{{ event.start_time|date:"H:i" }}
{% endif %}</strong>
</span>
{% if event.end_date %}
<br>
<span class="text-nowrap">End: {% if event.end_date != event.start_date %}<strong>{{ event.end_date|date:"D d/m/Y" }}{% endif %}
{% if event.has_end_time %}
{{ event.end_time|date:"H:i" }}
{% endif %}</strong>
</span>
{% endif %}
</td>
<!---Details-->
<td id="event_details" class="w-100">
<h4>
{{ event.name }}
{% if event.venue %}
<small>at {{ event.venue }}</small>
{% endif %}
</h4>
{% if event.is_rig and not event.cancelled %}
<h5>
{{ event.person.name }}
{% if event.organisation %}
for {{ event.organisation.name }}
{% endif %}
</h5>
{% endif %}
{% if not event.cancelled and event.description %}
<p>{{ event.description|markdown }}</p>
{% endif %}
</td>
<td>
{{ event.get_status_display }}
</td>
<!---MIC-->
<td id="event_mic" class="text-nowrap">
{% if event.mic %}
{{ event.mic }}
{% elif event.is_rig %}
<span class="fas fa-user-slash"></span>
{% endif %}
</td>
<td>
{{ event.riskassessment.power_plan|default:"Pending" }}
</td>
</tr>
{% empty %}
<tr class="bg-warning">
<td colspan="4">No events found</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

View File

@@ -1,6 +1,6 @@
<h5 class="py-3"><a class="btn btn-info" data-toggle="collapse" href="#values" aria-expanded="false" aria-controls="values">View Threshold Values</a></h5>
<div class="row collapse" id="values">
<div class="table-responsive">
<div class="col-md-6 col-sm-12">
<table class="table table-bordered">
<thead>
<tr>
@@ -33,17 +33,20 @@
<thead>
<tr>
<th scope="row">Distro</th>
<th scope="row">Max PSSC (kA)</th>
<th scope="row">Max PSSC with Single Phase Supply (kA)</th>
<th scope="row">Max PSSC with Three Phase Supply (kA)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Intel & Toblerone distros</td>
<td>6</td>
<td>3</td>
</tr>
<tr>
<td>All other distros</td>
<td>10</td>
<td>5</td>
</tr>
</tbody>
</table>

View File

@@ -1,4 +1,4 @@
<div>
<div id="event_status">
<span class="badge badge-{% if event.confirmed %}success{% elif event.cancelled %}dark{% else %}warning{% endif %}">Status: {{ event.get_status_display }}</span>
{% if event.is_rig %}
{% if event.sum_total > 0 %}

View File

@@ -1,105 +1,183 @@
{% load namewithnotes from filters %}
{% load markdown_tags %}
<div class="table-responsive">
<table class="table mb-0" id="event_table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Dates & Times</th>
<th scope="col">Event Details</th>
<th scope="col">MIC</th>
</tr>
</thead>
<tbody>
{% for event in events %}
<tr class="{% if event.cancelled %}
table-secondary
{% elif not event.is_rig %}
table-info
{% elif not event.mic %}
table-danger
{% elif event.confirmed and event.authorised %}
{% if event.dry_hire or event.riskassessment %}
table-success
{% else %}
table-warning
{% endif %}
{% else %}
table-warning
{% endif %}" {% if event.cancelled %}style="opacity: 50% !important;"{% endif %} id="event_row">
<!---Number-->
<th scope="row" id="event_number">{{ event.display_id }}</th>
<!--Dates & Times-->
<td id="event_dates" style="text-align: justify;">
{% if not event.cancelled %}
{% if event.meet_at %}
<span class="text-nowrap">Meet: <strong>{{ event.meet_at|date:"D d/m/Y H:i" }}</strong></span>
{% endif %}
{% if event.access_at %}
<br><span class="text-nowrap">Access: <strong>{{ event.access_at|date:"D d/m/Y H:i" }}</strong></span>
{% endif %}
{% endif %}
<span class="text-nowrap">Start: <strong>{{ event.start_date|date:"D d/m/Y" }}
{% if event.has_start_time %}
{{ event.start_time|date:"H:i" }}
{% endif %}</strong>
</span>
{% if event.end_date %}
<br>
<span class="text-nowrap">End: {% if event.end_date != event.start_date %}<strong>{{ event.end_date|date:"D d/m/Y" }}{% endif %}
{% if event.has_end_time %}
{{ event.end_time|date:"H:i" }}
{% endif %}</strong>
</span>
{% endif %}
</td>
<!---Details-->
<td id="event_details" class="w-100">
<h4>
<a href="{% url 'event_detail' event.pk %}">
{{ event.name }}
</a>
{% if event.venue %}
<small>at {{ event.venue|namewithnotes:'venue_detail' }}</small>
{% endif %}
{% if event.dry_hire %}
<span class="badge badge-secondary">Dry Hire</span>
{% endif %}
</h4>
{% if event.is_rig and not event.cancelled %}
<h5>
<a href="{{ event.person.get_absolute_url }}">{{ event.person.name }}</a>
{% if event.organisation %}
for <a href="{{ event.organisation.get_absolute_url }}">{{ event.organisation.name }}</a>
{% endif %}
</h5>
{% endif %}
{% if not event.cancelled and event.description %}
<p>{{ event.description|markdown }}</p>
{% endif %}
{% include 'partials/event_status.html' %}
</td>
<!---MIC-->
<td id="event_mic" class="text-nowrap">
{% if event.mic %}
{% if perms.RIGS.view_profile %}
<a href="{% url 'profile_detail' event.mic.pk %}" class="modal-href">
{% endif %}
<img src="{{ event.mic.profile_picture }}" class="event-mic-photo"/>
{{ event.mic }}
{% if perms.RIGS.view_profile %}
</a>
{% endif %}
{% elif event.is_rig %}
<span class="fas fa-user-slash"></span>
{% endif %}
</td>
</tr>
{% empty %}
<tr class="bg-warning">
<td colspan="4">No events found</td>
</tr>
{% endfor %}
</tbody>
</table>
<style>
#event_table {
display: grid;
grid-template-columns: max-content auto;
column-gap: 1em;
}
.eventgrid {
display: inherit;
grid-column: 1/5;
grid-template-columns: subgrid;
padding: 1em;
}
.grid-header {
border-bottom: 1px solid grey;
border-top: 1px solid grey;
}
#event_status {
grid-column-start: 3;
}
#event_mic {
grid-row-start: 1;
grid-column-start: 4;
}
@media (max-width: 600px) {
#event_table {
grid-template-columns: 1fr !important;
}
.eventgrid {
grid-column: 1/1 !important;
padding: 0.5em;
}
.grid-header {
display: none;
}
#event_dates {
order: 2;
}
#event_status {
order: 3;
}
#event_mic {
grid-row-start: auto;
grid-column-start: 4;
}
}
@media (max-width: 900px) {
#event_table {
grid-template-columns: max-content;
column-gap: 0.5em;
}
.eventgrid {
grid-column: 1/3;
border: 1px solid grey;
}
#event_dates {
grid-row: 2;
grid-column: 1;
}
#event_number {
grid-row: 1;
grid-column: 1;
}
#event_mic {
grid-column: 2;
}
#event_status {
grid-column: span 2;
}
.grid-header {
display: none;
}
}
dt {
float: left;
clear: left;
margin-right: 10px;
}
dd {
margin-left: 0px;
}
</style>
<div id="event_table">
<div class="eventgrid grid-header font-weight-bold">
<div id="event_number">#</div>
<div id="event_dates">Dates & Times</div>
<div>Event Details</div>
<div id="event_mic">MIC</div>
</div>
{% for event in events %}
<div class="eventgrid {% if event.cancelled %}
table-secondary
{% elif not event.is_rig %}
table-info
{% elif not event.mic %}
table-danger
{% elif event.confirmed and event.authorised %}
{% if event.dry_hire or event.riskassessment %}
table-success
{% else %}
table-warning
{% endif %}
{% else %}
table-warning
{% endif %}" {% if event.cancelled %}style="opacity: 50% !important;"{% endif %} id="event_row">
<!---Number-->
<div class="font-weight-bold d-none d-lg-block" id="event_number">{{ event.display_id }}</div>
<!--Dates & Times-->
<div id="event_dates" style="min-width: 180px;">
<dl>
{% if not event.cancelled %}
{% if event.meet_at %}
<dt class="font-weight-normal">Meet:</dt>
<dd class="text-nowrap font-weight-bold text-lg-right">{{ event.meet_at|date:"D d/m/Y H:i" }}</dd>
{% endif %}
{% if event.access_at %}
<dt class="font-weight-normal">Access:</dt>
<dd class="text-nowrap font-weight-bold text-lg-right">{{ event.access_at|date:"D d/m/Y H:i" }}</dd>
{% endif %}
{% endif %}
<dt class="font-weight-normal">Start:</dt>
<dd class="text-nowrap font-weight-bold text-lg-right">{{ event.start_date|date:"D d/m/Y" }}
{% if event.has_start_time %}
{{ event.start_time|date:"H:i" }}
{% endif %}
</dd>
{% if event.end_date %}
<dt class="font-weight-normal">End:</dt>
<dd class="text-nowrap font-weight-bold text-lg-right">{{ event.end_date|date:"D d/m/Y" }}
{% if event.has_end_time %}
{{ event.end_time|date:"H:i" }}
{% endif %}
</dd>
{% endif %}
</dl>
</div>
<!---Details-->
<div id="event_details" class="w-100">
<h4>
<a href="{% url 'event_detail' event.pk %}">
<span class="d-inline d-lg-none">{{ event }}</span><span class="d-none d-lg-inline">{{ event.name }}</span>
</a>
{% if event.dry_hire %}
<span class="badge badge-secondary">Dry Hire</span>
{% endif %}
<br class="d-none d-lg-inline">
{% if event.venue %}
<small>at {{ event.venue|namewithnotes:'venue_detail' }}</small>
{% endif %}
</h4>
{% if event.is_rig and not event.cancelled %}
<h5>
<a href="{{ event.person.get_absolute_url }}">{{ event.person.name }}</a>
{% if event.organisation %}
for <a href="{{ event.organisation.get_absolute_url }}">{{ event.organisation.name }}</a>
{% endif %}
</h5>
{% endif %}
{% if not event.cancelled and event.description %}
<p>{{ event.description|markdown }}</p>
{% endif %}
</div>
{% include 'partials/event_status.html' %}
<!---MIC-->
<div id="event_mic" class="text-nowrap">
<span class="d-md-none align-middle">MIC:</span>
{% if event.mic %}
{% if perms.RIGS.view_profile %}
<a href="{% url 'profile_detail' event.mic.pk %}" class="modal-href">
{% endif %}
<img src="{{ event.mic.profile_picture }}" class="event-mic-photo"/>
{{ event.mic }}
{% if perms.RIGS.view_profile %}
</a>
{% endif %}
{% elif event.is_rig %}
<span class="fas fa-exclamation"></span>
{% endif %}
</div>
</div>
{% endfor %}
</div>

View File

@@ -3,8 +3,8 @@
{% block content %}
<div class="row align-items-center justify-content-between py-2 align-middle">
<div class="col-sm-12 col-md align-middle">
Key: <span class="table-success mr-1 px-2 rounded">Ready</span><span class="table-warning mr-1 px-2 rounded">Action Required</span><span class="table-danger mr-1 px-2 rounded">Needs MIC</span><span class="table-secondary mr-1 px-2 rounded">Cancelled</span><span class="table-info px-2 rounded">Non-Rig</span>
<div class="col-sm-12 col-md align-middle d-flex flex-wrap">
Key: <span class="table-success mr-1 px-2 rounded">Ready</span><span class="table-warning mr-1 px-2 rounded text-nowrap">Action Required</span><span class="table-danger mr-1 px-2 rounded text-nowrap">Needs MIC</span><span class="table-secondary mr-1 px-2 rounded">Cancelled</span><span class="table-info px-2 rounded text-nowrap">Non-Rig</span>
</div>
{% if perms.RIGS.add_event %}
<div class="col text-right">

View File

@@ -4,7 +4,7 @@ from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.generic import RedirectView
from PyRIGS.decorators import (api_key_required, has_oembed,
permission_required_with_403, not_estates)
permission_required_with_403)
from . import views
urlpatterns = [
@@ -42,22 +42,21 @@ urlpatterns = [
name='venue_update'),
# Rigboard
path('rigboard/', not_estates()(views.RigboardIndex.as_view()), name='rigboard'),
path('rigboard/calendar/', not_estates()(views.WebCalendar.as_view()),
path('rigboard/', login_required(views.RigboardIndex.as_view()), name='rigboard'),
path('rigboard/calendar/', login_required()(views.WebCalendar.as_view()),
name='web_calendar'),
re_path(r'^rigboard/calendar/(?P<view>(month|week|day))/$',
not_estates()(views.WebCalendar.as_view()), name='web_calendar'),
login_required()(views.WebCalendar.as_view()), name='web_calendar'),
re_path(r'^rigboard/calendar/(?P<view>(month|week|day))/(?P<date>(\d{4}-\d{2}-\d{2}))/$',
not_estates()(views.WebCalendar.as_view()), name='web_calendar'),
login_required()(views.WebCalendar.as_view()), name='web_calendar'),
path('rigboard/archive/', RedirectView.as_view(permanent=True, pattern_name='event_archive')),
path('estates/', login_required()(views.EstatesEventList.as_view()), name='estates'),
path('event/<int:pk>/', has_oembed(oembed_view="event_oembed")(views.EventDetail.as_view()),
name='event_detail'),
path('event/create/', permission_required_with_403('RIGS.add_event')(views.EventCreate.as_view()),
name='event_create'),
path('event/archive/', not_estates()(views.EventArchive.as_view()),
path('event/archive/', login_required()(views.EventArchive.as_view()),
name='event_archive'),
path('event/<int:pk>/embed/',
xframe_options_exempt(login_required(login_url='/user/login/embed/')(views.EventEmbed.as_view())),
@@ -76,7 +75,7 @@ urlpatterns = [
path('event/<int:pk>/ra/', permission_required_with_403('RIGS.add_riskassessment')(views.EventRiskAssessmentCreate.as_view()),
name='event_ra'),
path('event/ra/<int:pk>/', not_estates()(views.EventRiskAssessmentDetail.as_view()),
path('event/ra/<int:pk>/', login_required(views.EventRiskAssessmentDetail.as_view()),
name='ra_detail'),
path('event/ra/<int:pk>/edit/', permission_required_with_403('RIGS.change_riskassessment')(views.EventRiskAssessmentEdit.as_view()),
name='ra_edit'),
@@ -86,7 +85,7 @@ urlpatterns = [
path('event/<int:pk>/checklist/', permission_required_with_403('RIGS.add_eventchecklist')(views.EventChecklistCreate.as_view()),
name='event_ec'),
path('event/checklist/<int:pk>/', not_estates()(views.EventChecklistDetail.as_view()),
path('event/checklist/<int:pk>/', login_required(views.EventChecklistDetail.as_view()),
name='ec_detail'),
path('event/checklist/<int:pk>/edit/', permission_required_with_403('RIGS.change_eventchecklist')(views.EventChecklistEdit.as_view()),
name='ec_edit'),
@@ -95,20 +94,20 @@ urlpatterns = [
path('event/<int:pk>/power/', permission_required_with_403('RIGS.add_powertestrecord')(views.PowerTestCreate.as_view()),
name='event_pt'),
path('event/power/<int:pk>/', not_estates()(views.PowerTestDetail.as_view()),
path('event/power/<int:pk>/', login_required(views.PowerTestDetail.as_view()),
name='pt_detail'),
path('event/power/<int:pk>/edit/', permission_required_with_403('RIGS.change_powertestrecord')(views.PowerTestEdit.as_view()),
name='pt_edit'),
path('event/power/<int:pk>/review/', permission_required_with_403('RIGS.review_power')(views.MarkReviewed.as_view()),
name='pt_review', kwargs={'model': 'PowerTestRecord'}),
path('event/<int:pk>/checkin/', not_estates()(views.EventCheckIn.as_view()),
path('event/<int:pk>/checkin/', login_required(views.EventCheckIn.as_view()),
name='event_checkin'),
path('event/checkout/', not_estates()(views.EventCheckOut.as_view()),
path('event/checkout/', login_required(views.EventCheckOut.as_view()),
name='event_checkout'),
path('event/<int:pk>/checkin/edit/', not_estates()(views.EventCheckInEdit.as_view()),
path('event/<int:pk>/checkin/edit/', login_required(views.EventCheckInEdit.as_view()),
name='edit_checkin'),
path('event/<int:pk>/checkin/add/', not_estates()(views.EventCheckInOverride.as_view()),
path('event/<int:pk>/checkin/add/', login_required(views.EventCheckInOverride.as_view()),
name='event_checkin_override'),
path('event/<int:pk>/thread/', permission_required_with_403('RIGS.change_event')(views.CreateForumThread.as_view()), name='event_thread'),

View File

@@ -115,7 +115,7 @@ class VenueDetail(GenericDetailView):
class VenueCreate(GenericCreateView, ModalURLMixin):
model = models.Venue
fields = ['name', 'phone', 'email', 'address', 'notes', 'three_phase_available', 'on_campus']
fields = ['name', 'phone', 'email', 'address', 'notes', 'three_phase_available']
def get_success_url(self):
return self.get_close_url('venue_update', 'venue_detail')
@@ -123,7 +123,7 @@ class VenueCreate(GenericCreateView, ModalURLMixin):
class VenueUpdate(GenericUpdateView, ModalURLMixin):
model = models.Venue
fields = ['name', 'phone', 'email', 'address', 'notes', 'three_phase_available', 'on_campus']
fields = ['name', 'phone', 'email', 'address', 'notes', 'three_phase_available']
def get_success_url(self):
return self.get_close_url('venue_update', 'venue_detail')

View File

@@ -26,7 +26,6 @@ from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views import generic
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.mixins import UserPassesTestMixin
from PyRIGS import decorators
from PyRIGS.views import OEmbedView, is_ajax, ModalURLMixin, PrintView, get_related
@@ -423,17 +422,3 @@ class RecieveForumWebhook(generic.View):
event.save()
return HttpResponse(status=202)
return HttpResponse(status=204)
class EstatesEventList(UserPassesTestMixin, generic.TemplateView):
template_name = 'estates/estates_event_list.html'
def get_context_data(self, **kwargs):
# get super context
context = super().get_context_data(**kwargs)
# call out method to get current events
context['events'] = models.Event.objects.current_events().filter(venue__on_campus=True, dry_hire=False, is_rig=True)
context['page_title'] = "Upcoming Campus Events"
return context
def test_func(self):
return self.request.user.email.endswith('@nottingham.ac.uk')

View File

@@ -4,7 +4,7 @@
"scripts": {
"postdeploy": "python manage.py migrate && python manage.py generateSampleData"
},
"stack": "heroku-20",
"stack": "heroku-22",
"env": {
"DEBUG": {
"required": true
@@ -51,7 +51,7 @@
"url": "heroku/nodejs"
},
{
"url": "https://github.com/nottinghamtec/heroku-buildpack-python"
"url": "heroku/python"
}
]
}

View File

@@ -2,7 +2,7 @@ from django.contrib.auth.decorators import login_required
from django.urls import path, register_converter
from django.views.decorators.clickjacking import xframe_options_exempt
from PyRIGS.decorators import has_oembed, permission_required_with_403, not_estates
from PyRIGS.decorators import has_oembed, permission_required_with_403
from PyRIGS.views import OEmbedView
from . import views, converters
@@ -10,8 +10,8 @@ register_converter(converters.AssetIDConverter, 'asset')
register_converter(converters.ListConverter, 'list')
urlpatterns = [
path('', not_estates()(views.AssetList.as_view()), name='asset_index'),
path('asset/list/', not_estates()(views.AssetList.as_view()), name='asset_list'),
path('', login_required(views.AssetList.as_view()), name='asset_index'),
path('asset/list/', login_required(views.AssetList.as_view()), name='asset_list'),
path('asset/id/<asset:pk>/', has_oembed(oembed_view="asset_oembed")(views.AssetDetail.as_view()), name='asset_detail'),
path('asset/create/', permission_required_with_403('assets.add_asset')
(views.AssetCreate.as_view()), name='asset_create'),
@@ -19,26 +19,26 @@ urlpatterns = [
(views.AssetEdit.as_view()), name='asset_update'),
path('asset/id/<asset:pk>/duplicate/', permission_required_with_403('assets.add_asset')
(views.AssetDuplicate.as_view()), name='asset_duplicate'),
path('asset/id/<asset:pk>/label', not_estates()(views.GenerateLabel.as_view()), name='generate_label'),
path('asset/id/<asset:pk>/label', login_required(views.GenerateLabel.as_view()), name='generate_label'),
path('asset/<list:ids>/list/label', views.GenerateLabels.as_view(), name='generate_labels'),
path('cables/list/', not_estates()(views.CableList.as_view()), name='cable_list'),
path('cabletype/list/', not_estates()(views.CableTypeList.as_view()), name='cable_type_list'),
path('cables/list/', login_required(views.CableList.as_view()), name='cable_list'),
path('cabletype/list/', login_required(views.CableTypeList.as_view()), name='cable_type_list'),
path('cabletype/create/', permission_required_with_403('assets.add_cable_type')(views.CableTypeCreate.as_view()), name='cable_type_create'),
path('cabletype/<int:pk>/update/', permission_required_with_403('assets.change_cable_type')(views.CableTypeUpdate.as_view()), name='cable_type_update'),
path('cabletype/<int:pk>/detail/', not_estates()(views.CableTypeDetail.as_view()), name='cable_type_detail'),
path('cabletype/<int:pk>/detail/', login_required(views.CableTypeDetail.as_view()), name='cable_type_detail'),
path('asset/id/<str:pk>/embed/',
xframe_options_exempt(
login_required(login_url='/user/login/embed/')(views.AssetEmbed.as_view())),
login_required(login_url='/user/login/embed/')(views.AssetEmbed.as_view())),
name='asset_embed'),
path('asset/id/<str:pk>/oembed_json/', views.AssetOEmbed.as_view(), name='asset_oembed'),
path('asset/audit/', permission_required_with_403('assets.change_asset')(views.AssetAuditList.as_view()), name='asset_audit_list'),
path('asset/id/<str:pk>/audit/', permission_required_with_403('assets.change_asset')(views.AssetAudit.as_view()), name='asset_audit'),
path('supplier/list/', not_estates()(views.SupplierList.as_view()), name='supplier_list'),
path('supplier/<int:pk>/', not_estates()(views.SupplierDetail.as_view()), name='supplier_detail'),
path('supplier/list/', login_required(views.SupplierList.as_view()), name='supplier_list'),
path('supplier/<int:pk>/', login_required(views.SupplierDetail.as_view()), name='supplier_detail'),
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')

View File

@@ -79,7 +79,7 @@ function browserSync(done) {
spawn('python', ['manage.py', 'runserver'], {stdio: 'inherit'});
// TODO Wait for Django server to come up before browsersync, it seems inconsistent
browsersync.init({
notify: false,
notify: true,
open: false,
port: 8001,
proxy: '127.0.0.1:8000'

435
package-lock.json generated
View File

@@ -34,11 +34,11 @@
"moment": "^2.29.4",
"node-sass": "^9.0.0",
"popper.js": "^1.16.1",
"postcss": "^8.4.5",
"postcss": "^8.4.31",
"uglify-js": "^3.14.5"
},
"devDependencies": {
"browser-sync": "^2.27.11"
"browser-sync": "^3.0.2"
}
},
"node_modules/@babel/code-frame": {
@@ -805,15 +805,6 @@
"postcss": "^8.1.0"
}
},
"node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dev": true,
"dependencies": {
"follow-redirects": "^1.14.0"
}
},
"node_modules/bach": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz",
@@ -954,15 +945,14 @@
}
},
"node_modules/browser-sync": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.29.1.tgz",
"integrity": "sha512-WXy9HMJVQaNUTPjmai330E2fnDA6W84l/vBILGkYu9yHXIpWw1gJYjdQWDfEhLFljYUHNTN9jM3GCej2T55m+g==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-3.0.2.tgz",
"integrity": "sha512-PC9c7aWJFVR4IFySrJxOqLwB9ENn3/TaXCXtAa0SzLwocLN3qMjN+IatbjvtCX92BjNXsY6YWg9Eb7F3Wy255g==",
"dev": true,
"dependencies": {
"browser-sync-client": "^2.29.1",
"browser-sync-ui": "^2.29.1",
"browser-sync-client": "^3.0.2",
"browser-sync-ui": "^3.0.2",
"bs-recipes": "1.3.4",
"bs-snippet-injector": "^2.0.1",
"chalk": "4.1.2",
"chokidar": "^3.5.1",
"connect": "3.6.6",
@@ -975,11 +965,9 @@
"fs-extra": "3.0.1",
"http-proxy": "^1.18.1",
"immutable": "^3",
"localtunnel": "^2.0.1",
"micromatch": "^4.0.2",
"opn": "5.3.0",
"portscanner": "2.2.0",
"qs": "^6.11.0",
"raw-body": "^2.3.2",
"resp-modifier": "6.0.2",
"rx": "4.1.0",
@@ -999,9 +987,9 @@
}
},
"node_modules/browser-sync-client": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.29.1.tgz",
"integrity": "sha512-aESnjt3rU7CZpzjyqzhIC2UJ3MVhzRis7cPKkGbyYWDf/wnbxyRa3fFenF3Qx9061/guY3HHhD67uiTVV26DVg==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-3.0.2.tgz",
"integrity": "sha512-tBWdfn9L0wd2Pjuz/NWHtNEKthVb1Y67vg8/qyGNtCqetNz5lkDkFnrsx5UhPNPYUO8vci50IWC/BhYaQskDiQ==",
"dev": true,
"dependencies": {
"etag": "1.8.1",
@@ -1013,9 +1001,9 @@
}
},
"node_modules/browser-sync-ui": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.29.1.tgz",
"integrity": "sha512-MB7SAiUgVUrhipO2xyO1sheC9H0+LKXPQ3L1tQWcZ3AgizBnUNKAqDZPSwe4grNSa8o8ImSAwJp7lMS6XYy1Dw==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-3.0.2.tgz",
"integrity": "sha512-V3FwWAI+abVbFLTyJjXJlCMBwjc3GXf/BPGfwO2fMFACWbIGW9/4SrBOFYEOOtqzCjQE0Di+U3VIb7eES4omNA==",
"dev": true,
"dependencies": {
"async-each-series": "0.1.1",
@@ -1060,12 +1048,6 @@
"integrity": "sha512-BXvDkqhDNxXEjeGM8LFkSbR+jzmP/CYpCiVKYn+soB1dDldeU15EBNDkwVXndKuX35wnNUaPd0qSoQEAkmQtMw==",
"dev": true
},
"node_modules/bs-snippet-injector": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz",
"integrity": "sha512-4u8IgB+L9L+S5hknOj3ddNSb42436gsnGm1AuM15B7CdbkpQTyVWgIM5/JUBiKiRwGOR86uo0Lu/OsX+SAlJmw==",
"dev": true
},
"node_modules/buffer-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz",
@@ -2136,14 +2118,14 @@
}
},
"node_modules/engine.io-client": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz",
"integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==",
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.0.3",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
@@ -2165,6 +2147,15 @@
}
}
},
"node_modules/engine.io-client/node_modules/engine.io-parser": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==",
"dev": true,
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/engine.io-client/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -2233,13 +2224,14 @@
}
},
"node_modules/es5-ext": {
"version": "0.10.62",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
"integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
"version": "0.10.64",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
"hasInstallScript": true,
"dependencies": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"esniff": "^2.0.1",
"next-tick": "^1.1.0"
},
"engines": {
@@ -2298,6 +2290,25 @@
"node": ">=0.8.0"
}
},
"node_modules/esniff": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
"dependencies": {
"d": "^1.0.1",
"es5-ext": "^0.10.62",
"event-emitter": "^0.3.5",
"type": "^2.7.2"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/esniff/node_modules/type": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
"integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -2777,9 +2788,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"dev": true,
"funding": [
{
@@ -4179,9 +4190,9 @@
}
},
"node_modules/ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
"integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ=="
},
"node_modules/is-absolute": {
"version": "1.0.0",
@@ -4629,76 +4640,6 @@
"node": ">=0.10.0"
}
},
"node_modules/localtunnel": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.2.tgz",
"integrity": "sha512-n418Cn5ynvJd7m/N1d9WVJISLJF/ellZnfsLnx8WBWGzxv/ntNcFkJ1o6se5quUhCplfLGBNL5tYHiq5WF3Nug==",
"dev": true,
"dependencies": {
"axios": "0.21.4",
"debug": "4.3.2",
"openurl": "1.1.1",
"yargs": "17.1.1"
},
"bin": {
"lt": "bin/lt.js"
},
"engines": {
"node": ">=8.3.0"
}
},
"node_modules/localtunnel/node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"node_modules/localtunnel/node_modules/debug": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"dev": true,
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/localtunnel/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/localtunnel/node_modules/yargs": {
"version": "17.1.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz",
"integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==",
"dev": true,
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=12"
}
},
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -5880,15 +5821,6 @@
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -5994,12 +5926,6 @@
"wrappy": "1"
}
},
"node_modules/openurl": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz",
"integrity": "sha512-d/gTkTb1i1GKz5k3XE3XFV/PxQ1k45zDqGP2OA7YhgsaLoqm6qRvARAZOFer1fcXritWlGBRCu/UgeS4HAnXAA==",
"dev": true
},
"node_modules/opn": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
@@ -6318,9 +6244,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",
"integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==",
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"funding": [
{
"type": "opencollective",
@@ -6827,21 +6753,6 @@
"stream-shift": "^1.0.0"
}
},
"node_modules/qs": {
"version": "6.11.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz",
"integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==",
"dev": true,
"dependencies": {
"side-channel": "^1.0.4"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/quick-lru": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
@@ -7523,20 +7434,6 @@
"node": ">=8"
}
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
@@ -7750,15 +7647,15 @@
}
},
"node_modules/socket.io-client": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz",
"integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==",
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
"integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.4.0",
"socket.io-parser": "~4.2.1"
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
@@ -7788,9 +7685,9 @@
"dev": true
},
"node_modules/socket.io-parser": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
"integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
@@ -9558,15 +9455,6 @@
"postcss-value-parser": "^4.2.0"
}
},
"axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dev": true,
"requires": {
"follow-redirects": "^1.14.0"
}
},
"bach": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz",
@@ -9675,15 +9563,14 @@
}
},
"browser-sync": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.29.1.tgz",
"integrity": "sha512-WXy9HMJVQaNUTPjmai330E2fnDA6W84l/vBILGkYu9yHXIpWw1gJYjdQWDfEhLFljYUHNTN9jM3GCej2T55m+g==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-3.0.2.tgz",
"integrity": "sha512-PC9c7aWJFVR4IFySrJxOqLwB9ENn3/TaXCXtAa0SzLwocLN3qMjN+IatbjvtCX92BjNXsY6YWg9Eb7F3Wy255g==",
"dev": true,
"requires": {
"browser-sync-client": "^2.29.1",
"browser-sync-ui": "^2.29.1",
"browser-sync-client": "^3.0.2",
"browser-sync-ui": "^3.0.2",
"bs-recipes": "1.3.4",
"bs-snippet-injector": "^2.0.1",
"chalk": "4.1.2",
"chokidar": "^3.5.1",
"connect": "3.6.6",
@@ -9696,11 +9583,9 @@
"fs-extra": "3.0.1",
"http-proxy": "^1.18.1",
"immutable": "^3",
"localtunnel": "^2.0.1",
"micromatch": "^4.0.2",
"opn": "5.3.0",
"portscanner": "2.2.0",
"qs": "^6.11.0",
"raw-body": "^2.3.2",
"resp-modifier": "6.0.2",
"rx": "4.1.0",
@@ -9714,9 +9599,9 @@
}
},
"browser-sync-client": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.29.1.tgz",
"integrity": "sha512-aESnjt3rU7CZpzjyqzhIC2UJ3MVhzRis7cPKkGbyYWDf/wnbxyRa3fFenF3Qx9061/guY3HHhD67uiTVV26DVg==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-3.0.2.tgz",
"integrity": "sha512-tBWdfn9L0wd2Pjuz/NWHtNEKthVb1Y67vg8/qyGNtCqetNz5lkDkFnrsx5UhPNPYUO8vci50IWC/BhYaQskDiQ==",
"dev": true,
"requires": {
"etag": "1.8.1",
@@ -9725,9 +9610,9 @@
}
},
"browser-sync-ui": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.29.1.tgz",
"integrity": "sha512-MB7SAiUgVUrhipO2xyO1sheC9H0+LKXPQ3L1tQWcZ3AgizBnUNKAqDZPSwe4grNSa8o8ImSAwJp7lMS6XYy1Dw==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-3.0.2.tgz",
"integrity": "sha512-V3FwWAI+abVbFLTyJjXJlCMBwjc3GXf/BPGfwO2fMFACWbIGW9/4SrBOFYEOOtqzCjQE0Di+U3VIb7eES4omNA==",
"dev": true,
"requires": {
"async-each-series": "0.1.1",
@@ -9756,12 +9641,6 @@
"integrity": "sha512-BXvDkqhDNxXEjeGM8LFkSbR+jzmP/CYpCiVKYn+soB1dDldeU15EBNDkwVXndKuX35wnNUaPd0qSoQEAkmQtMw==",
"dev": true
},
"bs-snippet-injector": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz",
"integrity": "sha512-4u8IgB+L9L+S5hknOj3ddNSb42436gsnGm1AuM15B7CdbkpQTyVWgIM5/JUBiKiRwGOR86uo0Lu/OsX+SAlJmw==",
"dev": true
},
"buffer-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz",
@@ -10602,14 +10481,14 @@
}
},
"engine.io-client": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz",
"integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==",
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.0.3",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
},
@@ -10623,6 +10502,12 @@
"ms": "2.1.2"
}
},
"engine.io-parser": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==",
"dev": true
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -10661,12 +10546,13 @@
}
},
"es5-ext": {
"version": "0.10.62",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
"integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
"version": "0.10.64",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
"requires": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"esniff": "^2.0.1",
"next-tick": "^1.1.0"
}
},
@@ -10716,6 +10602,24 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
},
"esniff": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
"requires": {
"d": "^1.0.1",
"es5-ext": "^0.10.62",
"event-emitter": "^0.3.5",
"type": "^2.7.2"
},
"dependencies": {
"type": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
"integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
}
}
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -11110,9 +11014,9 @@
}
},
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"dev": true
},
"for-in": {
@@ -12211,9 +12115,9 @@
"integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ=="
},
"ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
"integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ=="
},
"is-absolute": {
"version": "1.0.0",
@@ -12571,61 +12475,6 @@
}
}
},
"localtunnel": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.2.tgz",
"integrity": "sha512-n418Cn5ynvJd7m/N1d9WVJISLJF/ellZnfsLnx8WBWGzxv/ntNcFkJ1o6se5quUhCplfLGBNL5tYHiq5WF3Nug==",
"dev": true,
"requires": {
"axios": "0.21.4",
"debug": "4.3.2",
"openurl": "1.1.1",
"yargs": "17.1.1"
},
"dependencies": {
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"debug": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"dev": true,
"requires": {
"ms": "2.1.2"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"yargs": {
"version": "17.1.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz",
"integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==",
"dev": true,
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
}
}
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -13529,12 +13378,6 @@
}
}
},
"object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
"dev": true
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -13613,12 +13456,6 @@
"wrappy": "1"
}
},
"openurl": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz",
"integrity": "sha512-d/gTkTb1i1GKz5k3XE3XFV/PxQ1k45zDqGP2OA7YhgsaLoqm6qRvARAZOFer1fcXritWlGBRCu/UgeS4HAnXAA==",
"dev": true
},
"opn": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
@@ -13840,9 +13677,9 @@
"integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg=="
},
"postcss": {
"version": "8.4.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",
"integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==",
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"requires": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
@@ -14152,15 +13989,6 @@
}
}
},
"qs": {
"version": "6.11.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz",
"integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==",
"dev": true,
"requires": {
"side-channel": "^1.0.4"
}
},
"quick-lru": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
@@ -14693,17 +14521,6 @@
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
}
},
"signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
@@ -14894,15 +14711,15 @@
}
},
"socket.io-client": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz",
"integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==",
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
"integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.4.0",
"socket.io-parser": "~4.2.1"
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"dependencies": {
"debug": {
@@ -14923,9 +14740,9 @@
}
},
"socket.io-parser": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
"integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.1.0",

View File

@@ -30,11 +30,11 @@
"moment": "^2.29.4",
"node-sass": "^9.0.0",
"popper.js": "^1.16.1",
"postcss": "^8.4.5",
"postcss": "^8.4.31",
"uglify-js": "^3.14.5"
},
"devDependencies": {
"browser-sync": "^2.27.11"
"browser-sync": "^3.0.2"
},
"scripts": {
"gulp": "gulp",

View File

@@ -77,17 +77,8 @@
border-collapse: separate !important;
border-spacing: 0;
}
#event_table tr th {
border-right: 0 !important;
}
#event_table tr td {
border-left: 0 !important;
}
#event_table tr td:not(:last-child) {
border-right: 0 !important;
}
@each $color, $value in $theme-colors {
.table-#{$color} {
table.table-#{$color} {
> td,th {
border: 0.3em solid theme-color-level($color, -6) !important;
}
@@ -96,6 +87,11 @@
background-color: #222 !important;
}
}
#event_row.table-#{$color} {
border: 0.3em solid theme-color-level($color, -6) !important;
background-color: #222 !important;
color: white !important;
}
}
del {
color: black;
@@ -156,4 +152,7 @@
.modal {
overflow-y: auto !important; //Bootstrap Dark Theme overrides this to none for some insane reason so we need to change it back
}
.text-muted {
color: #c9c9c9 !important;
}
}

View File

@@ -1,7 +1,6 @@
{% extends override|default:"base_rigs.html" %}
{% load widget_tweaks %}
{% load button from filters %}
{% load verbose_name from filters %}
{% load markdown_tags %}
{% block content %}
@@ -31,11 +30,6 @@
<dd>{{ object.three_phase_available|yesno|capfirst }}</dd>
{% endif%}
{% if object.on_campus is not None %}
<dt>{{ object|verbose_name:"on_campus" }}</dt>
<dd>{{ object.on_campus|yesno|capfirst }}</dd>
{% endif%}
{% if object.union_account is not None %}
<dt>Union Account</dt>
<dd>{{ object.union_account|yesno|capfirst }}</dd>

View File

@@ -78,20 +78,6 @@
</div>
</div>
{% endif %}
{% if form.on_campus is not None %}
<div class="form-group form-row">
<div class="col-sm-10 col-sm-offset-2">
<div class="checkbox">
<label>
{% render_field form.on_campus %} {{ form.on_campus.label }}
</label>
</div>
</div>
<div class="alert alert-danger">
<span class="fas fa-exclamation"></span> Selecting this option will add <em>all</em> events at this venue to the calendar viewable by UoN Estates.
</div>
</div>
{% endif %}
{% if form.union_account is not None %}
<div class="form-group form-row">
<div class="col-sm-10 col-sm-offset-2">

View File

@@ -78,6 +78,11 @@
</tr>
{% endfor %}
<tr><th colspan="3" class="text-center">{{object}}</th></tr>
<tr>
<td><ul class="list-unstyled">{% for req in object.started_requirements %}<li>{{ req.item }} {% user_has_qualification u req.item 0 %}</li>{% endfor %}</ul></td>
<td><ul class="list-unstyled">{% for req in object.complete_requirements %}<li>{{ req.item }} {% user_has_qualification u req.item 1 %}</li>{% endfor %}</ul></td>
<td><ul class="list-unstyled">{% for req in object.passed_out_requirements %}<li>{{ req.item }} {% user_has_qualification u req.item 2 %}</li>{% endfor %}</ul></td>
</tr>
</tbody>
</table>
</div>

View File

@@ -1,34 +1,33 @@
from django.urls import path
from django.contrib.auth.decorators import login_required
from training.decorators import is_supervisor
from training import views, models
from versioning.views import VersionHistory
from PyRIGS.decorators import not_estates
urlpatterns = [
path('items/', not_estates()(views.ItemList.as_view()), name='item_list'),
path('items/export/', not_estates()(views.ItemListExport.as_view()), name='item_list_export'),
path('item/<int:pk>/qualified_users/', not_estates()(views.ItemQualifications.as_view()), name='item_qualification'),
path('items/', login_required(views.ItemList.as_view()), name='item_list'),
path('items/export/', login_required(views.ItemListExport.as_view()), name='item_list_export'),
path('item/<int:pk>/qualified_users/', login_required(views.ItemQualifications.as_view()), name='item_qualification'),
path('trainee/list/', not_estates()(views.TraineeList.as_view()), name='trainee_list'),
path('trainee/<int:pk>/', not_estates()(views.TraineeDetail.as_view()),
path('trainee/list/', login_required(views.TraineeList.as_view()), name='trainee_list'),
path('trainee/<int:pk>/', login_required(views.TraineeDetail.as_view()),
name='trainee_detail'),
path('trainee/<int:pk>/history', not_estates()(VersionHistory.as_view()), name='trainee_history', kwargs={'model': models.Trainee, 'app': 'training'}), # Not picked up automatically because proxy model (I think)
path('trainee/<int:pk>/history', login_required(VersionHistory.as_view()), name='trainee_history', kwargs={'model': models.Trainee, 'app': 'training'}), # Not picked up automatically because proxy model (I think)
path('trainee/<int:pk>/add_qualification/', is_supervisor()(views.AddQualification.as_view()),
name='add_qualification'),
path('trainee/edit_qualification/<int:pk>/', is_supervisor()(views.EditQualification.as_view()),
name='edit_qualification'),
path('levels/', not_estates()(views.LevelList.as_view()), name='level_list'),
path('level/<int:pk>/', not_estates()(views.LevelDetail.as_view()), name='level_detail'),
path('level/<int:pk>/user/<int:u>/', not_estates()(views.LevelDetail.as_view()), name='level_detail'),
path('levels/', login_required(views.LevelList.as_view()), name='level_list'),
path('level/<int:pk>/', login_required(views.LevelDetail.as_view()), name='level_detail'),
path('level/<int:pk>/user/<int:u>/', login_required(views.LevelDetail.as_view()), name='level_detail'),
path('level/<int:pk>/add_requirement/', is_supervisor()(views.AddLevelRequirement.as_view()), name='add_requirement'),
path('level/remove_requirement/<int:pk>/', is_supervisor()(views.RemoveRequirement.as_view()), name='remove_requirement'),
path('trainee/<int:pk>/level/<int:level_pk>/confirm', is_supervisor()(views.ConfirmLevel.as_view()), name='confirm_level'),
path('trainee/<int:pk>/item_record', not_estates()(views.TraineeItemDetail.as_view()), name='trainee_item_detail'),
path('trainee/<int:pk>/item_record', login_required(views.TraineeItemDetail.as_view()), name='trainee_item_detail'),
path('session_log', is_supervisor()(views.SessionLog.as_view()), name='session_log'),
]

View File

@@ -12,8 +12,8 @@ class Command(BaseCommand):
def handle(self, *args, **options):
for person in Profile.objects.all():
# Inactivate users that have not logged in for a year (or have never logged in)
if person.last_login is None or (timezone.now() - person.last_login).days > 365:
# Inactivate users that have not logged in for a year
if person.last_login is not None and (timezone.now() - person.last_login).days > 365:
person.is_active = False
person.is_approved = False
person.save()

View File

@@ -5,7 +5,7 @@ from django.urls import path
from django.views.decorators.clickjacking import xframe_options_exempt
from registration.backends.default.views import RegistrationView
from PyRIGS.decorators import permission_required_with_403, not_estates
from PyRIGS.decorators import permission_required_with_403
from users import forms, views
urlpatterns = [
@@ -14,11 +14,11 @@ urlpatterns = [
path('user/login/', LoginView.as_view(authentication_form=forms.CheckApprovedForm), name='login'),
path('user/login/embed/', xframe_options_exempt(views.LoginEmbed.as_view()), name='login_embed'),
# User editing
path('user/edit/', not_estates()(views.ProfileUpdateSelf.as_view()),
path('user/edit/', login_required(views.ProfileUpdateSelf.as_view()),
name='profile_update_self'),
path('user/reset_api_key', not_estates()(views.ResetApiKey.as_view(permanent=False)),
path('user/reset_api_key', login_required(views.ResetApiKey.as_view(permanent=False)),
name='reset_api_key'),
path('user/', not_estates()(views.ProfileDetail.as_view()), name='profile_detail'),
path('user/', login_required(views.ProfileDetail.as_view()), name='profile_detail'),
path('user/<int:pk>/',
permission_required_with_403('RIGS.view_profile')(views.ProfileDetail.as_view()),
name='profile_detail'),