rebelstuff

Keep track of your stuff
git clone https://git.ce9e.org/rebelstuff.git

commit
d0d33aa74c50b9d51dd84aace2afe8107a3ae7fa
parent
e5ed192844d2d7ab0a5437d658eaf8ad92c57ee5
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2020-02-29 12:15
grid-based calendar view

Diffstat

M rebelstuff/admin.py 5 +++++
A rebelstuff/templates/rebelstuff/calendar.html 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A rebelstuff/templatetags/__init__.py 0
A rebelstuff/templatetags/rebelstuff.py 26 ++++++++++++++++++++++++++
M rebelstuff/urls.py 6 ++++++
A rebelstuff/views.py 36 ++++++++++++++++++++++++++++++++++++

6 files changed, 161 insertions, 0 deletions


diff --git a/rebelstuff/admin.py b/rebelstuff/admin.py

@@ -1,3 +1,5 @@
   -1     1 import datetime
   -1     2 
    1     3 from django.conf import settings
    2     4 from django.contrib.auth.admin import UserAdmin
    3     5 from django.contrib.auth import models as auth_models
@@ -6,10 +8,13 @@ from django.utils.translation import gettext_lazy as _
    6     8 
    7     9 from . import models
    8    10 
   -1    11 today = datetime.date.today()
   -1    12 
    9    13 
   10    14 class Site(admin.AdminSite):
   11    15     site_header = 'RebelStuff'
   12    16     site_title = 'RebelStuff'
   -1    17     site_url = '/calendar/%i/%i/' % (today.year, today.month)
   13    18     index_title = _('Home')
   14    19 
   15    20 

diff --git a/rebelstuff/templates/rebelstuff/calendar.html b/rebelstuff/templates/rebelstuff/calendar.html

@@ -0,0 +1,88 @@
   -1     1 {% extends "admin/base_site.html" %}
   -1     2 {% load static i18n rebelstuff %}
   -1     3 
   -1     4 {% block content %}
   -1     5     <style>
   -1     6         .calendar {
   -1     7             width: 100%;
   -1     8         }
   -1     9         .calendar tr > :first-child {
   -1    10             width: 0;
   -1    11             text-align: start;
   -1    12             vertical-align: top;
   -1    13         }
   -1    14         .calendar thead th {
   -1    15             text-align: center;
   -1    16         }
   -1    17         .calendar-grid {
   -1    18             display: grid;
   -1    19             grid-auto-flow: dense;
   -1    20             grid-template-columns: repeat({{ date_list|length }}, 1fr);
   -1    21         }
   -1    22         .calendar-link {
   -1    23             display: block;
   -1    24             color: inherit;
   -1    25             text-decoration: none;
   -1    26             padding: 0.2em;
   -1    27         }
   -1    28         .calendar-row.collapsed .calendar-link {
   -1    29             display: none;
   -1    30         }
   -1    31         .calendar-item {
   -1    32             border: 1px solid;
   -1    33         }
   -1    34         .calendar-button {
   -1    35             background: none;
   -1    36             border: 0;
   -1    37             padding: 0;
   -1    38             font: inherit;
   -1    39         }
   -1    40     </style>
   -1    41 
   -1    42     <script>
   -1    43         document.addEventListener('click', function(event) {
   -1    44             if (event.target.matches('.calendar-button')) {
   -1    45                 var row = event.target.closest('.calendar-row');
   -1    46                 row.classList.toggle('collapsed');
   -1    47             }
   -1    48         });
   -1    49     </script>
   -1    50 
   -1    51     <ul class="object-tools">
   -1    52         <li><a href="{% url 'calendar' prev.year prev.month %}">{% trans 'Previous month' %}</a></li>
   -1    53         <li><a href="{% url 'calendar' next.year next.month %}">{% trans 'Next month' %}</a></li>
   -1    54     </ul>
   -1    55 
   -1    56     <table class="calendar">
   -1    57         <thead>
   -1    58             <tr>
   -1    59                 <th></th>
   -1    60                 <th>
   -1    61                     <div class="calendar-grid">
   -1    62                         {% for date in date_list %}
   -1    63                             <time title="{{ date|date }}">{{ date.day }}</time>
   -1    64                         {% endfor %}
   -1    65                     </div>
   -1    66                 </th>
   -1    67             </tr>
   -1    68         </thead>
   -1    69         <tbody>
   -1    70             {% for stuff in stuff_list %}
   -1    71                 <tr class="calendar-row collapsed">
   -1    72                     <th><button type="button" class="calendar-button" title="Expand/Collapse">{{ stuff.name }}</button></th>
   -1    73                     <td>
   -1    74                         <div class="calendar-grid" style="grid-template-rows: repeat({{ stuff.amount }}, 1fr)">
   -1    75                             {% for item in stuff|month_bookingitem_list:date_list %}
   -1    76                                 {% for i in item.amount|range %}
   -1    77                                     <div class="calendar-item" style="grid-column-start: {{ item.start.day }}; grid-column-end: {{ item.end.day }}; border-color: red">
   -1    78                                         <a class="calendar-link" href="{% url 'admin:rebelstuff_booking_change' item.booking.id %}">{{ item.booking.name }}</a>
   -1    79                                     </div>
   -1    80                                 {% endfor %}
   -1    81                             {% endfor %}
   -1    82                         </div>
   -1    83                     </td>
   -1    84                 </tr>
   -1    85             {% endfor %}
   -1    86         </tbody>
   -1    87     </table>
   -1    88 {% endblock %}

