django-handyhelpers 0.3.18__py3-none-any.whl → 0.3.20__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {django_handyhelpers-0.3.18.dist-info → django_handyhelpers-0.3.20.dist-info}/METADATA +2 -2
- {django_handyhelpers-0.3.18.dist-info → django_handyhelpers-0.3.20.dist-info}/RECORD +10 -8
- handyhelpers/__init__.py +1 -1
- handyhelpers/templates/handyhelpers/htmx/bs5/navigation/build_sidebar.htm +9 -0
- handyhelpers/templates/handyhelpers/partials/calendar.htm +126 -0
- handyhelpers/views/calendar.py +104 -0
- handyhelpers/views/htmx.py +3 -2
- {django_handyhelpers-0.3.18.dist-info → django_handyhelpers-0.3.20.dist-info}/LICENSE +0 -0
- {django_handyhelpers-0.3.18.dist-info → django_handyhelpers-0.3.20.dist-info}/WHEEL +0 -0
- {django_handyhelpers-0.3.18.dist-info → django_handyhelpers-0.3.20.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: django-handyhelpers
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.20
|
4
4
|
Summary: A collection of handy utilities to support django operations
|
5
5
|
Home-page: https://github.com/davidslusser/django-handyhelpers
|
6
|
-
Download-URL: https://github.com/davidslusser/django-handyhelpers/archive/0.3.
|
6
|
+
Download-URL: https://github.com/davidslusser/django-handyhelpers/archive/0.3.20.tar.gz
|
7
7
|
Author: David Slusser
|
8
8
|
Author-email: dbslusser@gmail.com
|
9
9
|
License: GPL-3.0
|
@@ -1,4 +1,4 @@
|
|
1
|
-
handyhelpers/__init__.py,sha256=
|
1
|
+
handyhelpers/__init__.py,sha256=K3oKhpJJHJk0Dorla4DSbV2WCL9p9ecv3-AB9tgleLM,406
|
2
2
|
handyhelpers/apps.py,sha256=g6mXn-5BENf48vY_Qz2FhAABJPBB3EIJXlNM33v6-v8,485
|
3
3
|
handyhelpers/checks.py,sha256=8LXb106sIBNV3fNIHDIW-UcixJk8emgbtFkIlKG5ZGM,578
|
4
4
|
handyhelpers/context_processors.py,sha256=31-j4WD-xaJp9JU_VbkbyUyWxI2UuDGW9qA805fEGBs,527
|
@@ -6398,8 +6398,9 @@ handyhelpers/templates/handyhelpers/generic/bs5/partials/pagination_controls.htm
|
|
6398
6398
|
handyhelpers/templates/handyhelpers/htmx/bs5/about_project_modal_body.htm,sha256=H2OhlHSJObkre_PlkJe_A1ybNAPF2VAVmBtl3HLxmgk,1212
|
6399
6399
|
handyhelpers/templates/handyhelpers/htmx/bs5/generic_modal.htm,sha256=Ttvswnu622audzG5Gl7zikY4KB-4cNcVm6wnWJInZAU,658
|
6400
6400
|
handyhelpers/templates/handyhelpers/htmx/bs5/generic_modal_swap.htm,sha256=NOAScjA1R62Shmrf8uRklRa32LU30nhkopU0ccCjz8c,1826
|
6401
|
-
handyhelpers/templates/handyhelpers/htmx/bs5/navigation/build_sidebar.htm,sha256=
|
6401
|
+
handyhelpers/templates/handyhelpers/htmx/bs5/navigation/build_sidebar.htm,sha256=6BuqpRbrChQCVHUEzknVd74vxXpyPf2YYMq1e5LawEU,1757
|
6402
6402
|
handyhelpers/templates/handyhelpers/htmx/bs5/navigation/sidebar_menu_sub_items.htm,sha256=-Hc0qxWK_vWCYW8T52NV7yvnvJA4-cfRdS5DaWWvx9k,152
|
6403
|
+
handyhelpers/templates/handyhelpers/partials/calendar.htm,sha256=4UZMT2CzkoxivpJxNhPshMk6EFb0q_bcZzvQXgRKFzM,5141
|
6403
6404
|
handyhelpers/templates/handyhelpers/report/theme_colors.htm,sha256=Jl31SW6o_2lGctKY2gz9INKFs7REC7FSqLtkqHfLOBY,1164
|
6404
6405
|
handyhelpers/templates/handyhelpers/report/chartjs/annual_progress.html,sha256=M9UISiqHR4HaiMD7f0FXHpOUwfmsgwjA8up1pnkCckU,323
|
6405
6406
|
handyhelpers/templates/handyhelpers/report/chartjs/annual_progress_chart.htm,sha256=HHlHOKsz7-wHPZVDFVil4uYm6caKAj2VoN4kBNs4oQ8,2294
|
@@ -6426,12 +6427,13 @@ handyhelpers/views/__init__.py,sha256=09jR-Yd1mhJqfzzoW5bNTum-KLI35OASqo7-8FQmKI
|
|
6426
6427
|
handyhelpers/views/action.py,sha256=bJZ-F5U6fcoTjxRxkYO1p7-Va4nBet4qfbG5J6WpHyI,1229
|
6427
6428
|
handyhelpers/views/ajax.py,sha256=wbBcl7aORR6OXS9eApdWy1aoFNeYLOJJx4repBVTGZQ,936
|
6428
6429
|
handyhelpers/views/auditlog.py,sha256=uwcLUCbmQf7vIKu9QGpt4bNXuKY79TmPxZLC7ICdjvk,1151
|
6430
|
+
handyhelpers/views/calendar.py,sha256=u3rm8CXYqcFESoNTGUs9Jhi6a8_pcpKCFdIzBYWpISE,3768
|
6429
6431
|
handyhelpers/views/export.py,sha256=45DP5d8L1npo39WqAqYqAnAaNthN5ILyQMIS8WWn85c,3128
|
6430
6432
|
handyhelpers/views/gui.py,sha256=cPGbMu8-dE7MgYleBiPf3YLX_5AsWVtiu1s6MtEDaoo,43358
|
6431
|
-
handyhelpers/views/htmx.py,sha256=
|
6433
|
+
handyhelpers/views/htmx.py,sha256=FWjHj7nexoy0W26LKuTi2HAW6ZiiNhHoNbOYY_apwTQ,6071
|
6432
6434
|
handyhelpers/views/report.py,sha256=1khoo_eEmKLszGEP3sRYqBaKeK-ndbMfahDq7SMRnQI,14898
|
6433
|
-
django_handyhelpers-0.3.
|
6434
|
-
django_handyhelpers-0.3.
|
6435
|
-
django_handyhelpers-0.3.
|
6436
|
-
django_handyhelpers-0.3.
|
6437
|
-
django_handyhelpers-0.3.
|
6435
|
+
django_handyhelpers-0.3.20.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
6436
|
+
django_handyhelpers-0.3.20.dist-info/METADATA,sha256=dVrUNIFPy7rjk5piy5a4yMuy0nIKakvXuZBoZKmsxMs,3327
|
6437
|
+
django_handyhelpers-0.3.20.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
6438
|
+
django_handyhelpers-0.3.20.dist-info/top_level.txt,sha256=qMQVRQqXX1vYNEfuQbwWMu2J-GLo_bfLmF6mtZF5caU,13
|
6439
|
+
django_handyhelpers-0.3.20.dist-info/RECORD,,
|
handyhelpers/__init__.py
CHANGED
@@ -9,6 +9,15 @@ Build dropdown navigations in a sidebar. This is intented to be used with the ha
|
|
9
9
|
{{ item.model_name|title }}
|
10
10
|
</a>
|
11
11
|
<ul id="{{ item.target_id }}" class="sidebar-dropdown list-unstyled collapse" data-bs-parent="#sidebar">
|
12
|
+
{% if item.list_all_url %}
|
13
|
+
<li class="sidebar-link">
|
14
|
+
{% if item.htmx_link is False %}
|
15
|
+
<a href="{{ item.list_all_url}}" class="sidebar-link ms-4">All {{ item.model_name }}</a>
|
16
|
+
{% else %}
|
17
|
+
<a hx-get="{{ item.list_all_url }}" hx-target="#{{ item.htmx_target }}" class="sidebar-link ms-4">All {{ item.model_name }}</a>
|
18
|
+
{% endif %}
|
19
|
+
</li>
|
20
|
+
{% endif %}
|
12
21
|
{% for row in item.queryset %}
|
13
22
|
<li class="sidebar-link">
|
14
23
|
{% if item.link %}
|
@@ -0,0 +1,126 @@
|
|
1
|
+
|
2
|
+
<style>
|
3
|
+
/* Add custom styles if needed */
|
4
|
+
/* Customize the calendar container */
|
5
|
+
.calendar-container {
|
6
|
+
margin-top: 1.5rem;
|
7
|
+
margin-bottom: 1.5rem;
|
8
|
+
padding-left: 3rem;
|
9
|
+
padding-right: 3rem;
|
10
|
+
}
|
11
|
+
/* Customize the navigation links */
|
12
|
+
.nav-links {
|
13
|
+
margin-bottom: 10px;
|
14
|
+
}
|
15
|
+
/* Customize the calendar table */
|
16
|
+
.calendar-table {
|
17
|
+
width: 100%;
|
18
|
+
border-collapse: collapse;
|
19
|
+
}
|
20
|
+
.calendar-table th {
|
21
|
+
border: 1px solid #dee2e6;
|
22
|
+
padding: 8px;
|
23
|
+
text-align: center;
|
24
|
+
height: 1rem; /* Set fixed height for header row cells */
|
25
|
+
}
|
26
|
+
.calendar-table td {
|
27
|
+
border: 1px solid #dee2e6;
|
28
|
+
padding: 8px;
|
29
|
+
text-align: center;
|
30
|
+
width: 80px; /* Set fixed width for all cells except header row */
|
31
|
+
height: 80px; /* Set fixed height for all cells except header row */
|
32
|
+
}
|
33
|
+
/* Highlight today's date with a different background color */
|
34
|
+
.today {
|
35
|
+
background-color: var(--bg-light-subtle) !important; /* Change to your desired background color */
|
36
|
+
}
|
37
|
+
/* Styling for events */
|
38
|
+
.event {
|
39
|
+
background-color: #007bff; /* Bootstrap primary color */
|
40
|
+
color: #fff; /* White text color */
|
41
|
+
padding: 4px;
|
42
|
+
border-radius: 4px;
|
43
|
+
margin-top: 2px;
|
44
|
+
font-size: .75rem;
|
45
|
+
margin-left: .75rem;
|
46
|
+
margin-right: .75rem;
|
47
|
+
{% comment %} cursor: pointer; {% endcomment %}
|
48
|
+
}
|
49
|
+
.cursor-pointer{
|
50
|
+
cursor: pointer;
|
51
|
+
}
|
52
|
+
</style>
|
53
|
+
|
54
|
+
<div class="container-fluid calendar-container">
|
55
|
+
<div class="h2 mt-5 text-primary text-center fw-bold">{{ title }}</div>
|
56
|
+
<div class="h4 mb-3 text-secondary text-center">{{ month_name }} {{ year }}</div>
|
57
|
+
<div class="text-end nav-links">
|
58
|
+
<a
|
59
|
+
{% if use_htmx %}
|
60
|
+
hx-get="{{ today_url }}" hx-target="#body_main"
|
61
|
+
{% else %}
|
62
|
+
href="{{ today_url }}"
|
63
|
+
{% endif %}
|
64
|
+
class="me-3" style="text-decoration: none">
|
65
|
+
today
|
66
|
+
</a>
|
67
|
+
<a
|
68
|
+
{% if use_htmx %}
|
69
|
+
hx-get="{{ prev_month_url }}" hx-target="#body_main"
|
70
|
+
{% else %}
|
71
|
+
href="{{ prev_month_url }}"
|
72
|
+
{% endif %}
|
73
|
+
class="me-2" title="previous month">
|
74
|
+
<i class="fa-solid fa-angle-left"></i>
|
75
|
+
</a>
|
76
|
+
<a
|
77
|
+
{% if use_htmx %}
|
78
|
+
hx-get="{{ next_month_url }}" hx-target="#body_main"
|
79
|
+
{% else %}
|
80
|
+
href="{{ next_month_url }}"
|
81
|
+
{% endif %}
|
82
|
+
class="ms-2" title="next month">
|
83
|
+
<i class="fa-solid fa-angle-right"></i>
|
84
|
+
</a>
|
85
|
+
</div>
|
86
|
+
<table class="table table-bordered calendar-table shadow">
|
87
|
+
<thead>
|
88
|
+
<tr>
|
89
|
+
<th class="bg-light-subtle" scope="col">Mon</th>
|
90
|
+
<th class="bg-light-subtle" scope="col">Tue</th>
|
91
|
+
<th class="bg-light-subtle" scope="col">Wed</th>
|
92
|
+
<th class="bg-light-subtle" scope="col">Thu</th>
|
93
|
+
<th class="bg-light-subtle" scope="col">Fri</th>
|
94
|
+
<th class="bg-light-subtle" scope="col">Sat</th>
|
95
|
+
<th class="bg-light-subtle" scope="col">Sun</th>
|
96
|
+
</tr>
|
97
|
+
</thead>
|
98
|
+
<tbody>
|
99
|
+
{% for week in cal_data %}
|
100
|
+
<tr>
|
101
|
+
{% for day in week %}
|
102
|
+
<td {% if day == today.day and month == today.month and year == today.year %}class="today"{% endif %}>
|
103
|
+
{% if day %}
|
104
|
+
<div class="text-end {% if day == today.day and month == today.month and year == today.year %}fw-bold{% endif %}">{{ day }}</div>
|
105
|
+
{%endif%}
|
106
|
+
{% for event in event_list %}
|
107
|
+
{% if event.date_time.day == day and event.date_time.month == month and event.date_time.year == year %}
|
108
|
+
{% if event_detail_url %}
|
109
|
+
<div class="event hvr-grow d-block cursor-pointer"
|
110
|
+
hx-get="{% url event_detail_url event.pk %}"
|
111
|
+
hx-target="#modal_wrapper"
|
112
|
+
data-bs-toggle="modal"
|
113
|
+
data-bs-target="#modal_wrapper">{{ event }}
|
114
|
+
</div>
|
115
|
+
{% else %}
|
116
|
+
<div class="event">{{ event }}</div>
|
117
|
+
{% endif %}
|
118
|
+
{% endif %}
|
119
|
+
{% endfor %}
|
120
|
+
</td>
|
121
|
+
{% endfor %}
|
122
|
+
</tr>
|
123
|
+
{% endfor %}
|
124
|
+
</tbody>
|
125
|
+
</table>
|
126
|
+
</div>
|
@@ -0,0 +1,104 @@
|
|
1
|
+
import calendar
|
2
|
+
from datetime import date
|
3
|
+
import re
|
4
|
+
|
5
|
+
from django.shortcuts import render
|
6
|
+
from django.views.generic import View
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
class CalendarView(View):
|
11
|
+
""" View to render a monthly calendar and optionally display events.
|
12
|
+
|
13
|
+
class parameters:
|
14
|
+
template_name - template used when rendering partial; defaults to: handyhelpers/partials/calendar.htm
|
15
|
+
event_model - django model representing events
|
16
|
+
event_model_date_field - date or datetime field containing event date
|
17
|
+
event_detail_url - url to use to get event details and display in a modal
|
18
|
+
use_htmx - boolean representing option to use htmx in in today/next month/previous month links
|
19
|
+
|
20
|
+
Usage Example:
|
21
|
+
class MyEventCalendarView(CalendarView):
|
22
|
+
event_model = Event
|
23
|
+
event_model_date_field = "date"
|
24
|
+
event_detail_url = "myapp_:get_event_details"
|
25
|
+
"""
|
26
|
+
title = "Calendar"
|
27
|
+
event_model = None
|
28
|
+
event_model_date_field = None
|
29
|
+
event_detail_url = None
|
30
|
+
template_name = "handyhelpers/partials/calendar.htm"
|
31
|
+
use_htmx = True
|
32
|
+
|
33
|
+
def get_next(self, this_year:int, this_month:int) -> tuple:
|
34
|
+
"""get the year and month of the next month
|
35
|
+
|
36
|
+
Args:
|
37
|
+
this_year (int): year of the currently rendered calendar
|
38
|
+
this_month (int): month of the currently rendered calendar
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
tuple: tuple of integers containing year and month of the next calendar month
|
42
|
+
"""
|
43
|
+
if this_month == 12:
|
44
|
+
return (this_year + 1), 1
|
45
|
+
return this_year, this_month + 1
|
46
|
+
|
47
|
+
def get_previous(self, this_year:int, this_month:int) -> tuple:
|
48
|
+
"""get the year and month of the previous month
|
49
|
+
|
50
|
+
Args:
|
51
|
+
this_year (int): year of the currently rendered calendar
|
52
|
+
this_month (int): month of the currently rendered calendar
|
53
|
+
|
54
|
+
Returns:
|
55
|
+
tuple: tuple of integers containing year and month of the next calendar month
|
56
|
+
"""
|
57
|
+
if this_month == 1:
|
58
|
+
return this_year - 1, 12
|
59
|
+
return this_year, this_month - 1
|
60
|
+
|
61
|
+
def get(self, request, *args, **kwargs):
|
62
|
+
mo = re.search(r"^(/[^/]+/)", request.path)
|
63
|
+
if mo:
|
64
|
+
calendar_url_root = mo.groups()[0]
|
65
|
+
|
66
|
+
today = date.today()
|
67
|
+
year = kwargs.get("year", today.year)
|
68
|
+
month = kwargs.get("month", today.month)
|
69
|
+
if year == 0:
|
70
|
+
year = today.year
|
71
|
+
if month == 0:
|
72
|
+
month = today.month
|
73
|
+
next_year, next_month = self.get_next(year, month)
|
74
|
+
prev_year, prev_month = self.get_previous(year, month)
|
75
|
+
|
76
|
+
today_url = f"{calendar_url_root}{today.year}/{today.month}"
|
77
|
+
prev_month_url = f"{calendar_url_root}{prev_year}/{prev_month}"
|
78
|
+
next_month_url = f"{calendar_url_root}{next_year}/{next_month}"
|
79
|
+
|
80
|
+
cal_data = calendar.monthcalendar(year, month)
|
81
|
+
|
82
|
+
queryset = None
|
83
|
+
if self.event_model:
|
84
|
+
queryset = self.event_model.objects.filter(
|
85
|
+
**{f"{self.event_model_date_field}__year": year,
|
86
|
+
f"{self.event_model_date_field}__month": month,
|
87
|
+
}
|
88
|
+
)
|
89
|
+
|
90
|
+
context = {
|
91
|
+
"cal_data": cal_data,
|
92
|
+
"title": self.title,
|
93
|
+
"year": year,
|
94
|
+
"month": month,
|
95
|
+
"month_name": calendar.month_name[month],
|
96
|
+
"today": today,
|
97
|
+
"event_list": queryset,
|
98
|
+
"use_htmx": self.use_htmx,
|
99
|
+
"event_detail_url": self.event_detail_url,
|
100
|
+
"today_url": today_url,
|
101
|
+
"prev_month_url": prev_month_url,
|
102
|
+
"next_month_url": next_month_url,
|
103
|
+
}
|
104
|
+
return render(request, self.template_name, context)
|
handyhelpers/views/htmx.py
CHANGED
@@ -123,6 +123,7 @@ class BuildModelSidebarNav(HtmxViewMixin, View):
|
|
123
123
|
{"queryset": MyModelOne.objects.filter(enabled=True),
|
124
124
|
"icon": '<i class="fa-solid fa-people-group"></i>',
|
125
125
|
"htmx_link": False,
|
126
|
+
"list_all_url": "list_mymodelones",
|
126
127
|
},
|
127
128
|
]
|
128
129
|
"""
|
@@ -144,7 +145,7 @@ class BuildModelSidebarNav(HtmxViewMixin, View):
|
|
144
145
|
item["link"] = hasattr(queryset.model, "get_absolute_url")
|
145
146
|
if item.get("htmx_link", True) and not item.get("htmx_target", None):
|
146
147
|
item["htmx_target"] = "body_main"
|
147
|
-
|
148
|
+
context = dict(
|
148
149
|
menu_item_list=self.menu_item_list,
|
149
150
|
)
|
150
|
-
return render(request, self.template_name,
|
151
|
+
return render(request, self.template_name, context)
|
File without changes
|
File without changes
|
File without changes
|