Zwischencommit Absence

This commit is contained in:
holger.trampe 2020-05-03 01:22:36 +02:00
parent 98d786a6c4
commit db58c37c82
14 changed files with 518 additions and 59 deletions

View File

@ -15,31 +15,35 @@ import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
############################################## DEV #####################################
BASE_URL = "https://dev01.digitale-agentur.com/"
############################################## LOCAL #####################################
BASE_URL = "http://localhost:8000/"
CRONAPIKEY = "gCddsaz6NOnE9QbXZM5LasdEk122D"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
# MAIL DEV
EMAIL_HOST = 'smtp.strato.de'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = "support@dev01.digitale-agentur.com"
EMAIL_HOST_PASSWORD = "support@dev01.digitale-agentur.com"
DEFAULT_FROM_EMAIL = "support@dev01.digitale-agentur.com"
DEBUG = True
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
# DEV
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME' : 'digitaleagentur_dev01',
'USER' : 'digitaleagentur_dev01',
'PASSWORD' : 't3TvtGAOkFHYXdJlUMIu9u3U',
'NAME' : 'digitaleagentur',
'USER' : 'root',
'PASSWORD' : '',
'PORT' : 3306
}
}
############################################## DEV #####################################
# MAIL DEV
EMAIL_HOST = 'gymhum.de'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = "holger.trampe"
EMAIL_HOST_PASSWORD = "Motte2016_!"
DEFAULT_FROM_EMAIL = "holger.trampe@gymhum.de"
################################################### LOCAL ###############################
# Nach zehn Stunden läuft der Cookie ab!

View File

@ -117,7 +117,7 @@
<h5 class="card-title">Quicklinks</h5>
<p class="card-text">
{% for ql in standard.addedquicklinks.all %}
<a href="{{ ql.link }}" target="_blank">{{ ql.link|truncatechars:30 }}</a><br />
<a href="{{ ql.link }}" target="_blank">{{ ql.name|truncatechars:30 }}</a><br />
{% endfor %}
</p>
</div>

View File

@ -832,5 +832,6 @@ $(document).ready(function() {
});
});
</script>
{% endblock content %}

View File

@ -2,7 +2,7 @@ from django import template
from django.contrib.auth.models import Group, User
from users.models import AgencyGroup, Agency, AgencyNetwork, AgencyNetworkPreperation
from standards.models import Standards, StandardCommentRate, StandardComments
from timemanagement.models import Workday
from timemanagement.models import Workday, FreeDays
from message.models import Message
import os
from django.conf import settings
@ -384,3 +384,34 @@ def getsumbreak(workday):
sum_break += (ele.end - ele.start).seconds
return int(sum_break/60)
# DATE TIME HELPTER
act_forloop_date_counter = "";
@register.simple_tag
def setdateforloopcounter(newcounter):
global act_forloop_date_counter
act_forloop_date_counter = newcounter
return ""
@register.simple_tag
def getactdateforloopcounter():
return act_forloop_date_counter
@register.simple_tag
def isfreeday(user, daytocheck):
returnstat = False
fd = FreeDays.objects.filter(agency=user.profile.agency, day=daytocheck)
if len(fd) > 0:
returnstat = True
return returnstat
@register.simple_tag
def isfreedayname(user, daytocheck):
returnstat = False
fd = FreeDays.objects.filter(agency=user.profile.agency, day=daytocheck)
if len(fd) > 0:
returnstat = True
returnstat = fd[0].name
return returnstat

19
timemanagement/forms.py Normal file
View File

@ -0,0 +1,19 @@
from bootstrap_datepicker_plus import DatePickerInput
from django import forms
from django.forms import ModelForm
from .models import Absence
class AddAbsence(forms.ModelForm):
class Meta:
model = Absence
labels = {
"start" : "Beginn der Abwesenheit",
"end" : "Ende der Abwesenheit",
}
fields = ['start', 'end']
widgets = {
'start': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
'end': DatePickerInput(options={"format":'DD.MM.YYYY', "locale":'de'}),
}

View File