diff --git a/rebelstuff/templatetags/__init__.py b/rebelstuff/templatetags/__init__.py

diff --git a/rebelstuff/templatetags/rebelstuff.py b/rebelstuff/templatetags/rebelstuff.py

@@ -0,0 +1,26 @@
   -1     1 from django import template
   -1     2 from django.db.models import Case, When, Value, F
   -1     3 
   -1     4 register = template.Library()
   -1     5 
   -1     6 
   -1     7 @register.filter('range')
   -1     8 def _range(n):
   -1     9     return range(n)
   -1    10 
   -1    11 
   -1    12 @register.filter
   -1    13 def month_bookingitem_list(stuff, date_list):
   -1    14     return stuff.bookingitem_set.filter(
   -1    15         booking__start__lte=date_list[-1],
   -1    16         booking__end__gte=date_list[0],
   -1    17     ).annotate(
   -1    18         start=Case(
   -1    19             When(booking__start__lt=date_list[0], then=Value(date_list[0])),
   -1    20             default=F('booking__start'),
   -1    21         ),
   -1    22         end=Case(
   -1    23             When(booking__end__gt=date_list[-1], then=Value(date_list[-1])),
   -1    24             default=F('booking__end'),
   -1    25         ),
   -1    26     )

diff --git a/rebelstuff/urls.py b/rebelstuff/urls.py

@@ -1,7 +1,13 @@
    1     1 from django.urls import path
    2     2 
   -1     3 from . import views
    3     4 from .admin import site
    4     5 
    5     6 urlpatterns = [
    6     7     path('', site.urls),
   -1     8     path(
   -1     9         'calendar/<int:year>/<int:month>/',
   -1    10         views.CalendarView.as_view(),
   -1    11         name='calendar',
   -1    12     ),
    7    13 ]

diff --git a/rebelstuff/views.py b/rebelstuff/views.py

@@ -0,0 +1,36 @@
   -1     1 import datetime
   -1     2 from django.contrib.auth.mixins import PermissionRequiredMixin
   -1     3 from django.utils.translation import gettext_lazy as _
   -1     4 from django.views.generic.base import TemplateView
   -1     5 
   -1     6 from .models import Stuff
   -1     7 
   -1     8 
   -1     9 class CalendarView(PermissionRequiredMixin, TemplateView):
   -1    10     permission_required = 'rebelstuff.view_booking'
   -1    11     template_name = 'rebelstuff/calendar.html'
   -1    12 
   -1    13     def get_context_data(self, **kwargs):
   -1    14         context = super().get_context_data(**kwargs)
   -1    15         context['stuff_list'] = Stuff.objects.all()
   -1    16 
   -1    17         year = self.kwargs['year']
   -1    18         month = self.kwargs['month']
   -1    19         context['date_list'] = []
   -1    20         for i in range(31):
   -1    21             try:
   -1    22                 context['date_list'].append(datetime.date(year, month, i + 1))
   -1    23             except ValueError:
   -1    24                 break
   -1    25 
   -1    26         day = datetime.timedelta(days=1)
   -1    27         context['prev'] = context['date_list'][0] - day
   -1    28         context['next'] = context['date_list'][-1] + day
   -1    29 
   -1    30         # for django admin template
   -1    31         context['title'] = _('Calendar')
   -1    32         context['site_header'] = 'RebelStuff'
   -1    33         context['site_title'] = 'RebelStuff'
   -1    34         context['has_permission'] = True
   -1    35 
   -1    36         return context