Skip to content

Commit

Permalink
A first working version showing a job calendar #171. Fixed #175 fixed #…
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Kraft committed Jan 24, 2025
1 parent 646a186 commit 5ad1bb2
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 260 deletions.
21 changes: 8 additions & 13 deletions odmf/db/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
from traceback import format_exc as traceback
from functools import total_ordering


# from ..tools.mail import EMail
from .base import Base, newid
from .site import Log
from .person import Person
from ..tools.migrate_db import new_column

from logging import getLogger
logger = getLogger(__name__)
Expand All @@ -33,6 +35,8 @@ class Job(Base):
backref=orm.backref('jobs', lazy='dynamic'))
# Marks the job as done
done = sql.Column("done", sql.Boolean, default=False)
# Job duration in days after due
duration: orm.Mapped[int] = new_column(sql.Column(sql.Integer))
# Number of days to repeat this job, if NULL, negetative or zero, the job is not repeated
# The new job is generated when this job is done, due date is the number of days after this due date
repeat = sql.Column(sql.Integer)
Expand All @@ -52,6 +56,7 @@ def __repr__(self):
def __jdict__(self):
return dict(id=self.id,
name=self.name,
type=self.type,
description=self.description,
due=self.due,
donedate=self.donedate,
Expand Down Expand Up @@ -189,16 +194,6 @@ def make_done(self, by, time=None):
msg.extend(errors)
return '\n'.join(msg)

@property
def color(self):
if self.done:
return '#FFF'
dt = (self.due - datetime.now()).days
if dt < 0:
return '#F00'
elif dt == 0:
return '#F80'
elif dt < 2:
return '#8F4'
else:
return '#8F8'
def end(self):
return self.due + timedelta(days=self.duration or 0)

90 changes: 90 additions & 0 deletions odmf/static/templates/job-list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<!DOCTYPE html>

<py:extends href="layout.html" xmlns:py="">
<py:block name="scripts">
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js'></script>
<script>
let calendar;
document.addEventListener('DOMContentLoaded', function() {
let filter = JSON.parse(sessionStorage.getItem('job-filter'))
if (filter) {
$('#filter-persons').val(filter.persons)
$('#filter-types').val(filter.types)
$('#filter-active').prop('checked', filter.onlyactive)
} else {
$('#filter-persons').val(`${user()}`)
$('#filter-active').prop('checked', true)
}
var calendarEl = document.getElementById('calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'listYear',
headerToolbar: { center: 'dayGridMonth,multiMonthYear,listYear' },
events: {
url: "${conf.url('job','json')}",
extraParams: function() {
return {
persons: $('#filter-persons').val(),
types: $('#filter-types').val(),
onlyactive: $('#filter-active').is(':checked')
}
}
}
});
calendar.render();
$('.filter').on('change', event => {
sessionStorage.setItem('job-filter', JSON.stringify(
{
persons: $('#filter-persons').val(),
types: $('#filter-types').val(),
onlyactive: $('#filter-active').is(':checked')
}
))
calendar.refetchEvents()
})
});
</script>
</py:block>
<py:block name="style">
<!-- insert additional styles -->
</py:block>
<py:block name="sidebar">
<!-- insert sidebar content -->
<div class="container-fluid" >
<a class="btn btn-primary w-100 mb-4" href="new">
<i class="fas fa-plus-circle mr-3" />
new job
</a>
</div>
<div class="card m-2">
<div class="card-header">
<i class="fas fa-filter"></i> filter
</div>
<div class="card-body">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input filter" id="filter-active"/>
<label class="custom-control-label" for="filter-active">show only active elements</label>
</div>
<div class="form-group">
<label for="filter-types">types</label>
<select class="select2 form-control filter" id="filter-types" multiple="multiple" name="type[]">
<option py:for="t, in jobtypes" value="${t}">${t}</option>
</select>
</div>
<div class="form-group">
<label for="filter-persons">persons</label>
<select class="select2 form-control filter" id="filter-persons" multiple="multiple" name="person[]">
<option py:for="p in persons" value="${p.username}">${p}</option>
</select>
</div>
</div>
</div>

</py:block>
<py:block name="content">
<!-- insert main content -->
<div class="container">
<div id="calendar" class="w100 h100"></div>
</div>

</py:block>
</py:extends>
Loading

0 comments on commit 5ad1bb2

Please sign in to comment.