@ -0,0 +1,207 @@
{% load counter_tag %}
<div class="btn-group mr-2 mb-2" role="group" aria-label="calendarbuttons">
<button type="button" class="btn btn-primary mr-1" onclick="javascript:prevMonth()" ><i class="fas fa-arrow-circle-left"></i></button>
<button type="button" class="btn btn-primary mr-1" style="min-width: 150px !important;">{{days_this_month.0|date:"F Y"}}</button>
<button type="button" class="btn btn-primary mr-1" onclick="javascript:nextMonth()"><i class="fas fa-arrow-circle-right"></i></button>
</div>
<table class="table table-striped table-sm table-bordered" id="timetable_team">
<th>
{% for da in days_this_month %}
<td id="{{forloop.counter0}}_tableheadid"><small>{{da|date:"d D"}}</small></td>
{% endfor %}
</th>
{% for us in usersofagency %}
{% setdateforloopcounter forloop.counter %}
{% getactdateforloopcounter as actfcounter %}
<tr>
<td width="21%" id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_firstcolum">
<img class="commentimg mr-2" src="{{ us.profile.get_photo_url }}">
{{us.get_full_name}}
</td>
{% for da in days_this_month %}
{% isfreeday user da as isfree %}
{% isfreedayname user da as isfreename %}
{% if isfree %}
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #e74a3b" data-toggle="tooltip" data-placement="top" title="{{isfreename}}">
{% elif da.weekday == 5 or da.weekday == 6 %}
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_free" style="background-color: #d3d3d3">
{% else %}
<td id="{{actfcounter}}_{{forloop.counter}}_{{us.pk}}_{{da|date:'Y-m-d'}}" {% if us.pk == user.pk or user|usergperm:"absencemanager" %}class="tm-ab-tdhover"{% endif %}>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<script type="text/javascript">
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
function prevMonth(){
$.ajax({
type: "GET",
url: "{% url 'tm-ajax' %}",
data:{
action : "testdjango",
activeyear : {{prevyear}},
activemonth : {{prevmonth}}
},
beforeSend: function(request) {
$("#overlay").fadeIn();
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
},
success : function(data){
$("#overlay").fadeOut();
$("#rendered_table").html(data)
}
});
}
function nextMonth(){
$.ajax({
type: "GET",
url: "{% url 'tm-ajax' %}",
data:{
action : "testdjango",
activeyear : {{nextyear}},
activemonth : {{nextmonth}}
},
beforeSend: function(request) {
$("#overlay").fadeIn();
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
},
success : function(data){
$("#overlay").fadeOut();
$("#rendered_table").html(data)
}
});
}
var selectedElements = [];
var active_row = "";
var user_has_right = "{{user|usergperm:"absencemanager"}}";
if(user_has_right == "True"){
user_has_right = true;
}
else{
user_has_right = false;
}
function recalculateChoosenDays(){
seldates = [];
userid = "";
for(i = 0; i < selectedElements.length; i++){
seldates.push(selectedElements[i].split("_")[3]);
userid = selectedElements[i].split("_")[2];
}
seldates.sort();
date_start = new Date(seldates[0])
date_end = new Date(seldates[seldates.length-1])
$("#div_id_end").show();
$("#startAbsenceProgress").modal("toggle");
$("#id_start").data("DateTimePicker").date(date_start);
$("#id_end").data("DateTimePicker").date(date_end);
if(seldates.length == 1){
$("#div_id_end").hide();
}
}
$( function() {
$( "#timetable_team" ).selectable({
filter: 'td',
start : function(){
if(selectedElements.length > 0){
selectedElements = [];
}
},
selecting: function(event, ui){
newid = ui["selecting"]["id"];
if(newid.split("_")[1] == "tableheadid" || newid.split("_")[3] == "firstcolum" || (newid.split("_")[2] != {{user.pk}} && user_has_right != true ) || newid.split("_")[3] == "free"){
$("#" + newid).removeClass();
}
else{
if(selectedElements.length == 0){
active_row = newid.split("_")[0];
selectedElements.push(ui["selecting"]["id"]);
}
else if(newid.split("_")[0] != active_row){
$("#" + newid).removeClass();
}
else{
selectedElements.push(ui["selecting"]["id"]);
}
}
},
unselecting: function(event, ui){
selectedElements.splice(selectedElements.indexOf(ui["unselecting"]["id"]),1);
},
stop: function(){
recalculateChoosenDays();
}
});
} );
</script>
<style>
.loader {
position: relative;
border: 7px solid #d3d3d3;
border-radius: 50%;
border-top: 7px solid red;
width: 70px;
height: 70px;
left:50%;
top:50%;
-webkit-animation: spin 1s linear infinite; /* Safari */
animation: spin 1s linear infinite;
}
#overlay{
position: absolute;
top:0px;
left:0px;
width: 100%;
height: 100%;
background: black;
opacity: .4;
}
.container{
position:relative;
height: 300px;
width: 200px;
border:1px solid red;
}
/* Safari */
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>

View File

