mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-10-10 14:52:53 +00:00
Bootstrap 5 & remove jQuery (#661)
* build: move frontend assets to Bootstrap 5.3 and Tom Select * feat: migrate templates and scripts to Bootstrap 5, dropping jQuery Templates - Rename Bootstrap 4 classes and data attributes (data-bs-*, ms-/me-/ps-/pe-, text-start/end, form-group -> mb-3, input-group wrappers removed, badges, custom controls -> form-check/form-select, media -> d-flex, btn-close, ...) - Dark mode now uses Bootstrap 5.3 colour modes (data-bs-theme on <html>), set from <head> to avoid a flash of the light theme - Remove the Bootstrap 4 /bootstrap/ demo page - Contextual table classes (table-success etc.) still work as plain backgrounds for the rigboard key JavaScript - Remove jQuery: src.js/interaction.js and every inline template script are rewritten in plain JS on top of small helpers (helpers.js, bundled with Bootstrap into jpop.js so inline scripts can use them) - Replace bootstrap-select/ajax-bootstrap-select with Tom Select. The remote search now sends the `q` parameter and reads `text`, which is what the API actually uses (the old picker sent `term` and read `label`) - HTML fragments are fetched with an X-Requested-With header so views keep rendering their modal variants, and fetched scripts are re-executed - Remove the Bootstrap 4 plugin script includes * fix: stop rigboard header buttons stretching to full width under Bootstrap 5 * fix: restore dark-mode brand colours and contextual table colours under Bootstrap 5 * fix: brighten dark-mode links and make coloured card outlines visible * fix: calendar layout and grid borders, navbar search button width, guard missing modal links * fix: readable text in dark-mode Tom Select inputs and placeholders, restore form-control column widths * build: split the Dockerfile into cached stages with prod and dev targets * deploy: make compose.yml development-only with live reload, and document it * fix: keep badge text colour for links inside badges * fix: restore table-bordered grid lines in dark mode * fix: include Bootstrap's progress styles and keep progress labels readable
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<div class="card-header">Associated Organisations</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
{% for organisation,count in object.organisations %}
|
||||
<a class="list-group-item list-group-item-action" href="{% url 'organisation_detail' organisation.pk %}">{{ organisation.pk|stringformat:"05d" }} | {{ organisation.name }} <span class="badge badge-secondary" title="{{count}} events with {{object.name}} for {{organisation.name}}">{{count}}</span></a>
|
||||
<a class="list-group-item list-group-item-action" href="{% url 'organisation_detail' organisation.pk %}">{{ organisation.pk|stringformat:"05d" }} | {{ organisation.name }} <span class="badge text-bg-secondary" title="{{count}} events with {{object.name}} for {{organisation.name}}">{{count}}</span></a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="card-header">Associated People</div>
|
||||
<div class="list-group list-group-flush">
|
||||
{% for person,count in object.persons %}
|
||||
<a class="list-group-item list-group-item-action" href="{% url 'person_detail' person.pk %}">{{ person.pk|stringformat:"05d" }} | {{ person.name }} <span class="badge badge-secondary" title="{{count}} events with {{person.name}} for {{object.name}}">{{count}}</span></a>
|
||||
<a class="list-group-item list-group-item-action" href="{% url 'person_detail' person.pk %}">{{ person.pk|stringformat:"05d" }} | {{ person.name }} <span class="badge text-bg-secondary" title="{{count}} events with {{person.name}} for {{object.name}}">{{count}}</span></a>
|
||||
{% empty %}
|
||||
<div class="card-body">None</div>
|
||||
{% endfor %}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<td>{% if crew.end_time %}
|
||||
{{crew.end_time}}
|
||||
{% else %}
|
||||
<span class="text-success fas fa-clock" data-toggle="tooltip"
|
||||
<span class="text-success fas fa-clock" data-bs-toggle="tooltip"
|
||||
title="This person is currently checked into this event"></span>{% endif %}
|
||||
</td>
|
||||
<td>{% if crew.end_time %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<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>
|
||||
<h5 class="py-3"><a class="btn btn-info" data-bs-toggle="collapse" href="#values" aria-expanded="false" aria-controls="values">View Threshold Values</a></h5>
|
||||
<div class="row collapse" id="values">
|
||||
<div class="col-md-6 col-sm-12">
|
||||
<table class="table table-bordered">
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{{ object.venue|namewithnotes:'venue_detail' }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if object.parking_and_access or object.riskassessment.parking_and_access %}<span class="badge badge-warning">Additional Access Requirements</span>{% endif %}
|
||||
{% if object.parking_and_access or object.riskassessment.parking_and_access %}<span class="badge text-bg-warning">Additional Access Requirements</span>{% endif %}
|
||||
</dd>
|
||||
{% if object.venue %}
|
||||
<dt class="col-sm-6">Venue Notes</dt>
|
||||
@@ -85,7 +85,7 @@
|
||||
{% else %}
|
||||
<a href="{% url 'event_thread' object.pk %}" class="btn btn-primary" title="Create Forum Thread" target="_blank"><span
|
||||
class="fas fa-plus"></span> <span
|
||||
class="hidden-xs">Create Forum Thread</span></a>
|
||||
class="d-none d-sm-inline">Create Forum Thread</span></a>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<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">
|
||||
<h5 class="mb-0 me-3">
|
||||
<a href="{% url 'event_detail' event.pk %}"
|
||||
class="{{ header_text }} text-decoration-underline fw-bold">
|
||||
<strong>{{ event.display_id }}</strong> - {{ event.name }}
|
||||
@@ -106,7 +106,7 @@
|
||||
<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">
|
||||
class="rounded-circle me-1" width="32" height="32">
|
||||
<span>
|
||||
{% if perms.RIGS.view_profile %}
|
||||
<a href="{% url 'profile_detail' event.mic.pk %}" class="modal-href">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% if object.event_size == 2 %}
|
||||
<span class="badge badge-danger p-2 my-3">Large Event</span>
|
||||
<span class="badge text-bg-danger p-2 my-3">Large Event</span>
|
||||
{% elif object.event_size == 1 %}
|
||||
<span class="badge badge-warning p-2 my-3">Medium Event</span>
|
||||
<span class="badge text-bg-warning p-2 my-3">Medium Event</span>
|
||||
{%else%}
|
||||
<span class="badge badge-success p-2 my-3">Small Event</span>
|
||||
<span class="badge text-bg-success p-2 my-3">Small Event</span>
|
||||
{%endif%}
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
<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>
|
||||
<span class="badge text-bg-{% 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 %}
|
||||
{% if event.purchase_order %}
|
||||
<span class="badge badge-success">PO: Received</span>
|
||||
<span class="badge text-bg-success">PO: Received</span>
|
||||
{% elif event.authorised %}
|
||||
<span class="badge badge-success">Authorisation: Complete <span class="fas fa-check"></span></span>
|
||||
<span class="badge text-bg-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 %}
|
||||
<span class="badge badge-warning"> Authorisation: Issue <span class="fas fa-exclamation-circle"></span></span>
|
||||
<span class="badge text-bg-warning"> Authorisation: Issue <span class="fas fa-exclamation-circle"></span></span>
|
||||
{% elif event.auth_request_to %}
|
||||
<span class="badge badge-info"> Authorisation: Sent <span class="fas fa-paper-plane"></span></span>
|
||||
<span class="badge text-bg-info"> Authorisation: Sent <span class="fas fa-paper-plane"></span></span>
|
||||
{% else %}
|
||||
<span class="badge badge-danger">Authorisation: <span class="fas fa-times"></span></span>
|
||||
<span class="badge text-bg-danger">Authorisation: <span class="fas fa-times"></span></span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if not event.dry_hire %}
|
||||
{% if event.riskassessment %}
|
||||
<a href="{{ event.riskassessment.get_absolute_url }}"><span class="badge badge-success">RA: <span class="fas fa-check{% if event.riskassessment.reviewed_by %}-double{%endif%}"></span></a>
|
||||
<a href="{{ event.riskassessment.get_absolute_url }}"><span class="badge text-bg-success">RA: <span class="fas fa-check{% if event.riskassessment.reviewed_by %}-double{%endif%}"></span></a>
|
||||
{% else %}
|
||||
<span class="badge badge-danger">RA: <span class="fas fa-times"></span></span>
|
||||
<span class="badge text-bg-danger">RA: <span class="fas fa-times"></span></span>
|
||||
{% endif %}
|
||||
{% if event.has_checklist %}
|
||||
<span class="badge badge-success">Checklist: <span class="fas fa-check"></span> {% if event.checklists.count > 1 %}({{event.checklists.count}}){% endif %}</span>
|
||||
<span class="badge text-bg-success">Checklist: <span class="fas fa-check"></span> {% if event.checklists.count > 1 %}({{event.checklists.count}}){% endif %}</span>
|
||||
{% else %}
|
||||
<span class="badge badge-danger">Checklist: <span class="fas fa-times"></span></span>
|
||||
<span class="badge text-bg-danger">Checklist: <span class="fas fa-times"></span></span>
|
||||
{% endif %}
|
||||
{% if event.has_power %}
|
||||
<span class="badge badge-success">Power Record: <span class="fas fa-check"></span> {% if event.power_tests.count > 1 %}({{event.power_tests.count}}){% endif %}</span>
|
||||
<span class="badge text-bg-success">Power Record: <span class="fas fa-check"></span> {% if event.power_tests.count > 1 %}({{event.power_tests.count}}){% endif %}</span>
|
||||
{% else %}
|
||||
<span class="badge badge-danger">Power Record: <span class="fas fa-times"></span></span>
|
||||
<span class="badge text-bg-danger">Power Record: <span class="fas fa-times"></span></span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if perms.RIGS.view_invoice %}
|
||||
{% if event.invoice %}
|
||||
{% if event.invoice.void %}
|
||||
<span class="badge badge-secondary">Invoice: Void</span>
|
||||
<span class="badge text-bg-secondary">Invoice: Void</span>
|
||||
{% elif event.invoice.is_closed %}
|
||||
<span class="badge badge-success">Invoice: Paid</span>
|
||||
<span class="badge text-bg-success">Invoice: Paid</span>
|
||||
{% else %}
|
||||
<span class="badge badge-warning">Invoice: Outstanding</span>
|
||||
<span class="badge text-bg-warning">Invoice: Outstanding</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="badge badge-info">Invoice: Not Generated</span>
|
||||
<span class="badge text-bg-info">Invoice: Not Generated</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if event.parking_and_access %}
|
||||
<span class="badge badge-warning">Addititional Access Requirements</span>
|
||||
<span class="badge text-bg-warning">Addititional Access Requirements</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<br/>
|
||||
{% endfor %}
|
||||
<a href="{% url 'event_ec' event.pk %}" class="btn btn-info mt-2"><span class="fas fa-paperclip"></span> <span
|
||||
class="hidden-xs">Create</span></a>
|
||||
class="d-none d-sm-inline">Create</span></a>
|
||||
<hr>
|
||||
<h5>Power Test Records:</h5>
|
||||
{% for record in event.power_tests.all %}
|
||||
@@ -22,6 +22,6 @@
|
||||
<br/>
|
||||
{% endfor %}
|
||||
<a href="{% url 'event_pt' event.pk %}" class="btn btn-info mt-2"><span class="fas fa-paperclip"></span> <span
|
||||
class="hidden-xs">Create</span></a>
|
||||
class="d-none d-sm-inline">Create</span></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
{% include 'partials/review_status.html' %}
|
||||
{% elif event != None %}
|
||||
<a href="{% url create event.pk %}" class="btn btn-info"><span class="fas fa-paperclip"></span> <span
|
||||
class="hidden-xs">Create</span></a>
|
||||
class="d-none d-sm-inline">Create</span></a>
|
||||
{% endif %}
|
||||
|
||||
@@ -3,29 +3,27 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4>{{ object.name|default:"New Event" }}</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form id="item-form">
|
||||
<div class="modal-body">
|
||||
<div class="form-group form-row">
|
||||
<div class="mb-3 row g-2">
|
||||
<label for="item_name" class="col-sm-2 col-form-label">Item Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" placeholder="Item Name" class="form-control" required maxlength="255"
|
||||
id="item_name"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group form-row" data-toggle="tooltip" title="A detailed description of the kit. MD enabled.">
|
||||
<div class="mb-3 row g-2" data-bs-toggle="tooltip" title="A detailed description of the kit. MD enabled.">
|
||||
<label for="item_description" class="col-sm-2 col-form-label">Description</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea type="text" placeholder="Description" class="form-control md-enabled"
|
||||
id="item_description" rows="8"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="row g-2">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group form-row">
|
||||
<div class="mb-3 row g-2">
|
||||
<label for="item_quantity" class="col-sm-4 col-form-label">Quantity</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" placeholder="Quantity" class="form-control" required
|
||||
@@ -34,12 +32,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group form-row">
|
||||
<div class="mb-3 row g-2">
|
||||
<label for="item_cost" class="col-sm-4 col-form-label">Cost</label>
|
||||
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend"><span class="input-group-text">£</span></div>
|
||||
<span class="input-group-text">£</span>
|
||||
<input type="number" placeholder="Cost" class="form-control" required
|
||||
min="-99999999.99" max="99999999.99" step="0.01"
|
||||
id="item_cost"/>
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
<td>£<span class="sub-total" data-subtotal="{{item.total_cost}}">{{item.total_cost|floatformat:2}}</span></td>
|
||||
{% endif %}
|
||||
{% if edit %}
|
||||
<td class="vert-align text-right">
|
||||
<td class="vert-align text-end">
|
||||
<div class="btn-group" role="group" aria-label="Action buttons">
|
||||
<button type="button" class="item-edit btn btn-sm btn-warning"
|
||||
data-pk="{{item.pk}}"
|
||||
data-toggle="modal" data-target="#itemModal">
|
||||
data-modal-target="#itemModal">
|
||||
<span class="fas fa-edit"></span>
|
||||
</button>
|
||||
<button type="button" class="item-delete btn btn-sm btn-danger"
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
<th scope="col">Sub-total</th>
|
||||
{% endif %}
|
||||
{% if edit %}
|
||||
<th scope="col" class="text-right align-self-start">
|
||||
<th scope="col" class="text-end align-self-start">
|
||||
<button type="button" class="btn btn-success btn-sm item-add"
|
||||
data-toggle="modal"
|
||||
data-target="#itemModal">
|
||||
data-modal-target="#itemModal">
|
||||
<i class="fas fa-plus"></i> Add Item
|
||||
</button>
|
||||
</th>
|
||||
@@ -65,11 +64,11 @@
|
||||
<td class="quantity"></td>
|
||||
<td>£<span class="sub-total"></span></td>
|
||||
{% if edit %}
|
||||
<td class="vert-align text-right">
|
||||
<td class="vert-align text-end">
|
||||
<div class="btn-group" role="group" aria-label="Action buttons">
|
||||
<button type="button" class="item-edit btn btn-sm btn-warning"
|
||||
data-pk="{{item.pk}}"
|
||||
data-toggle="modal" data-target="#itemModal">
|
||||
data-modal-target="#itemModal">
|
||||
<span class="fas fa-edit"></span>
|
||||
</button>
|
||||
<button type="button" class="item-delete btn btn-sm btn-danger"
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
}
|
||||
</style>
|
||||
<div id="event_table">
|
||||
<div class="eventgrid grid-header font-weight-bold">
|
||||
<div class="eventgrid grid-header fw-bold">
|
||||
<div id="event_number">#</div>
|
||||
<div id="event_dates">Dates & Times</div>
|
||||
<div>Event Details</div>
|
||||
@@ -117,29 +117,29 @@
|
||||
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>
|
||||
<div class="fw-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>
|
||||
<dt class="fw-normal">Meet:</dt>
|
||||
<dd class="text-nowrap fw-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>
|
||||
<dt class="fw-normal">Access:</dt>
|
||||
<dd class="text-nowrap fw-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" }}
|
||||
<dt class="fw-normal">Start:</dt>
|
||||
<dd class="text-nowrap fw-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" }}
|
||||
<dt class="fw-normal">End:</dt>
|
||||
<dd class="text-nowrap fw-bold text-lg-right">{{ event.end_date|date:"D d/m/Y" }}
|
||||
{% if event.has_end_time %}
|
||||
{{ event.end_time|date:"H:i" }}
|
||||
{% endif %}
|
||||
@@ -154,7 +154,7 @@
|
||||
<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>
|
||||
<span class="badge text-bg-secondary">Dry Hire</span>
|
||||
{% endif %}
|
||||
<br class="c-none c-lg-inline">
|
||||
{% if event.venue %}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% if object.reviewed_by %}
|
||||
<span class="badge badge-success py-2">Reviewed by <a href="{% url 'profile_detail' object.reviewed_by.pk %}">{{object.reviewed_by}}</a> at {{object.reviewed_at}}</span>
|
||||
<span class="badge text-bg-success py-2">Reviewed by <a href="{% url 'profile_detail' object.reviewed_by.pk %}">{{object.reviewed_by}}</a> at {{object.reviewed_at}}</span>
|
||||
{% elif perm %}
|
||||
<a class="btn btn-success my-2" href="{% url review object.pk %}">Mark Reviewed</a>
|
||||
{% else %}
|
||||
<span class="badge badge-danger py-2">Not reviewed</span>
|
||||
<span class="badge text-bg-danger py-2">Not reviewed</span>
|
||||
{% endif %}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
class="col-8 control-label">{{ formitem.help_text|safe }}</label>
|
||||
<div class="col-4 pb-3" id="{{ formitem.0.id_for_label|slice:'-2' }}">
|
||||
{% for radio in formitem %}
|
||||
<div class="custom-control custom-radio">
|
||||
<div class="form-check">
|
||||
{{ radio.tag }}
|
||||
<label class="custom-control-label" for="{{ radio.id_for_label }}">{{ radio.choice_label }}</label>
|
||||
<label class="form-check-label" for="{{ radio.id_for_label }}">{{ radio.choice_label }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user