mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-10-07 21:15:33 +00:00
* 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
176 lines
7.9 KiB
HTML
176 lines
7.9 KiB
HTML
{% extends 'base_rigs.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Calendar{% endblock %}
|
|
|
|
{% block css %}
|
|
<link href="{% static 'css/main.css' %}" rel='stylesheet' />
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script src="{% static 'js/moment.js' %}"></script>
|
|
<script src="{% static 'js/main.js' %}"></script>
|
|
<script>
|
|
viewToUrl = {
|
|
'timeGridWeek':'week',
|
|
'timeGridDay':'day',
|
|
'dayGridMonth':'month'
|
|
}
|
|
viewFromUrl = {
|
|
'week':'timeGridWeek',
|
|
'day':'timeGridDay',
|
|
'month':'dayGridMonth'
|
|
}
|
|
var calendar; //Need to access it from jquery ready
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var calendarEl = document.getElementById('calendar');
|
|
|
|
calendar = new FullCalendar.Calendar(calendarEl, {
|
|
firstDay: 1,
|
|
themeSystem: 'standard',
|
|
aspectRatio: 1.5,
|
|
eventTimeFormat: {
|
|
'hour': '2-digit',
|
|
'minute': '2-digit',
|
|
'hour12': false
|
|
},
|
|
headerToolbar: false,
|
|
editable: false,
|
|
dayMaxEventRows: true, // allow "more" link when too many events
|
|
events: function(fetchInfo, successCallback, failureCallback) {
|
|
var params = new URLSearchParams({
|
|
start: moment(fetchInfo.startStr).format("YYYY-MM-DD[T]HH:mm:ss"),
|
|
end: moment(fetchInfo.endStr).format("YYYY-MM-DD[T]HH:mm:ss")
|
|
});
|
|
fetch('/api/event?' + params, {credentials: 'same-origin'})
|
|
.then(function (response) { return response.json(); })
|
|
.then(function (doc) {
|
|
var events = [];
|
|
colours = {
|
|
'Provisional': '#FFE89B',
|
|
'Confirmed': '#3AB54A' ,
|
|
'Booked': '#3AB54A' ,
|
|
'Cancelled': 'grey' ,
|
|
'non-rig': '#25AAE2'
|
|
};
|
|
doc.forEach(function (item) {
|
|
end = item.latest
|
|
allDay = false
|
|
if(end.indexOf("T") < 0){ //If latest does not contain a time
|
|
end = moment(end + " 23:59").format("YYYY-MM-DD[T]HH:mm:ss")
|
|
allDay = true
|
|
}
|
|
|
|
thisEvent = {
|
|
'start': item.earliest,
|
|
'end': end,
|
|
'className': 'modal-href',
|
|
'title': item.title,
|
|
'url': item.url,
|
|
'allDay': allDay
|
|
}
|
|
|
|
if(item.is_rig===true || item.status === "Cancelled"){
|
|
thisEvent['color'] = colours[item.status];
|
|
}else{
|
|
thisEvent['color'] = colours['non-rig'];
|
|
}
|
|
events.push(thisEvent);
|
|
});
|
|
successCallback(events);
|
|
})
|
|
.catch(failureCallback);
|
|
},
|
|
datesSet: function(info) {
|
|
var view = info.view;
|
|
// Set the title of the view
|
|
document.getElementById('calendar-header').textContent = view.title;
|
|
|
|
// Enable/Disable "Today" button as required
|
|
//Today is within the current view
|
|
document.getElementById('today-button').disabled = moment().isBetween(view.currentStart, view.currentEnd);
|
|
|
|
// Set active view select button
|
|
var buttons = {
|
|
dayGridMonth: document.getElementById('month-button'),
|
|
timeGridWeek: document.getElementById('week-button'),
|
|
timeGridDay: document.getElementById('day-button')
|
|
};
|
|
Object.keys(buttons).forEach(function (type) {
|
|
buttons[type].classList.toggle('active', type === view.type);
|
|
});
|
|
history.replaceState(null,null,"{% url 'web_calendar' %}"+viewToUrl[view.type]+'/'+moment(view.currentStart).format('YYYY-MM-DD')+'/');
|
|
}
|
|
});
|
|
calendar.render();
|
|
});
|
|
ready(function() {
|
|
// set some button listeners
|
|
var click = function (id, fn) { document.getElementById(id).addEventListener('click', fn); };
|
|
click('next-button', function(){ calendar.next(); });
|
|
click('prev-button', function(){ calendar.prev(); });
|
|
click('today-button', function(){ calendar.today(); });
|
|
click('month-button', function(){ calendar.changeView('dayGridMonth'); });
|
|
click('week-button', function(){ calendar.changeView('timeGridWeek'); });
|
|
click('day-button', function(){ calendar.changeView('timeGridDay'); });
|
|
var dateInput = document.getElementById('go-to-date-input');
|
|
var dateButton = document.getElementById('go-to-date-button');
|
|
dateInput.addEventListener('change', function(){
|
|
dateButton.disabled = !moment(dateInput.value).isValid();
|
|
});
|
|
dateButton.addEventListener('click', function(){
|
|
day = moment(dateInput.value);
|
|
if(day.isValid()){
|
|
calendar.gotoDate(day.format("YYYY-MM-DD"));
|
|
} else{
|
|
alert('Invalid Date');
|
|
}
|
|
});
|
|
{% if view and date %}
|
|
// Go to the initial settings, if they're valid
|
|
view = viewFromUrl['{{view}}'];
|
|
calendar.changeView(view);
|
|
day = moment('{{date}}');
|
|
if(day.isValid()){
|
|
calendar.gotoDate(day.format("YYYY-MM-DD"));
|
|
} else{
|
|
console.log('Supplied date is invalid - using default')
|
|
}
|
|
{% endif %}
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="row">
|
|
<div class="col-sm-12 d-flex flex-wrap justify-content-between align-items-center">
|
|
<div>
|
|
<span id="calendar-header" class="h2"></span>
|
|
</div>
|
|
<div class="d-flex align-items-center flex-wrap gap-2 btn-page my-3">
|
|
<div class="input-group w-auto">
|
|
<input type="date" class="form-control" id="go-to-date-input" placeholder="Go to date...">
|
|
<button class="btn btn-success" id="go-to-date-button" type="button" disabled>Go!</button>
|
|
</div>
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-primary" id="today-button">Today</button>
|
|
</div>
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-secondary" id="prev-button"><span class="fas fa-chevron-left"></span></button>
|
|
<button type="button" class="btn btn-secondary" id="next-button"><span class="fas fa-chevron-right"></span></button>
|
|
</div>
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-light" id="month-button">Month</button>
|
|
<button type="button" class="btn btn-light" id="week-button">Week</button>
|
|
<button type="button" class="btn btn-light" id="day-button">Day</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<div id='calendar'></div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|