2
2
from netbox .views import generic
3
3
from django .db .models import Count
4
4
from . import forms , models , tables , filtersets
5
+ from django .views .generic import View
6
+ from django .contrib .auth .mixins import PermissionRequiredMixin
7
+ from django .shortcuts import render
8
+ import datetime
9
+ import calendar
10
+ from django .utils .safestring import mark_safe
11
+ from django .db .models import Q
12
+ from django .conf import settings
5
13
6
14
# Circuit Maintenance Views
7
15
class CircuitMaintenanceView (generic .ObjectView ):
@@ -55,6 +63,139 @@ class CircuitMaintenanceNotificationsDeleteView(generic.ObjectDeleteView):
55
63
class CircuitMaintenanceNotificationView (generic .ObjectView ):
56
64
queryset = models .CircuitMaintenanceNotifications .objects .all ()
57
65
66
+
67
+ class Calendar (calendar .HTMLCalendar ):
68
+ def __init__ (self , year = None , month = None ):
69
+ self .year = year
70
+ self .month = month
71
+ super (Calendar , self ).__init__ ()
72
+
73
+ def suffix (self , day ):
74
+ if 4 <= day <= 20 or 24 <= day <= 30 :
75
+ return "th"
76
+ else :
77
+ return ["st" , "nd" , "rd" ][day % 10 - 1 ]
78
+
79
+ def custom_strftime (self , format , t ):
80
+ return t .strftime (format ).replace ('SU' , str (t .day ) + self .suffix (t .day ))
81
+
82
+ def formatmonthname (self , theyear , themonth ) :
83
+ return f"<h1>{ calendar .month_name [themonth ]} { theyear } </h1>"
84
+
85
+ def prev_month (self ,month ):
86
+ if month == 1 :
87
+ return 12
88
+ else :
89
+ return month - 1
90
+
91
+ def next_month (self , month ):
92
+ if month == 12 :
93
+ return 1
94
+ else :
95
+ return month + 1
96
+
97
+ def prev_year (self , month , year ):
98
+ if month == 1 :
99
+ return year - 1
100
+ elif month == 12 :
101
+ return year + 1
102
+ else :
103
+ return year
104
+
105
+ def next_year (self , month , year ):
106
+ if month == 1 :
107
+ return year - 1
108
+ elif month == 12 :
109
+ return year + 1
110
+ else :
111
+ return year
112
+
113
+ def formatday (self , day , weekday , events ):
114
+ """
115
+ Return a day as a table cell.
116
+ """
117
+ events_from_day = events .filter (Q (start__day = day ) | Q (end__day = day ))
118
+ events_html = "<ul>"
119
+ for event in events_from_day :
120
+ if events_html != '<ul>' :
121
+ events_html += '<br><br>'
122
+
123
+ # Format time of the event
124
+ if self .custom_strftime ('SU' , event .start ) == self .custom_strftime ('SU' , event .end ):
125
+ event_time = f'{ self .custom_strftime ('%H:%M' , event .start )} - { self .custom_strftime ('%H:%M' , event .end )} '
126
+ else :
127
+ event_time = f'{ self .custom_strftime ('SU %H:%M' , event .start )} - { self .custom_strftime ('SU %H:%M' , event .end )} '
128
+
129
+ # Add the event to the day
130
+ events_html += f'<span class="badge text-bg-{ event .get_status_color ()} "><a href="{ event .get_absolute_url ()} ">{ event_time } <br>{ event .name } <br>{ event .provider } - { event .status } <br>{ event .impact_count } Impacted</a></span>'
131
+ events_html += "</ul>"
132
+
133
+ if day == 0 :
134
+ return '<td> </td>'
135
+ else :
136
+ return '<td class="%s"><strong>%d</strong>%s</td>' % (self .cssclasses [weekday ], day , events_html )
137
+
138
+ def formatweek (self , theweek , events ):
139
+ """
140
+ Return a complete week as a table row.
141
+ """
142
+ week = '' .join (self .formatday (d , wd , events ) for (d , wd ) in theweek )
143
+ return '<tr>%s</tr>' % week
144
+
145
+ def formatmonth (self , theyear , themonth ):
146
+ events = models .CircuitMaintenance .objects .filter (Q (start__month = themonth ) | Q (end__month = themonth )).annotate (impact_count = Count ('impact' ))
147
+ v = []
148
+ a = v .append
149
+ a ('<table class="table">' )
150
+ a ('\n ' )
151
+ a (self .formatmonthname (theyear , themonth ))
152
+ a ('\n ' )
153
+ a (self .formatweekheader ())
154
+ a ('\n ' )
155
+ for week in self .monthdays2calendar (theyear , themonth ):
156
+ a (self .formatweek (week , events ))
157
+ a ('\n ' )
158
+ a ('</table>' )
159
+ a ('\n ' )
160
+ return '' .join (v )
161
+
162
+
58
163
# CircuitMaintenanceSchedule
59
- class CircuitMaintenanceScheduleView (generic .ObjectView ):
60
- queryset = models .CircuitMaintenance .objects .all ()
164
+ class CircuitMaintenanceScheduleView (View ):
165
+ template_name = 'netbox_circuitmaintenance/calendar.html'
166
+
167
+
168
+ def get (self , request ):
169
+
170
+ curr_month = datetime .date .today ()
171
+
172
+ # Check if we have a month and year in the URL
173
+ if request .GET and 'month' in request .GET :
174
+ month = int (request .GET ["month" ])
175
+ year = int (request .GET ["year" ])
176
+
177
+ else :
178
+ month = curr_month .month
179
+ year = curr_month .year
180
+
181
+ # Load calendar
182
+ cal = Calendar ()
183
+ html_calendar = cal .formatmonth (year , month )
184
+ html_calendar = html_calendar .replace ('<td ' , '<td width="300" height="150"' )
185
+
186
+ return render (
187
+ request ,
188
+ self .template_name ,
189
+ {
190
+ "calendar" : mark_safe (html_calendar ),
191
+ "this_month" : curr_month .month ,
192
+ "this_year" : curr_month .year ,
193
+ "month" : month ,
194
+ "year" : year ,
195
+ "next_month" : cal .next_month (month ),
196
+ "next_year" : cal .next_year (month , year ),
197
+ "prev_month" : cal .prev_month (month ),
198
+ "prev_year" : cal .prev_year (month , year ),
199
+ "basepath" : settings .BASE_PATH ,
200
+ }
201
+ )
0 commit comments