@ -1,13 +1,83 @@
{% extends "users/base.html" %}
{% block content %}
{% load crispy_forms_tags %}
{% load counter_tag %}
{% if request.user.profile.agency.module_timemanagement_ze %}
<!-- Moment.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js" integrity="sha256-VBLiveTKyUZMEzJd6z2mhfxIqz3ZATCuVMawPZGzIfA=" crossorigin="anonymous"></script>
<!-- Tempus Dominus Bootstrap 4 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.1.2/css/tempusdominus-bootstrap-4.min.css" integrity="sha256-XPTBwC3SBoWHSmKasAk01c08M6sIA5gF5+sRxqak2Qs=" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.1.2/js/tempusdominus-bootstrap-4.min.js" integrity="sha256-z0oKYg6xiLq3yJGsp/LsY9XykbweQlHl42jHv2XTBz4=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<div class="content-section col-12">
<h3>Abwesenheiten&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Bearbeiten Sie hier Ihre Abwesenheiten." class="far fa-question-circle"></i></small></h3>
<h3>Abwesenheiten{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Bearbeiten Sie hier Ihre Abwesenheiten." class="far fa-question-circle"></i></small>{% endif %}</h3>
<hr>
{{freedays}}
<div>
<div id="rendered_table">
Lade Kalenderdaten...
</div>
<div id="overlay" style="display: none;">
<div class="loader"></div>
</div>
</div>
<div class="modal fade" tabindex="-1" role="dialog" id="startAbsenceProgress" data-backdrop="static">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Abwesenheit bentragen</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form method="POST">
{% csrf_token %}
{{abscenceform.media}}
{{abscenceform|crispy}}
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary">Abwesenheit beantragen</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Abbrechen</button>
</div>
</div>
</div>
</div>
<style>
.tm-ab-tdhover:hover{
background-color: #858796 !important;
}
#timetable_team .ui-selecting {
background: #858796;
}
#timetable_team .ui-selected {
background: #858796;
color: white;
}
#timetable_team {
list-style-type: none;
margin: 0;
padding: 0;
width: 100%;
}
#timetable_team {
margin: 0px;
padding: 0.4em;
font-size: 1em;
height: 10px;
}
</style>
<style type="text/css">
.commentimg {
border-radius: 50%;
width: 18%;
}
</style>
<style>
/* DATATABLES */
.paginate_button {
padding: 0px !important;
@ -15,29 +85,28 @@
}
</style>
<script>
$(document).ready(function(){
/*
$('#table_timemanagement').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
//Initial Load
function loaddjango(){
$.ajax({
type: "GET",
url: "{% url 'tm-ajax' %}",
data:{
action : "testdjango",
activeyear : {{activeyear}},
activemonth : {{activemonth}}
},
beforeSend: function(request) {
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
},
"buttons" : {
"className" : "btn-danger"
success : function(data){
$("#rendered_table").html(data)
}
});
*/
}
$(document).ready(function(){
loaddjango();
moment.locale('de');
});
</script>

View File

@ -8,6 +8,7 @@ Permissions definiert in models.py bei USERS und dann hier vor die View geschrie
urlpatterns = [
path('', TimeManagement, name='tm-management'),
path('abs/', AbsenceManagmenet, name='tma-management'),
path('abs/<int:activemonth>/<int:activeyear>', AbsenceManagmenet, name='tma-management'),
path('ajax/', TimeAjax, name='tm-ajax'),
#path('newsadd/', permission_required('users.modulenews')(views.NewsAdd), name='news-add'),
#path('newsupdate/<int:id>/', permission_required('users.modulenews')(views.NewsUpdate), name='news-update'),

View File

@ -1,12 +1,17 @@
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from .models import Workday, Breaks
from .models import Workday, Breaks, FreeDays
from django.utils import timezone
import requests, csv, os
from django.templatetags.static import static
from django.conf import settings
from datetime import date
from django.contrib.auth.models import User
from calendar import monthrange
import datetime
import calendar
from .forms import AddAbsence
def loadingFreeDays(plz):
# Getting land
@ -34,15 +39,71 @@ def loadingFreeDays(plz):
else:
return False
def get_datetime_range(year, month):
nb_days = monthrange(year, month)[1]
return [datetime.date(year, month, day) for day in range(1, nb_days+1)]
@login_required
def AbsenceManagmenet(request):
def AbsenceManagmenet(request, activemonth=False, activeyear=False):
prevmonth = ""
nextmonth = ""
#MONTH
if(not activemonth or activemonth > 12 or activemonth < 1):
activemonth = int(activemonth)
#Active month
activemonth=date.today().month
if(activemonth == 1):
prevmonth = 12
else:
prevmonth = activemonth-1
if(activemonth == 12):
nextmonth = 1
else:
nextmonth = activemonth + 1
else:
if(activemonth == 1):
prevmonth = 12
else:
prevmonth = activemonth-1
if(activemonth == 12):
nextmonth = 1
else:
nextmonth = activemonth + 1
#YEAR
nextyear = date.today().year
prevyear = date.today().year
if(not activeyear):
activeyear = date.today().year
else:
if(nextmonth == 1):
nextyear = activeyear + 1
else:
nextyear = activeyear
if(prevmonth == 12):
prevyear = activeyear - 1
else:
prevyear = activeyear
context = {
"active_link" : "abscence",
"freedays" : loadingFreeDays(request.user.profile.agency.plz)
"usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).order_by("-last_name"),
"days_this_month" : get_datetime_range(activeyear,activemonth),
"nextmonth" : nextmonth,
"prevmonth" : prevmonth,
"nextyear" : nextyear,
"prevyear" : prevyear,
"activemonth" : activemonth,
"activeyear" : activeyear,
"abscenceform" : AddAbsence()
}
return render(request, 'timemanagement/tm_ab_management.html', context)
@ -126,6 +187,70 @@ def TimeAjax(request):
}
else:
data = { "success" : False}
# REMOVE WORKDAY
elif request.GET["action"] == "testdjango":
prevmonth = ""
nextmonth = ""
activemonth = int(request.GET["activemonth"])
activeyear = int(request.GET["activeyear"])
#MONTH
if(not activemonth or activemonth > 12 or activemonth < 1):
activemonth = int(activemonth)
#Active month
activemonth=date.today().month
if(activemonth == 1):
prevmonth = 12
else:
prevmonth = activemonth-1
if(activemonth == 12):
nextmonth = 1
else:
nextmonth = activemonth + 1
else:
if(activemonth == 1):
prevmonth = 12
else:
prevmonth = activemonth-1
if(activemonth == 12):
nextmonth = 1
else:
nextmonth = activemonth + 1
#YEAR
nextyear = date.today().year
prevyear = date.today().year
if(not activeyear):
activeyear = date.today().year
else:
if(nextmonth == 1):
nextyear = activeyear + 1
else:
nextyear = activeyear
if(prevmonth == 12):
prevyear = activeyear - 1
else:
prevyear = activeyear
context = {
"active_link" : "abscence",
"usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).order_by("-last_name"),
"days_this_month" : get_datetime_range(activeyear,activemonth),
"activemonth" : activemonth,
"activeyear" : activeyear,
"nextmonth" : nextmonth,
"prevmonth" : prevmonth,
"nextyear" : nextyear,
"prevyear" : prevyear
}
return render(request, "timemanagement/rendered_table.html", context)
else:
data = {
"success" : False

View File

@ -606,10 +606,6 @@ function removeNotification(notifyid){
}
$(document).ready(function(){
console.log("{{root}}");
console.log("{{url}}");
$("#notification_items").html("");
loadUnsendNotifications();

View File

@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="shortcut icon" type="image/x-icon" href="{% static 'users/img/favicon.png' %}">
<link rel="shortcut icon" type="image/x-icon" href="{% static 'users/img/favicon.ico' %}">
<title>Digitale Agentur</title>
<!-- Custom fonts for this template-->
@ -69,16 +69,26 @@
height: 100%;
filter: blur(8px);
}
</style>
</head>
<body id="page-top">
<!--<svg style="min-width:100%; min-height: 100%;">
<defs>
<filter id="blur">
<feGaussianBlur stdDeviation="6" />
</filter>
</defs>
<image xlink:href="{% static 'users/img/registerbackground.jpg' %}" style="min-width:100%; min-height: 100%;" filter="url(#blur)"></image>
</svg>-->
<div class="background-image"></div>
<ul class=" bg-gray-900 navbar sidebar-dark accordion fixed-top" id="accordionSidebar">
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}">
<i class="fas fa-laptop" style="margin-top: 0px;"></i>
<div class="sidebar-brand-text mx-3" style="text-align: left;">
<b> Digitale<br />Agentur</b>
<img src="{% static 'users/img/VVE-Logo.png' %}" style="float: right; margin-top: -20px;" width="3%" class="">
<img src="{% static 'users/img/VVE-Logo.png' %}" style="float: right; " width="3%" class="">
</div>
</a>
</ul>

View File

@ -262,8 +262,6 @@ class AgencyCreateView(CreateView):
@login_required
def dashboard(request):
print("MEIDA ROOT:" + settings.MEDIA_ROOT)
print("MEDIA URL:" + settings.MEDIA_URL)
# UPDATE FUNCTIONS BY NEW MODEL-CHANGES FOR COPIEN SOME DATA
toUpdate(request)
@ -272,8 +270,6 @@ def dashboard(request):
context = {
'active_link' : 'dashboard',
'root' : settings.MEDIA_ROOT,
'url' : settings.MEDIA_URL
#"systemencode" : storageinfo
}
# Adding active_link