mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-30 11:52:17 +00:00
Entirely new concept
This commit is contained in:
@@ -390,15 +390,25 @@ class BaseEvent(models.Model, RevisionMixin):
|
|||||||
else:
|
else:
|
||||||
return endDate
|
return endDate
|
||||||
|
|
||||||
|
@property
|
||||||
|
def length(self):
|
||||||
|
start = self.earliest_time
|
||||||
|
if isinstance(self.earliest_time, datetime.datetime):
|
||||||
|
start = self.earliest_time.date()
|
||||||
|
end = self.latest_time
|
||||||
|
if isinstance(self.latest_time, datetime.datetime):
|
||||||
|
end = self.latest_time.date()
|
||||||
|
return (end - start).days
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
errdict = {}
|
errdict = {}
|
||||||
if self.end_date and self.start_date > self.end_date:
|
if self.end_date and self.start_date > self.end_date:
|
||||||
errdict['end_date'] = ['Unless you\'ve invented time travel, the event can\'t finish before it has started.']
|
errdict['end_date'] = ["Unless you've invented time travel, the event can't finish before it has started."]
|
||||||
|
|
||||||
startEndSameDay = not self.end_date or self.end_date == self.start_date
|
startEndSameDay = not self.end_date or self.end_date == self.start_date
|
||||||
hasStartAndEnd = self.has_start_time and self.has_end_time
|
hasStartAndEnd = self.has_start_time and self.has_end_time
|
||||||
if startEndSameDay and hasStartAndEnd and self.start_time > self.end_time:
|
if startEndSameDay and hasStartAndEnd and self.start_time > self.end_time:
|
||||||
errdict['end_time'] = ['Unless you\'ve invented time travel, the event can\'t finish before it has started.']
|
errdict['end_time'] = ["Unless you've invented time travel, the event can't finish before it has started."]
|
||||||
return errdict
|
return errdict
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@@ -606,6 +616,10 @@ class Subhire(BaseEvent):
|
|||||||
def get_edit_url(self):
|
def get_edit_url(self):
|
||||||
return reverse('subhire_update', kwargs={'pk': self.pk})
|
return reverse('subhire_update', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def earliest_time(self):
|
||||||
|
return find_earliest_event_time(self, [])
|
||||||
|
|
||||||
|
|
||||||
class InvoiceManager(models.Manager):
|
class InvoiceManager(models.Manager):
|
||||||
def outstanding_invoices(self):
|
def outstanding_invoices(self):
|
||||||
|
|||||||
@@ -28,27 +28,70 @@
|
|||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<style>
|
<style>
|
||||||
.calendar tr, .calendar td {
|
.week {
|
||||||
border: 1px solid grey;
|
display:grid;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
grid-auto-flow: dense;
|
||||||
|
grid-gap: 2px 10px;
|
||||||
|
border: 1px solid black;
|
||||||
|
height: 8em;
|
||||||
|
align-content: start;
|
||||||
}
|
}
|
||||||
.date {
|
|
||||||
float: right;
|
.day {
|
||||||
|
display:contents;
|
||||||
}
|
}
|
||||||
.days {
|
.day-label {
|
||||||
height: 20vh;
|
grid-row-start: 1;
|
||||||
|
text-align: right;
|
||||||
|
margin:0;
|
||||||
|
font-size: 1em !important;
|
||||||
|
height: 1em;
|
||||||
}
|
}
|
||||||
td {
|
|
||||||
width: calc(100% / 7);
|
.week-day, .day-label, .event {
|
||||||
|
padding: 4px 10px;
|
||||||
}
|
}
|
||||||
th {
|
|
||||||
margin: 0.5em;
|
.event {
|
||||||
border-bottom: 3px solid grey;
|
background-color: #CCC;
|
||||||
|
font-size: 0.8em !important;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.event-end {
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-start {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.day:nth-child(1) > .event { grid-column-start: 1; }
|
||||||
|
.day:nth-child(2) > .event { grid-column-start: 2; }
|
||||||
|
.day:nth-child(3) > .event { grid-column-start: 3; }
|
||||||
|
.day:nth-child(4) > .event { grid-column-start: 4; }
|
||||||
|
|
||||||
|
[data-span="1"] { grid-column-end: span 1; }
|
||||||
|
[data-span="2"] { grid-column-end: span 2; }
|
||||||
|
[data-span="3"] { grid-column-end: span 3; }
|
||||||
|
[data-span="4"] { grid-column-end: span 4; }
|
||||||
|
[data-span="5"] { grid-column-end: span 5; }
|
||||||
|
[data-span="6"] { grid-column-end: span 6; }
|
||||||
|
[data-span="7"] { grid-column-end: span 7; }
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit !important;
|
||||||
|
text-decoration: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center mb-1">
|
||||||
<a class="btn btn-info col-2" href="{% url 'web_calendar' %}?{{ prev_month }}"><span class="fas fa-chevron-left"></span> Previous Month</a>
|
<a class="btn btn-info col-2" href="{% url 'web_calendar' %}?{{ prev_month }}"><span class="fas fa-chevron-left"></span> Previous Month</a>
|
||||||
<div class="input-group col-4">
|
<div class="input-group col-4">
|
||||||
<input type="date" id="go-to-date-input" placeholder="Go to date...">
|
<input type="date" id="go-to-date-input" placeholder="Go to date...">
|
||||||
@@ -60,7 +103,23 @@ th {
|
|||||||
<a class="btn btn-info mx-2 col-2" href="{% url 'web_calendar' %}?{{ next_month }}"><span class="fas fa-chevron-right"></span> Next Month</a>
|
<a class="btn btn-info mx-2 col-2" href="{% url 'web_calendar' %}?{{ next_month }}"><span class="fas fa-chevron-right"></span> Next Month</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-responsive-md pt-2">
|
<div class="week" style="height: 2em;">
|
||||||
{{ calendar }}
|
<div class="week-day">Monday</div>
|
||||||
|
<div class="week-day">Tuesday</div>
|
||||||
|
<div class="week-day">Wednesday</div>
|
||||||
|
<div class="week-day">Thursday</div>
|
||||||
|
<div class="week-day">Friday</div>
|
||||||
|
<div class="week-day">Saturday</div>
|
||||||
|
<div class="week-day">Sunday</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% for week in weeks %}
|
||||||
|
<div class="week">
|
||||||
|
{% for day in week %}
|
||||||
|
<div class="day" id="{{day.0}}">
|
||||||
|
<h3 class="day-label text-muted">{% if day.0 != 0 %}{{day.0}}{% endif %}</h3>
|
||||||
|
{{ day.2|safe }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ class Calendar(HTMLCalendar):
|
|||||||
# formats a day as a td
|
# formats a day as a td
|
||||||
# filter events by day
|
# filter events by day
|
||||||
def formatday(self, day, events, subhires):
|
def formatday(self, day, events, subhires):
|
||||||
events_per_day = events.order_by("start_date").filter(start_date__day__lte=day, end_date__day__gte=day)
|
|
||||||
subhires_per_day = subhires.order_by("start_date").filter(start_date__day__lte=day, end_date__day__gte=day)
|
|
||||||
d = get_html(events_per_day, day) + get_html(subhires_per_day, day)
|
d = get_html(events_per_day, day) + get_html(subhires_per_day, day)
|
||||||
if day != 0:
|
if day != 0:
|
||||||
return f"<td valign='top' class='days'><span class='date'>{day}</span><br>{d}</td>"
|
return f"<td valign='top' class='days'><span class='date'>{day}</span><br>{d}</td>"
|
||||||
@@ -44,17 +43,25 @@ class Calendar(HTMLCalendar):
|
|||||||
week += self.formatday(d, events, subhires)
|
week += self.formatday(d, events, subhires)
|
||||||
return f'<tr> {week} </tr>'
|
return f'<tr> {week} </tr>'
|
||||||
|
|
||||||
# formats a month as a table
|
|
||||||
# filter events by year and month
|
|
||||||
def formatmonth(self, withyear=True):
|
def formatmonth(self, withyear=True):
|
||||||
events = Event.objects.filter(start_date__year=self.year, start_date__month=self.month)
|
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)
|
subhires = Subhire.objects.filter(start_date__year=self.year, start_date__month=self.month)
|
||||||
|
weeks = self.monthdays2calendar(self.year, self.month)
|
||||||
|
data = []
|
||||||
|
|
||||||
cal = f'<table cellpadding="0" cellspacing="0" class="calendar">\n'
|
for week in weeks:
|
||||||
cal += f'{self.formatweekheader()}\n'
|
weeks_events = []
|
||||||
for week in self.monthdays2calendar(self.year, self.month):
|
for day in week:
|
||||||
cal += f'{self.formatweek(week, events, subhires)}\n'
|
events_per_day = events.order_by("start_date").filter(start_date__day=day[0])
|
||||||
return cal
|
subhires_per_day = subhires.order_by("start_date").filter(start_date__day=day[0])
|
||||||
|
event_html = ""
|
||||||
|
for event in events_per_day:
|
||||||
|
event_html += f"<a href='{event.get_edit_url()}' style='display: contents;'><div class='event event-start event-end bg-{event.color}' data-span='{event.length}'>{event}</div></a>"
|
||||||
|
for sh in subhires_per_day:
|
||||||
|
event_html += f"<div class='event event-start event-end bg-{sh.color}' data-span='{sh.length}'>{sh}</div>"
|
||||||
|
weeks_events.append((day[0], day[1], event_html))
|
||||||
|
data.append(weeks_events)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
def get_date(req_day):
|
def get_date(req_day):
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ class WebCalendar(generic.ListView):
|
|||||||
|
|
||||||
# Call the formatmonth method, which returns our calendar as a table
|
# Call the formatmonth method, which returns our calendar as a table
|
||||||
html_cal = cal.formatmonth(withyear=True)
|
html_cal = cal.formatmonth(withyear=True)
|
||||||
context['calendar'] = mark_safe(html_cal)
|
# context['calendar'] = mark_safe(html_cal)
|
||||||
|
context['weeks'] = html_cal
|
||||||
context['page_title'] = d.strftime("%B %Y")
|
context['page_title'] = d.strftime("%B %Y")
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user