From 8cade512d10e42a91a90f411e274ebb18870c2d3 Mon Sep 17 00:00:00 2001 From: FreneticScribbler Date: Fri, 18 Nov 2022 16:16:06 +0000 Subject: [PATCH] Initial work at reimplementing the calendar in python Buhby fullcalendar --- RIGS/models.py | 33 +++- RIGS/templates/calendar.html | 220 +++++------------------ RIGS/templates/partials/event_table.html | 16 +- RIGS/urls.py | 8 +- RIGS/utils.py | 65 +++++++ RIGS/views/rigboard.py | 21 ++- package-lock.json | 12 -- package.json | 1 - 8 files changed, 156 insertions(+), 220 deletions(-) create mode 100644 RIGS/utils.py diff --git a/RIGS/models.py b/RIGS/models.py index 9049d210..501ebc87 100644 --- a/RIGS/models.py +++ b/RIGS/models.py @@ -401,6 +401,12 @@ class BaseEvent(models.Model, RevisionMixin): errdict['end_time'] = ['Unless you\'ve invented time travel, the event can\'t finish before it has started.'] return errdict + @property + def get_html_url(self): + return f'{self}' + + def __str__(self): + return f"{self.display_id}: {self.name}" @reversion.register(follow=['items']) class Event(BaseEvent): @@ -502,13 +508,29 @@ class Event(BaseEvent): else: return bool(self.purchase_order) + @property + def color(self): + if self.cancelled: + return "secondary" + elif not self.is_rig: + return "info" + elif not self.mic: + return "danger" + elif self.confirmed and self.authorised: + if self.dry_hire or self.riskassessment: + return "success" + else: + return "warning" + else: + return "warning" + objects = EventManager() def get_absolute_url(self): return reverse('event_detail', kwargs={'pk': self.pk}) - def __str__(self): - return f"{self.display_id}: {self.name}" + def get_edit_url(self): + return reverse('event_update', kwargs={'pk': self.pk}) def clean(self): errdict = super.clean() @@ -581,6 +603,13 @@ class Subhire(BaseEvent): def display_id(self): return f"S{self.pk:05d}" + @property + def color(self): + return "purple" + + def get_edit_url(self): + return reverse('subhire_update', kwargs={'pk': self.pk}) + class InvoiceManager(models.Manager): def outstanding_invoices(self): diff --git a/RIGS/templates/calendar.html b/RIGS/templates/calendar.html index 7bf854cf..3e83ea6a 100644 --- a/RIGS/templates/calendar.html +++ b/RIGS/templates/calendar.html @@ -4,194 +4,56 @@ {% block title %}Calendar{% endblock %} {% block css %} - -{% endblock %} + {% endblock %} {% block content %} -
-
-
- -
-
-
- - - - -
-
- -
-
- - -
-
- - - -
-
-
-
-
-
-
-
-
+
+ Previous Month + Next Month +
+{{ calendar }} {% endblock %} diff --git a/RIGS/templates/partials/event_table.html b/RIGS/templates/partials/event_table.html index 4262b58b..efdd50b7 100644 --- a/RIGS/templates/partials/event_table.html +++ b/RIGS/templates/partials/event_table.html @@ -12,21 +12,7 @@ {% for event in events %} - + {{ event.display_id }} diff --git a/RIGS/urls.py b/RIGS/urls.py index cd0d11ce..89313377 100644 --- a/RIGS/urls.py +++ b/RIGS/urls.py @@ -43,12 +43,8 @@ urlpatterns = [ # Rigboard path('rigboard/', login_required(views.RigboardIndex.as_view()), name='rigboard'), - path('rigboard/calendar/', login_required()(views.WebCalendar.as_view()), + re_path(r'^rigboard/calendar/$', login_required()(views.WebCalendar.as_view()), name='web_calendar'), - re_path(r'^rigboard/calendar/(?P(month|week|day))/$', - login_required()(views.WebCalendar.as_view()), name='web_calendar'), - re_path(r'^rigboard/calendar/(?P(month|week|day))/(?P(\d{4}-\d{2}-\d{2}))/$', - login_required()(views.WebCalendar.as_view()), name='web_calendar'), path('rigboard/archive/', RedirectView.as_view(permanent=True, pattern_name='event_archive')), @@ -77,7 +73,7 @@ urlpatterns = [ path('subhire/create/', permission_required_with_403('RIGS.add_event')(views.SubhireCreate.as_view()), name='subhire_create'), path('subhire//edit', views.SubhireEdit.as_view(), - name='subhire_edit'), + name='subhire_update'), # Event H&S diff --git a/RIGS/utils.py b/RIGS/utils.py new file mode 100644 index 00000000..99ad2971 --- /dev/null +++ b/RIGS/utils.py @@ -0,0 +1,65 @@ +from datetime import datetime, timedelta, date +import calendar +from calendar import HTMLCalendar +from RIGS.models import BaseEvent, Event, Subhire + +class Calendar(HTMLCalendar): + def __init__(self, year=None, month=None): + self.year = year + self.month = month + super(Calendar, self).__init__() + + # formats a day as a td + # filter events by day + def formatday(self, day, events, subhires): + events_per_day = events.filter(start_date__day=day) + subhires_per_day = subhires.filter(start_date__day=day) + d = '' + for event in events_per_day: + d += f'{event.get_html_url}
' + for subhire in subhires_per_day: + d += f'{subhire.get_html_url}
' + + if day != 0: + return f"{day}
    {d}
" + return '' + + # formats a week as a tr + def formatweek(self, theweek, events, subhires): + week = '' + for d, weekday in theweek: + week += self.formatday(d, events, subhires) + return f' {week} ' + + # formats a month as a table + # filter events by year and month + def formatmonth(self, withyear=True): + events = Event.objects.filter(start_date__year=self.year, start_date__month=self.month) + subhires = Subhire.objects.filter(start_date__year=self.year, start_date__month=self.month) + + cal = f'\n' + cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n' + cal += f'{self.formatweekheader()}\n' + for week in self.monthdays2calendar(self.year, self.month): + cal += f'{self.formatweek(week, events, subhires)}\n' + return cal + + +def get_date(req_day): + if req_day: + year, month = (int(x) for x in req_day.split('-')) + return date(year, month, day=1) + return datetime.today() + +def prev_month(d): + first = d.replace(day=1) + prev_month = first - timedelta(days=1) + month = 'month=' + str(prev_month.year) + '-' + str(prev_month.month) + return month + +def next_month(d): + days_in_month = calendar.monthrange(d.year, d.month)[1] + last = d.replace(day=days_in_month) + next_month = last + timedelta(days=1) + month = 'month=' + str(next_month.year) + '-' + str(next_month.month) + return month diff --git a/RIGS/views/rigboard.py b/RIGS/views/rigboard.py index 099f016b..eb8066ba 100644 --- a/RIGS/views/rigboard.py +++ b/RIGS/views/rigboard.py @@ -17,12 +17,13 @@ from django.template.loader import get_template from django.urls import reverse from django.urls import reverse_lazy from django.utils import timezone +from django.utils.html import mark_safe from django.utils.decorators import method_decorator from django.views import generic from PyRIGS import decorators from PyRIGS.views import OEmbedView, is_ajax, ModalURLMixin, PrintView, get_related -from RIGS import models, forms +from RIGS import models, forms, utils __author__ = 'ghost' @@ -40,14 +41,24 @@ class RigboardIndex(generic.TemplateView): return context -class WebCalendar(generic.TemplateView): +class WebCalendar(generic.ListView): + model = models.Event template_name = 'calendar.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['view'] = kwargs.get('view', '') - context['date'] = kwargs.get('date', '') - # context['page_title'] = "Calendar" + + # use today's date for the calendar + d = utils.get_date(self.request.GET.get('month', None)) + context['prev_month'] = utils.prev_month(d) + context['next_month'] = utils.next_month(d) + + # Instantiate our calendar class with today's year and date + cal = utils.Calendar(d.year, d.month) + + # Call the formatmonth method, which returns our calendar as a table + html_cal = cal.formatmonth(withyear=True) + context['calendar'] = mark_safe(html_cal) return context diff --git a/package-lock.json b/package-lock.json index 25c3b3e1..80fe0b13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,6 @@ "requires": true, "packages": { "": { - "name": "PyRIGS", "version": "1.0.0", "license": "Custom", "dependencies": { @@ -19,7 +18,6 @@ "clipboard": "^2.0.8", "cssnano": "^5.0.13", "easymde": "^2.16.1", - "fullcalendar": "^5.10.1", "gulp": "^4.0.2", "gulp-concat": "^2.6.1", "gulp-flatten": "^0.4.0", @@ -2943,11 +2941,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fullcalendar": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-5.10.1.tgz", - "integrity": "sha512-0jgDxiWRuC36MzAUK3+Equmu4R0+vAPEtttsXLX9GNNDUHEZ5HjcH+dUtWut4vlJtxGJgVZ+eZ76/7qhcu+RMA==" - }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -11350,11 +11343,6 @@ "dev": true, "optional": true }, - "fullcalendar": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-5.10.1.tgz", - "integrity": "sha512-0jgDxiWRuC36MzAUK3+Equmu4R0+vAPEtttsXLX9GNNDUHEZ5HjcH+dUtWut4vlJtxGJgVZ+eZ76/7qhcu+RMA==" - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", diff --git a/package.json b/package.json index 05024e49..2f35e9b3 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "clipboard": "^2.0.8", "cssnano": "^5.0.13", "easymde": "^2.16.1", - "fullcalendar": "^5.10.1", "gulp": "^4.0.2", "gulp-concat": "^2.6.1", "gulp-flatten": "^0.4.0",