mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-02-10 00:39:40 +00:00
Compare commits
39 Commits
ad8ffa69de
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
731ccc0516 | ||
|
|
fa60c4421f | ||
|
|
97b3663909 | ||
|
|
50f6ff4bfd | ||
|
|
0945a893d5 | ||
|
|
bc3611db9e | ||
|
|
a6c76ee24f | ||
|
|
a4ab2992a4 | ||
|
|
33ac604d10 | ||
|
|
9f25fe7bf0 | ||
|
|
68b28a6df2 | ||
|
|
b022a0541e | ||
|
|
51deadc192 | ||
|
|
444f64ddc1 | ||
|
|
3f38ce77e0 | ||
|
|
39a2401ec9 | ||
|
|
032768d3b0 | ||
|
|
007571fab6 | ||
|
|
311189470d | ||
|
|
db387c768a | ||
|
|
3c4901f86a | ||
|
|
385a3bd979 | ||
|
|
ded8925ef5 | ||
|
|
0bb7418f17 | ||
|
|
30a053b813 | ||
|
|
bd5af7c390 | ||
|
|
22bba7e8af | ||
|
|
dcf19ff773 | ||
|
|
6e1ac4e203 | ||
|
|
899f958aa3 | ||
|
|
ee83fd2064 | ||
|
|
87dd32da6c | ||
|
|
25593f3e6c | ||
|
|
89d50fbd49 | ||
|
|
7313c905ea | ||
|
|
074d40ea03 | ||
|
|
1496a75826 | ||
|
|
1f22470bfd | ||
|
|
47babff6d4 |
29
.github/workflows/django.yml
vendored
29
.github/workflows/django.yml
vendored
@@ -18,34 +18,37 @@ jobs:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get install libcairo2-dev
|
||||
- name: Set up Python
|
||||
|
||||
- name: "Set up Python"
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
cache: 'pipenv'
|
||||
python-version-file: ".python-version"
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip pipenv
|
||||
pipenv install -d
|
||||
# if: steps.pcache.outputs.cache-hit != 'true'
|
||||
run: uv sync --locked --all-extras --dev
|
||||
|
||||
- name: Cache Static Files
|
||||
id: static-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: 'pipeline/built_assets'
|
||||
key: ${{ hashFiles('package-lock.json') }}-${{ hashFiles('pipeline/source_assets') }}
|
||||
|
||||
- uses: bahmutov/npm-install@v1
|
||||
if: steps.static-cache.outputs.cache-hit != 'true'
|
||||
- run: node node_modules/gulp/bin/gulp build
|
||||
if: steps.static-cache.outputs.cache-hit != 'true'
|
||||
- name: Basic Checks
|
||||
run: |
|
||||
pipenv run pycodestyle . --exclude=migrations,node_modules
|
||||
pipenv run python3 manage.py check
|
||||
pipenv run python3 manage.py makemigrations --check --dry-run
|
||||
pipenv run python3 manage.py collectstatic --noinput
|
||||
uv run pycodestyle . --exclude=.venv,migrations,node_modules
|
||||
uv run python3 manage.py check
|
||||
uv run python3 manage.py makemigrations --check --dry-run
|
||||
uv run python3 manage.py collectstatic --noinput
|
||||
- name: Run Tests
|
||||
run: pipenv run pytest -n auto --cov
|
||||
run: uv run pytest -n auto --cov
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
@@ -53,4 +56,4 @@ jobs:
|
||||
path: screenshots/
|
||||
retention-days: 5
|
||||
- name: Coveralls
|
||||
run: pipenv run coveralls --service=github
|
||||
run: uv run coveralls --service=github
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -101,3 +101,6 @@ crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
.vscode/
|
||||
screenshots/
|
||||
|
||||
# Virutal Environments
|
||||
.venv/
|
||||
|
||||
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.10
|
||||
104
Pipfile
104
Pipfile
@@ -1,104 +0,0 @@
|
||||
[[source]]
|
||||
url = "https://pypi.python.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
ansicolors = "~=1.1.8"
|
||||
asgiref = "~=3.3.1"
|
||||
"backports.tempfile" = "~=1.0"
|
||||
"backports.weakref" = "~=1.0.post1"
|
||||
beautifulsoup4 = "~=4.9.3"
|
||||
Brotli = "~=1.0.9"
|
||||
cachetools = "~=4.2.1"
|
||||
chardet = "~=4.0.0"
|
||||
configparser = "~=5.0.1"
|
||||
contextlib2 = "~=0.6.0.post1"
|
||||
cssselect = "~=1.1.0"
|
||||
cssutils = "~=1.0.2"
|
||||
dj-database-url = "~=0.5.0"
|
||||
dj-static = "~=0.0.6"
|
||||
Django = "~=3.2"
|
||||
django-debug-toolbar = "~=4.0.0"
|
||||
django-filter = "~=2.4.0"
|
||||
django-ical = "~=1.7.1"
|
||||
django-recurrence = "~=1.10.3"
|
||||
django-registration-redux = "~=2.9"
|
||||
django-reversion = "~=3.0.9"
|
||||
django-widget-tweaks = "~=1.4.8"
|
||||
django-htmlmin = "~=0.11.0"
|
||||
envparse = "*"
|
||||
gunicorn = "~=22.0.0"
|
||||
icalendar = "~=4.0.7"
|
||||
idna = "~=3.7"
|
||||
Markdown = "~=3.3.3"
|
||||
msgpack = "~=1.0.2"
|
||||
pep517 = "~=0.9.1"
|
||||
Pillow = "~=10.0.1"
|
||||
premailer = "~=3.7.0"
|
||||
progress = "~=1.5"
|
||||
psutil = "~=5.8.0"
|
||||
psycopg2 = "~=2.8.6"
|
||||
Pygments = "~=2.15.0"
|
||||
pyparsing = "~=2.4.7"
|
||||
PyPDF2 = "~=1.27.5"
|
||||
PyPOM = "~=2.2.4"
|
||||
python-dateutil = "~=2.8.1"
|
||||
pytoml = "~=0.1.21"
|
||||
pytz = "~=2020.5"
|
||||
reportlab = "*"
|
||||
requests = "~=2.32.3"
|
||||
retrying = "~=1.3.3"
|
||||
simplejson = "~=3.17.2"
|
||||
six = "~=1.15.0"
|
||||
soupsieve = "~=2.1"
|
||||
sqlparse = "~=0.5.0"
|
||||
static3 = "~=0.7.0"
|
||||
svg2rlg = "~=0.3"
|
||||
tini = "~=3.0.1"
|
||||
tornado = "~=6.3"
|
||||
urllib3 = "~=1.26.19"
|
||||
whitenoise = "~=5.2.0"
|
||||
yolk = "~=0.4.3"
|
||||
zipp = "~=3.4.0"
|
||||
"zope.component" = "~=4.6.2"
|
||||
"zope.deferredimport" = "~=4.3.1"
|
||||
"zope.deprecation" = "~=4.4.0"
|
||||
"zope.event" = "~=4.5.0"
|
||||
"zope.hookable" = "~=5.0.1"
|
||||
"zope.interface" = "~=5.2.0"
|
||||
"zope.proxy" = "~=4.3.5"
|
||||
"zope.schema" = "~=6.0.1"
|
||||
sentry-sdk = "*"
|
||||
diff-match-patch = "*"
|
||||
python-barcode = "*"
|
||||
django-hCaptcha = "*"
|
||||
importlib-metadata = "*"
|
||||
django-hcaptcha = "*"
|
||||
"z3c.rml" = "*"
|
||||
pikepdf = "*"
|
||||
django-queryable-properties = "*"
|
||||
django-mass-edit = "*"
|
||||
selenium = "~=4.9.1"
|
||||
|
||||
[dev-packages]
|
||||
pycodestyle = "~=2.9.1"
|
||||
coveralls = "*"
|
||||
django-coverage-plugin = "*"
|
||||
pytest-cov = "*"
|
||||
pytest-django = "*"
|
||||
pluggy = "*"
|
||||
pytest-splinter = "*"
|
||||
pytest = "*"
|
||||
pytest-reverse = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.10"
|
||||
|
||||
[dev-packages.pytest-xdist]
|
||||
extras = [ "psutil",]
|
||||
version = "*"
|
||||
|
||||
[dev-packages.PyPOM]
|
||||
extras = [ "splinter",]
|
||||
version = "*"
|
||||
2309
Pipfile.lock
generated
2309
Pipfile.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -79,7 +79,9 @@ def api_key_required(function):
|
||||
"""
|
||||
Decorator for views that checks api_pk and api_key.
|
||||
Failed users will be given a 403 error.
|
||||
Should only be used for urls which include <api_pk> and <api_key> kwargs
|
||||
Should only be used for urls which include <api_pk> and <api_key> kwargs.
|
||||
|
||||
Will update the kwargs to include the user object if successful (under the key 'user').
|
||||
"""
|
||||
|
||||
def wrap(request, *args, **kwargs):
|
||||
@@ -97,6 +99,7 @@ def api_key_required(function):
|
||||
|
||||
try:
|
||||
user_object = models.Profile.objects.get(pk=userid)
|
||||
kwargs = {**kwargs, 'user': user_object}
|
||||
except models.Profile.DoesNotExist:
|
||||
return error_resp
|
||||
|
||||
|
||||
@@ -104,7 +104,10 @@ DATABASES = {
|
||||
if not DEBUG:
|
||||
import dj_database_url
|
||||
|
||||
DATABASES['default'] = dj_database_url.config()
|
||||
if env("FRANKENRIGS_DATABASE_URL") is not None:
|
||||
DATABASES['default'] = dj_database_url.config(env="FRANKENRIGS_DATABASE_URL")
|
||||
else:
|
||||
DATABASES['default'] = dj_database_url.config()
|
||||
|
||||
# Logging
|
||||
LOGGING = {
|
||||
|
||||
@@ -379,6 +379,10 @@ class Event(models.Model, RevisionMixin):
|
||||
return self.pk
|
||||
return "????"
|
||||
|
||||
@property
|
||||
def needs_mic(self):
|
||||
return self.is_rig and not self.dry_hire
|
||||
|
||||
# Calculated values
|
||||
"""
|
||||
EX Vat
|
||||
@@ -508,7 +512,7 @@ class Event(models.Model, RevisionMixin):
|
||||
def can_check_in(self):
|
||||
earliest = self.earliest_time
|
||||
if isinstance(self.earliest_time, datetime.date):
|
||||
earliest = datetime.datetime.combine(self.start_date, datetime.time(00, 00))
|
||||
earliest = datetime.datetime.combine(self.earliest_time, datetime.time(00, 00))
|
||||
tz = pytz.timezone(settings.TIME_ZONE)
|
||||
earliest = tz.localize(earliest)
|
||||
return not self.dry_hire and not self.status == Event.CANCELLED and earliest <= timezone.now()
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
|
||||
<listStyle name="ul"
|
||||
start="bulletchar"
|
||||
leftIndent="0"
|
||||
bulletDedent="10"
|
||||
bulletFontSize="10"/>
|
||||
</stylesheet>
|
||||
|
||||
|
||||
@@ -6,7 +6,36 @@
|
||||
{% load total_invoices_todo from filters %}
|
||||
|
||||
{% block titleheader %}
|
||||
<a class="navbar-brand" style="margin-left: auto; margin-right: auto;" href="/">RIGS</a>
|
||||
<style>
|
||||
.franken {
|
||||
font-family: Fontdiner Swanky;
|
||||
color: #00ff00;
|
||||
animation: glow 1.5s infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes glow {
|
||||
0% {
|
||||
text-shadow: 0 0 5px #00ff00,
|
||||
0 0 10px #00ff00,
|
||||
0 0 20px #00ff00,
|
||||
0 0 40px #00ff00;
|
||||
}
|
||||
50% {
|
||||
text-shadow: 0 0 10px #00ff00,
|
||||
0 0 20px #00ff00,
|
||||
0 0 30px #00ff00,
|
||||
0 0 60px #00ff00;
|
||||
}
|
||||
100% {
|
||||
text-shadow: 0 0 5px #00ff00,
|
||||
0 0 10px #00ff00,
|
||||
0 0 20px #00ff00,
|
||||
0 0 40px #00ff00;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<a class="navbar-brand" style="margin-left: auto; margin-right: auto;" href="/"><span class="franken">Franken</span>RIGS</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block titleelements %}
|
||||
|
||||
@@ -3,6 +3,19 @@
|
||||
{% load markdown_tags %}
|
||||
{% load static %}
|
||||
|
||||
{% block js %}
|
||||
{{ block.super }}
|
||||
|
||||
<script>
|
||||
$(document).keydown(function(e) {
|
||||
if ((e.ctrlKey || e.metaKey) && e.keyCode == 80) {
|
||||
window.open("{% url 'event_print' object.pk %}", '_blank');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row my-3 py-3">
|
||||
{% if not request.is_ajax %}
|
||||
|
||||
@@ -70,6 +70,16 @@
|
||||
</blockTable>
|
||||
|
||||
<spacer length="15"/>
|
||||
|
||||
{% if object.notes %}
|
||||
<hr/>
|
||||
<spacer length="15"/>
|
||||
<para><strong>Additional Notes:</strong></para>
|
||||
<spacer length="15"/>
|
||||
<para>{{ object.notes }}</para>
|
||||
<spacer length="15"/>
|
||||
{% endif %}
|
||||
|
||||
<hr/>
|
||||
<spacer length="15"/>
|
||||
|
||||
|
||||
147
RIGS/templates/partials/event_row.html
Normal file
147
RIGS/templates/partials/event_row.html
Normal file
@@ -0,0 +1,147 @@
|
||||
{% load namewithnotes from filters %}
|
||||
{% load markdown_tags %}
|
||||
|
||||
<div class="card h-100 border-3 {{ border_class }} event-row">
|
||||
<div class="card-header {{ header_bg }} {{ header_text }} py-3">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="d-flex align-items-center">
|
||||
<h5 class="mb-0 mr-3">
|
||||
<a href="{% url 'event_detail' event.pk %}"
|
||||
class="{{ header_text }} text-decoration-underline fw-bold">
|
||||
<strong>{{ event.display_id }}</strong> - {{ event.name }}
|
||||
</a>
|
||||
</h5>
|
||||
{% if event.dry_hire %}
|
||||
<span class="badge px-3 py-2 rounded-pill fs-6 text-dark bg-light">Dry Hire</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="badge fs-6 px-3 py-2 bg-light text-dark rounded-pill">{{ event.get_status_display }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row align-items-start">
|
||||
|
||||
<div class="col-md-2 border-end event-dates">
|
||||
<div class="mb-2">
|
||||
<small class="text-muted">Meet at:</small>
|
||||
{% if event.meet_at %}
|
||||
<p class="mb-1">{{ event.meet_at|date:"D j M Y, H:i" }}</p>
|
||||
{% else %}
|
||||
<p class="mb-1">Not specified</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<small class="text-muted">Access from:</small>
|
||||
{% if event.access_at %}
|
||||
<p class="mb-1">{{ event.access_at|date:"D j M Y, H:i" }}</p>
|
||||
{% else %}
|
||||
<p class="mb-1">Not specified</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<small class="text-muted">Start:</small>
|
||||
<p class="mb-1">
|
||||
{% if event.start_date and event.start_time %}
|
||||
{{ event.start_date|date:"D j M Y" }}, {{ event.start_time|date:"H:i" }}
|
||||
{% elif event.start_date %}
|
||||
{{ event.start_date|date:"D j M Y" }}
|
||||
{% elif event.start_time %}
|
||||
{{ event.start_time|date:"H:i" }}
|
||||
{% else %}
|
||||
Not specified
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<small class="text-muted">End:</small>
|
||||
<p class="mb-1">
|
||||
{% if event.end_date and event.end_time %}
|
||||
{{ event.end_date|date:"D j M Y" }}, {{ event.end_time|date:"H:i" }}
|
||||
{% elif event.end_date %}
|
||||
{{ event.end_date|date:"D j M Y" }}
|
||||
{% elif event.end_time %}
|
||||
{{ event.end_time|date:"H:i" }}
|
||||
{% else %}
|
||||
Not specified
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-10">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-6">
|
||||
|
||||
{% if event.venue %}
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">Venue:</small>
|
||||
<p class="mb-1">{{ event.venue|namewithnotes:'venue_detail' }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if event.is_rig %}
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">Client:</small>
|
||||
<p class="mb-1">
|
||||
{% if event.person %}
|
||||
<a href="{{ event.person.get_absolute_url }}">{{ event.person.name }}</a>
|
||||
{% if event.organisation %}
|
||||
for <a href="{{ event.organisation.get_absolute_url }}">{{ event.organisation }}</a>
|
||||
{% endif %}
|
||||
{% elif event.organisation %}
|
||||
<a href="{{ event.organisation.get_absolute_url }}">{{ event.organisation }}</a>
|
||||
{% else %}
|
||||
No client specified
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if event.mic or event.needs_mic %}
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">Member in Charge (MIC):</small>
|
||||
<div class="d-flex align-items-center mt-1">
|
||||
{% if event.mic %}
|
||||
<img src="{{ event.mic.profile_picture }}" alt="{{ event.mic.name }}"
|
||||
class="rounded-circle mr-1" width="32" height="32">
|
||||
<span>
|
||||
{% if perms.RIGS.view_profile %}
|
||||
<a href="{% url 'profile_detail' event.mic.pk %}" class="modal-href">
|
||||
{% endif %}
|
||||
{{ event.mic.name }}
|
||||
{% if perms.RIGS.view_profile %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="text-danger">No MIC assigned</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-6">
|
||||
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">Description:</small>
|
||||
<p class="mb-1">{{ event.description|markdown }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<small class="text-muted">Status:</small>
|
||||
<div class="mt-1">
|
||||
{% include "partials/event_status.html" with status=event.status %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3,7 +3,7 @@
|
||||
{% if event.is_rig %}
|
||||
{% if event.sum_total > 0 %}
|
||||
{% if event.purchase_order %}
|
||||
<span class="badge badge-success">PO: {{ event.purchase_order }}</span>
|
||||
<span class="badge badge-success">PO: Received</span>
|
||||
{% elif event.authorised %}
|
||||
<span class="badge badge-success">Authorisation: Complete <span class="fas fa-check"></span></span>
|
||||
{% elif event.authorisation and event.authorisation.amount != event.total and event.authorisation.last_edited_at > event.auth_request_at %}
|
||||
|
||||
@@ -1,195 +1,70 @@
|
||||
{% load namewithnotes from filters %}
|
||||
{% load markdown_tags %}
|
||||
|
||||
<style>
|
||||
#event_table {
|
||||
display: grid;
|
||||
grid-template-columns: max-content min-content minmax(max-content, 1fr) max-content;
|
||||
column-gap: 1em;
|
||||
}
|
||||
.eventgrid {
|
||||
display: inherit;
|
||||
grid-column: 1/5;
|
||||
grid-template-columns: subgrid;
|
||||
padding: 1em;
|
||||
dt, dd { display: block; float: left; }
|
||||
dt { clear: both; }
|
||||
dd { float: right; }
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.c-none {
|
||||
display: none;
|
||||
}
|
||||
.c-inline {
|
||||
display: inline;
|
||||
}
|
||||
@container (width <= 500px) {
|
||||
#event_table {
|
||||
grid-template-columns: 1fr !important;
|
||||
.light-link {
|
||||
color: #ebf5ff !important;
|
||||
}
|
||||
.eventgrid {
|
||||
grid-column: 1/1 !important;
|
||||
padding: 0.5em;
|
||||
|
||||
.dark-link {
|
||||
color: #4495ff !important;
|
||||
}
|
||||
.grid-header {
|
||||
display: none;
|
||||
|
||||
.link-on-green {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
#event_dates {
|
||||
order: 2;
|
||||
}
|
||||
#event_status {
|
||||
order: 3;
|
||||
}
|
||||
#event_mic {
|
||||
grid-row-start: auto;
|
||||
grid-column-start: 4;
|
||||
}
|
||||
}
|
||||
@container (width <= 700px) {
|
||||
#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, .c-md-none {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@container (width > 700px) {
|
||||
.c-lg-block {
|
||||
display: block;
|
||||
}
|
||||
.c-lg-inline {
|
||||
display: inline;
|
||||
}
|
||||
.c-lg-none, .c-md-none {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</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
|
||||
|
||||
<div class="row">
|
||||
{% for event in events %}
|
||||
<div class="col-12 mb-4">
|
||||
{% comment %} Determine card style based on event status {% endcomment %}
|
||||
{% if event.cancelled %}
|
||||
|
||||
{% with border_class="border-secondary" header_bg="bg-secondary" header_text="light-link" %}
|
||||
{% include "partials/event_row.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% elif not event.is_rig %}
|
||||
table-info
|
||||
|
||||
{% with border_class="border-primary" header_bg="bg-primary" header_text="light-link" %}
|
||||
{% include "partials/event_row.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% elif not event.mic %}
|
||||
table-danger
|
||||
|
||||
{% with border_class="border-danger" header_bg="bg-danger" header_text="light-link" %}
|
||||
{% include "partials/event_row.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% elif event.confirmed and event.authorised %}
|
||||
|
||||
{% if event.dry_hire or event.riskassessment %}
|
||||
table-success
|
||||
|
||||
{% with border_class="border-success" header_bg="bg-success" header_text="link-on-green" %}
|
||||
{% include "partials/event_row.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% else %}
|
||||
table-warning
|
||||
|
||||
{% with border_class="border-warning" header_bg="bg-warning" header_text="dark-link" %}
|
||||
{% include "partials/event_row.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
table-warning
|
||||
{% endif %}" {% if event.cancelled %}style="opacity: 50% !important;"{% endif %} id="event_row">
|
||||
<!---Number-->
|
||||
<div class="font-weight-bold c-none c-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>
|
||||
|
||||
{% with border_class="border-warning" header_bg="bg-warning" header_text="dark-link" %}
|
||||
{% include "partials/event_row.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
No events currently scheduled.
|
||||
</div>
|
||||
<!---Details-->
|
||||
<div id="event_details" class="w-100">
|
||||
<h4>
|
||||
<a href="{% url 'event_detail' event.pk %}">
|
||||
<span class="c-inline c-lg-none">{{ event }}</span><span class="c-none c-lg-inline">{{ event.name }}</span>
|
||||
</a>
|
||||
{% if event.dry_hire %}
|
||||
<span class="badge badge-secondary">Dry Hire</span>
|
||||
{% endif %}
|
||||
<br class="c-none c-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="c-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>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
195
RIGS/templates/partials/legacy_event_table.html
Normal file
195
RIGS/templates/partials/legacy_event_table.html
Normal file
@@ -0,0 +1,195 @@
|
||||
{% load namewithnotes from filters %}
|
||||
{% load markdown_tags %}
|
||||
<style>
|
||||
#event_table {
|
||||
display: grid;
|
||||
grid-template-columns: max-content min-content minmax(max-content, 1fr) max-content;
|
||||
column-gap: 1em;
|
||||
}
|
||||
.eventgrid {
|
||||
display: inherit;
|
||||
grid-column: 1/5;
|
||||
grid-template-columns: subgrid;
|
||||
padding: 1em;
|
||||
dt, dd { display: block; float: left; }
|
||||
dt { clear: both; }
|
||||
dd { float: right; }
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.c-none {
|
||||
display: none;
|
||||
}
|
||||
.c-inline {
|
||||
display: inline;
|
||||
}
|
||||
@container (width <= 500px) {
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@container (width <= 700px) {
|
||||
#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, .c-md-none {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@container (width > 700px) {
|
||||
.c-lg-block {
|
||||
display: block;
|
||||
}
|
||||
.c-lg-inline {
|
||||
display: inline;
|
||||
}
|
||||
.c-lg-none, .c-md-none {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</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 c-none c-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="c-inline c-lg-none">{{ event }}</span><span class="c-none c-lg-inline">{{ event.name }}</span>
|
||||
</a>
|
||||
{% if event.dry_hire %}
|
||||
<span class="badge badge-secondary">Dry Hire</span>
|
||||
{% endif %}
|
||||
<br class="c-none c-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="c-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>
|
||||
@@ -4,15 +4,44 @@
|
||||
{% block content %}
|
||||
<div class="row align-items-center justify-content-between py-2 align-middle">
|
||||
<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>
|
||||
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">
|
||||
{% button 'new' 'event_create' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not request.GET.legacy %}
|
||||
|
||||
{% if not request.GET.hide_cancelled %}
|
||||
<a href="?hide_cancelled=true" class="btn btn-primary mr-3">Hide cancelled</a>
|
||||
{% else %}
|
||||
<a href="." class="btn btn-primary mr-3">Show cancelled</a>
|
||||
{% endif %}
|
||||
|
||||
<a href="?legacy=true" class="btn btn-secondary">Legacy rigboard</a>
|
||||
{% else %}
|
||||
<a href="." class="btn btn-secondary">New rigboard</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if request.GET.legacy %}
|
||||
<div class="alert alert-warning">
|
||||
<strong>Warning:</strong> The legacy rigboard is being deprecated and will be removed in the future. Please use the
|
||||
new rigboard.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div style="container-type: inline-size;">
|
||||
{% include 'partials/event_table.html' %}
|
||||
{% if request.GET.legacy %}
|
||||
{% include 'partials/legacy_event_table.html' %}
|
||||
{% else %}
|
||||
{% include 'partials/event_table.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -16,14 +16,14 @@ class Rigboard(BasePage):
|
||||
URL_TEMPLATE = reverse('rigboard')
|
||||
|
||||
_add_item_selector = (By.XPATH, "//a[contains(@class,'btn-primary') and contains(., 'New')]")
|
||||
_event_row_locator = (By.ID, 'event_row')
|
||||
_event_row_locator = (By.CLASS_NAME, "event-row")
|
||||
|
||||
def add(self):
|
||||
self.find_element(*self._add_item_selector).click()
|
||||
|
||||
class EventListRow(Region):
|
||||
_event_number_locator = (By.ID, "event_number")
|
||||
_event_dates_locator = (By.ID, "event_dates")
|
||||
_event_dates_locator = (By.CLASS_NAME, "event-dates")
|
||||
_event_details_locator = (By.ID, "event_details")
|
||||
_event_mic_locator = (By.ID, "event_mic")
|
||||
|
||||
|
||||
@@ -91,8 +91,8 @@ class TestRigboard(BaseRigboardTest):
|
||||
# self.live_server_url + '/event/create/', self.driver.current_url)
|
||||
|
||||
def test_event_order(self):
|
||||
self.assertIn(self.testEvent.start_date.strftime('%a %d/%m/%Y'), self.page.events[0].dates)
|
||||
self.assertIn(self.testEvent2.start_date.strftime('%a %d/%m/%Y'), self.page.events[1].dates)
|
||||
self.assertIn(self.testEvent.start_date.strftime('%-d %b %Y'), self.page.events[0].dates)
|
||||
self.assertIn(self.testEvent2.start_date.strftime('%-d %b %Y'), self.page.events[1].dates)
|
||||
|
||||
def test_add_button(self):
|
||||
self.page.add()
|
||||
@@ -530,10 +530,11 @@ class TestCalendar(BaseRigboardTest):
|
||||
self.page.toggle_filter('cancelled')
|
||||
self.page.toggle_filter('provisional')
|
||||
self.page.toggle_filter('confirmed')
|
||||
self.page.toggle_filter('only_mic')
|
||||
|
||||
# and then check the url is correct
|
||||
self.assertIn(
|
||||
"rigs.ics?rig=false&non-rig=false&dry-hire=false&cancelled=true&provisional=false&confirmed=false",
|
||||
"rigs.ics?rig=false&non-rig=false&dry-hire=false&cancelled=true&provisional=false&confirmed=false&only_mic=true",
|
||||
self.page.cal_url)
|
||||
|
||||
# Awesome - all seems to work
|
||||
|
||||
@@ -24,6 +24,7 @@ class CalendarICS(ICalFeed):
|
||||
# Rig = 'rig' = True
|
||||
# Provisional = 'provisional' = True
|
||||
# Confirmed/Booked = 'confirmed' = True
|
||||
# Only MIC = 'mic' = False
|
||||
|
||||
def get_object(self, request, *args, **kwargs):
|
||||
params = {}
|
||||
@@ -35,6 +36,9 @@ class CalendarICS(ICalFeed):
|
||||
params['cancelled'] = request.GET.get('cancelled', 'false') == 'true'
|
||||
params['provisional'] = request.GET.get('provisional', 'true') == 'true'
|
||||
params['confirmed'] = request.GET.get('confirmed', 'true') == 'true'
|
||||
params['only_mic'] = request.GET.get('only_mic', 'false') == 'true'
|
||||
|
||||
params['user'] = kwargs['user']
|
||||
|
||||
return params
|
||||
|
||||
@@ -73,6 +77,9 @@ class CalendarICS(ICalFeed):
|
||||
|
||||
filter = filter & typeFilters & statusFilters
|
||||
|
||||
if params['only_mic']:
|
||||
filter = filter & Q(mic=params['user'])
|
||||
|
||||
return models.Event.objects.filter(filter).order_by('-start_date').select_related('person', 'organisation',
|
||||
'venue', 'mic')
|
||||
|
||||
|
||||
@@ -41,8 +41,13 @@ class RigboardIndex(generic.TemplateView):
|
||||
# get super context
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
objects = models.Event.objects.current_events()
|
||||
|
||||
if self.request.GET.get('hide_cancelled', False):
|
||||
objects = objects.exclude(status=models.Event.CANCELLED)
|
||||
|
||||
# call out method to get current events
|
||||
context['events'] = models.Event.objects.current_events().select_related('riskassessment', 'invoice').prefetch_related('checklists')
|
||||
context['events'] = objects.select_related('riskassessment', 'invoice').prefetch_related('checklists')
|
||||
context['page_title'] = "Rigboard"
|
||||
return context
|
||||
|
||||
|
||||
@@ -244,6 +244,7 @@ class TestSupplierList(AutoLoginTest):
|
||||
|
||||
self.page.set_query("")
|
||||
self.page.search()
|
||||
time.sleep(1)
|
||||
self.assertTrue(len(self.page.suppliers) == 7)
|
||||
|
||||
self.page.set_query("This is not a supplier")
|
||||
|
||||
662
package-lock.json
generated
662
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
99
pyproject.toml
Normal file
99
pyproject.toml
Normal file
@@ -0,0 +1,99 @@
|
||||
[project]
|
||||
name = "pyrigs"
|
||||
version = "0.1.0"
|
||||
description = "A Django-based event booking system designed for use by TEC PA and Lighting"
|
||||
readme = "README.md"
|
||||
requires-python = "~=3.10.0"
|
||||
dependencies = [
|
||||
"ansicolors~=1.1.8",
|
||||
"asgiref~=3.3.1",
|
||||
"backports.tempfile~=1.0",
|
||||
"backports.weakref~=1.0.post1",
|
||||
"beautifulsoup4~=4.9.3",
|
||||
"Brotli~=1.0.9",
|
||||
"cachetools~=4.2.1",
|
||||
"chardet~=4.0.0",
|
||||
"configparser~=5.0.1",
|
||||
"contextlib2~=0.6.0.post1",
|
||||
"cssselect~=1.1.0",
|
||||
"cssutils~=1.0.2",
|
||||
"dj-database-url~=0.5.0",
|
||||
"dj-static~=0.0.6",
|
||||
"Django~=3.2",
|
||||
"django-debug-toolbar~=4.0.0",
|
||||
"django-filter~=2.4.0",
|
||||
"django-ical~=1.7.1",
|
||||
"django-recurrence~=1.10.3",
|
||||
"django-registration-redux~=2.9",
|
||||
"django-reversion~=3.0.9",
|
||||
"django-widget-tweaks~=1.4.8",
|
||||
"django-htmlmin~=0.11.0",
|
||||
"envparse",
|
||||
"gunicorn~=22.0.0",
|
||||
"icalendar~=4.0.7",
|
||||
"idna~=3.7",
|
||||
"Markdown~=3.3.3",
|
||||
"msgpack~=1.0.2",
|
||||
"pep517~=0.9.1",
|
||||
"Pillow~=10.0.1",
|
||||
"premailer~=3.7.0",
|
||||
"progress~=1.5",
|
||||
"psutil~=5.8.0",
|
||||
"psycopg2-binary",
|
||||
"Pygments~=2.15.0",
|
||||
"pyparsing~=2.4.7",
|
||||
"PyPDF2~=1.27.5",
|
||||
"PyPOM~=2.2.4",
|
||||
"python-dateutil~=2.8.1",
|
||||
"pytoml~=0.1.21",
|
||||
"pytz~=2020.5",
|
||||
"reportlab",
|
||||
"requests~=2.32.3",
|
||||
"retrying~=1.3.3",
|
||||
"simplejson~=3.17.2",
|
||||
"six~=1.15.0",
|
||||
"soupsieve~=2.1",
|
||||
"sqlparse~=0.5.0",
|
||||
"static3~=0.7.0",
|
||||
"svg2rlg~=0.3",
|
||||
"tini~=3.0.1",
|
||||
"tornado~=6.3",
|
||||
"urllib3~=1.26.19",
|
||||
"whitenoise~=5.2.0",
|
||||
"yolk~=0.4.3",
|
||||
"zipp~=3.4.0",
|
||||
"zope.component~=4.6.2",
|
||||
"zope.deferredimport~=4.3.1",
|
||||
"zope.deprecation~=4.4.0",
|
||||
"zope.event~=4.5.0",
|
||||
"zope.hookable~=5.0.1",
|
||||
"zope.proxy~=4.3.5",
|
||||
"zope.schema~=6.0.1",
|
||||
"sentry-sdk",
|
||||
"diff-match-patch",
|
||||
"python-barcode",
|
||||
"django-hCaptcha",
|
||||
"importlib-metadata",
|
||||
"django-hcaptcha",
|
||||
"z3c.rml",
|
||||
"pikepdf",
|
||||
"django-queryable-properties",
|
||||
"django-mass-edit",
|
||||
"selenium~=4.9.1",
|
||||
"zope.interface",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pycodestyle~=2.9.1",
|
||||
"coveralls",
|
||||
"django-coverage-plugin",
|
||||
"pytest-cov",
|
||||
"pytest-django",
|
||||
"pluggy",
|
||||
"pytest-splinter",
|
||||
"pytest",
|
||||
"pytest-reverse",
|
||||
"pytest-xdist[psutil]",
|
||||
"PyPOM[splinter]",
|
||||
]
|
||||
@@ -13,6 +13,10 @@
|
||||
<meta name="theme-color" content="#3853a4">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fontdiner+Swanky&display=swap" rel="stylesheet">
|
||||
|
||||
<link rel="icon" type="image/png" href="{% static 'imgs/pyrigs-avatar.png' %}">
|
||||
<link rel="apple-touch-icon" href="{% static 'imgs/pyrigs-avatar.png' %}">
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<label for="supervisor" class="col-sm-2 col-form-label">Supervisor</label>
|
||||
<select name="supervisor" id="supervisor_id" class="selectpicker col-sm-10" data-live-search="true" data-sourceurl="{% url 'api_secure' model='profile' %}?fields=first_name,last_name,initials" required data-noclear="true">
|
||||
{% if supervisor %}
|
||||
<select name="supervisor" id="supervisor_id" class="selectpicker col-sm-10" data-live-search="true"
|
||||
data-sourceurl="{% url 'api_secure' model='profile' %}?fields=first_name,last_name,initials" required
|
||||
data-noclear="true">
|
||||
{% if supervisor %}
|
||||
<option value="{{form.supervisor.value}}" selected>{{ supervisor }}</option>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<option value="{{request.user.pk}}" selected>{{ request.user }}</option>
|
||||
</select>
|
||||
|
||||
@@ -17,8 +17,8 @@ def select_super(page, supervisor):
|
||||
assert page.supervisor_selector.is_open
|
||||
page.supervisor_selector.search(supervisor.name[:-6])
|
||||
time.sleep(2) # Slow down for javascript
|
||||
page.supervisor_selector.set_option(supervisor.name, True)
|
||||
assert page.supervisor_selector.options[0].selected
|
||||
page.supervisor_selector.toggle()
|
||||
|
||||
|
||||
def test_add_qualification(logged_in_browser, live_server, trainee, supervisor, training_item):
|
||||
@@ -40,6 +40,7 @@ def test_add_qualification(logged_in_browser, live_server, trainee, supervisor,
|
||||
page.item_selector.toggle()
|
||||
|
||||
select_super(page, supervisor)
|
||||
page.supervisor_selector.toggle()
|
||||
|
||||
page.submit()
|
||||
assert page.success
|
||||
|
||||
@@ -126,6 +126,9 @@
|
||||
<label class="checkbox-inline ml-lg-2">
|
||||
<input type="checkbox" value="confirmed" data-default="true" checked> Confirmed/Booked
|
||||
</label>
|
||||
<label class="checkbox-inline ml-lg-2">
|
||||
<input type="checkbox" value="only_mic" data-default="false" > Only MIC
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</dd>
|
||||
|
||||
Reference in New Issue
Block a user