Zwischencommit Vertragsdaten und Kleinkrams

This commit is contained in:
holger.trampe 2020-04-26 01:30:04 +02:00
parent e68c374664
commit f52d1d64e4
43 changed files with 881 additions and 298 deletions

View File

@ -4,6 +4,14 @@ from django.contrib.auth.models import User
from users.models import AgencyGroup, Agency, Profile, AgencyJob, AgencyNetwork
from PIL import Image
class AgencyOrganigrammForm(forms.ModelForm):
class Meta:
model = Agency
fields = ['dynamicprofile']
labels = {
'dynamicprofile' : "Dynamischer Steckbrief"
}
class AgencyNetworkForm(forms.ModelForm):
class Meta:
@ -94,13 +102,14 @@ class UserProfileForm(forms.ModelForm):
"persnumber" : "Personalnummer",
"visible" : "Im Organigramm sichtbar",
"phonemobile" : "Mobilnummer",
"phone_public" : "Nur Interne Verwendung der Mobilnummer",
"phoneland" : "Festnetznummer",
"image": "Profilbild",
"func" : "Agenturfunktion",
"compfunc" : "Tätigkeit"
}
widgets = {"parent" : forms.HiddenInput()}
fields = ["parent", "func", "compfunc", "visible", "phoneland", "phonemobile", "persnumber", "image" ]
fields = ["parent", "func", "compfunc", "visible", "phoneland", "phonemobile", "phone_public", "persnumber", "image" ]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

View File

@ -15,7 +15,7 @@
<div class="row">
<div class="col-3">
{% for formfield in agencyform %}
{% if forloop.counter|divisibleby:6 %}
{% if forloop.counter|divisibleby:5 %}
</div>
<div class="col-3">
{{formfield|as_crispy_field}}

View File

@ -0,0 +1,19 @@
{% load crispy_forms_tags %}
<form method="POST" enctype="multipart/form-data" name="updateModSettingsOrganigramm">
{% csrf_token %}
{{modsettings_organigramm|crispy}}
</form>
<script type="text/javascript">
function updateOrganigrammSettings(){
$.ajax(
{
type: "GET",
url: "{% url 'modsettings-orga' %}",
data:{
dynorga: $("#id_dynamicprofile").prop('checked')
},
success: function( data )
{}
});
}
</script>

View File

@ -16,8 +16,8 @@
{% for formfield in modulform %}
<tr>
<td>{{formfield.label_tag}}</td>
<td>{{formfield}}</td>
<td><button type="button" class="btn btn-sm btn-primary" disabled="true"><i class="fas fa-cog"></i></button></td>
<td>{{formfield}}</td>
<td><button type="button" class="btn btn-sm btn-primary" onclick="javascript:$('#modulesettings_{{formfield.name}}').modal('toggle');"><i class="fas fa-cog"></i></button></td>
</tr>
{% endfor %}
</tbody>
@ -26,3 +26,39 @@
</form>
</div>
{% for formfield in modulform %}
<div class="modal fade" id="modulesettings_{{formfield.name}}" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="" aria-hidden="true">
<div class="modal-dialog " role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Moduleinstellungen {{formfield.label_tag}}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Schließen">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
{% if formfield.name != 'module_organigramm' %}
Keine Einstellungen vorhanden.
{% else %}
{% block modulesettings_organigramm %}
{% include "dasettings/modulesettings_organigramm.html" %}
{% endblock %}
{% endif %}
{% if formfield.name == 'module_organigramm' %}
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Schließen</button>&nbsp;
<button id="" type="button" onclick="javascript:updateOrganigrammSettings()" class="btn btn-success" data-dismiss="modal" >Speichern</button>
</div>
{% else %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Schließen</button>&nbsp;
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endfor %}

View File

@ -122,7 +122,7 @@ noclickeffect:active { border-style: outset !important;}
</button>
</div>
<div class="modal-body">
Möchten Sie den Bereich <b><span id="areaName"></span></b> wirklich löschen? Alle darin enthaltenen Tätigkeiten <u>und Standards</u> werden ebenfalls entfernt!
Möchten Sie den Bereich <b><span id="areaName"></span></b> wirklich löschen? Alle darin enthaltenen Tätigkeiten werden gelöscht und die Standards müssen neu einer Tätigkeit und einem Bereich zugeordnet werde!
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal" onclick="javascript:doDelArea()">Bereich löschen</button>&nbsp;&nbsp;

View File

@ -40,105 +40,128 @@
<div class="content-section col-10">
<h3>Mitarbeiter {{user_fullname}} &nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Geben Sie hier die Profildaten für den Mitarbeiter ein." class="far fa-question-circle"></i></small></h3>
<h3>Mitarbeiter <span id="user_title_fullname">{{user_fullname}}</span> &nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Geben Sie hier die Profildaten für den Mitarbeiter ein." class="far fa-question-circle"></i></small></h3>
<hr>
{% if newuser == 1 %}
<div class="progress mb-3" style="max-height: 15px;">
<div class="progress-bar" role="progressbar" style="width: 80%; " aria-valuenow="80" aria-valuemin="0" aria-valuemax="100">Schritt 2: Profildaten festlegen</div>
</div>
{% endif %}
<div class="media mb-4">
<div class="media">
<img class="img-profile" style="width: 15%;" src="{{ imagelink }}">
<div class="media-body col-6">
<div class="row">
<div class="col-12">
<div class="col-8">
<h6><b>Name</b></h6>
<p>
{{ user_fullname }}
<span id="user_fullname">{{ user_fullname }}</span>&nbsp;<button style="float: right" type="button" class="btn btn-secondary btn-sm" onclick="javascript:ChangeName()" id="changenamebutton"><i class="fas fa-pen"></i></button>
</p>
<h6><b>E-Mail</b></h6>
<p>
{{ mail }}
<span id="user_email">{{ mail }}</span>&nbsp;<button onclick="javascript:ChangeMail()" style="float: right" type="button" class="btn btn-secondary btn-sm" id="changemailbutton"><i class="fas fa-pen"></i></button>
</p>
<div style="float: left">
<a href="{% url 'changeusermaindata' vieweduser %}">
<button type="button" class="btn-primary btn-sm active" >Stammdaten ändern</button></a>
<button type="button" id="" onclick="javascript:sendPassMail({{vieweduser}})" class="btn-primary btn-sm active" >E-Mail mit Link zur Passworterstellung senden</button>&nbsp;&nbsp;<span class="alert alert-success" id="mailsend" role="alert" style="display: none;">&nbsp;E-Mail gesendet!</span>
<button type="button" id="" onclick="javascript:sendPassMail({{vieweduser}})" class="btn-primary btn-sm active" >Passwort wiederherstellen</button>&nbsp;&nbsp;
<br /><br /><span class="alert alert-success" id="mailsend" role="alert" style="display: none;">&nbsp;E-Mail gesendet!</span>
</div>
</div>
</div>
</div>
</div>
<hr>
<form method="POST" enctype="multipart/form-data">
<input type="hidden" name="userprof_formtype" value="profileform">
<div class="mt-2">
<p>Gruppen&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, in welchen Gruppen der neue Mitarbeiter sein soll. Standardmäßig sind alle Mitarbeiter in der Gruppe Mitarbeiter (wenn diese nicht umbenannt worden ist)." class="far fa-question-circle"></i></small></p>
<div class="row">
<div class="col-4">
{% for g in agencygroups %}
{% if forloop.counter|divisibleby:6 %}
</div><div class="col-4">
<div class="custom-control custom-checkbox mb-2">
{% if vieweduser|useringroupbyid:g.group.name %}
<input type="checkbox" class="custom-control-input" name="group_{{g.pk}}" id="group_{{g.pk}}" onchange="javascript:updateUser({{vieweduser}}, {{g.pk}}, this.checked)" checked="true">
{% else %}
<input type="checkbox" class="custom-control-input" name="group_{{g.pk}}" id="group_{{g.pk}}" onchange="javascript:updateUser({{vieweduser}}, {{g.pk}}, this.checked)">
{% endif %}
<label class="custom-control-label" for="group_{{g.pk}}" >{{g.agencygroupname}}</label>
</div>
{% else %}
<div class="custom-control custom-checkbox mb-2">
{% if vieweduser|useringroupbyid:g.group.name %}
<input type="checkbox" class="custom-control-input" name="group_{{g.pk}}" id="group_{{g.pk}}" onchange="javascript:updateUser({{vieweduser}}, {{g.pk}}, this.checked)" checked="true">
{% else %}
<input type="checkbox" class="custom-control-input" name="group_{{g.pk}}" id="group_{{g.pk}}" onchange="javascript:updateUser({{vieweduser}}, {{g.pk}}, this.checked)">
{% endif %}
<label class="custom-control-label" for="group_{{g.pk}}" >{{g.agencygroupname}}</label>
</div>
{% endif %}
{% endfor %}
</div></div>
</div>
<hr>
<div class="mt-2">
<p>Übergeordneter Mitarbeiter&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, welche Mitarbeiter über diesen im Organigramm steht. Ist die Einstellung leer, wir" class="far fa-question-circle"></i></small></p>
<select name="usertoparent" id="usertoparent" class="select form-control col-4">
<option value="">---------</option>
{% for singleparent in usertoparent %}
{% if parentuser == singleparent.pk %}
<option value="{{singleparent.pk}}" selected>{{singleparent.first_name}} {{singleparent.last_name}} </option>
{% else %}
<option value="{{singleparent.pk}}">{{singleparent.first_name}} {{singleparent.last_name}} </option>
{% endif %}
{% endfor %}
</select>
</div>
<hr>
<p>Persönliches Profil</p>
{% csrf_token %}
<div class="row">
<div class="col-6">
{% for field in profileform %}
{% if forloop.counter|divisibleby:6 %}
</div>
<div class="col-6">
<ul class="nav nav-tabs" id="profSettingsTabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="profil-user-tab" data-toggle="tab" href="#profil-user" role="tab" aria-controls="profil-user" aria-selected="false" >Profil</a>
</li>
<li class="nav-item">
<a class="nav-link" id="contract-tab" data-toggle="tab" href="#contract" role="tab" aria-controls="contract" aria-selected="false" >Vertragsdaten</a>
</li>
</ul>
<div class="tab-content" id="profSettingsTabs">
<div class="tab-pane fade show" id="profil-user" role="tabpanel" aria-labelledby="profil-user-tab">
<form method="POST" enctype="multipart/form-data" name="profileform_basic">
<input type="hidden" name="userprof_formtype" value="profileform">
<div class="mt-2">
<p>Gruppen&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, in welchen Gruppen der neue Mitarbeiter sein soll. Standardmäßig sind alle Mitarbeiter in der Gruppe Mitarbeiter (wenn diese nicht umbenannt worden ist)." class="far fa-question-circle"></i></small></p>
<div class="row">
<div class="col-4">
{% for g in agencygroups %}
{% if forloop.counter|divisibleby:6 %}
</div><div class="col-4">
<div class="custom-control custom-checkbox mb-2">
{% if vieweduser|useringroupbyid:g.group.name %}
<input type="checkbox" class="custom-control-input" name="group_{{g.pk}}" id="group_{{g.pk}}" onchange="javascript:updateUser({{vieweduser}}, {{g.pk}}, this.checked)" checked="true">
{% else %}
<input type="checkbox" class="custom-control-input" name="group_{{g.pk}}" id="group_{{g.pk}}" onchange="javascript:updateUser({{vieweduser}}, {{g.pk}}, this.checked)">
{% endif %}
<label class="custom-control-label" for="group_{{g.pk}}" >{{g.agencygroupname}}</label>
</div>
{% else %}
<div class="custom-control custom-checkbox mb-2">
{% if vieweduser|useringroupbyid:g.group.name %}
<input type="checkbox" class="custom-control-input" name="group_{{g.pk}}" id="group_{{g.pk}}" onchange="javascript:updateUser({{vieweduser}}, {{g.pk}}, this.checked)" checked="true">
{% else %}
<input type="checkbox" class="custom-control-input" name="group_{{g.pk}}" id="group_{{g.pk}}" onchange="javascript:updateUser({{vieweduser}}, {{g.pk}}, this.checked)">
{% endif %}
<label class="custom-control-label" for="group_{{g.pk}}" >{{g.agencygroupname}}</label>
</div>
{% endif %}
{% endfor %}
</div></div>
</div>
<hr>
<div class="mt-2">
<p>Übergeordneter Mitarbeiter&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, welche Mitarbeiter über diesen im Organigramm steht. Ist die Einstellung leer, wir" class="far fa-question-circle"></i></small></p>
<select name="usertoparent" id="usertoparent" class="select form-control col-4">
<option value="">---------</option>
{% for singleparent in usertoparent %}
{% if parentuser == singleparent.pk %}
<option value="{{singleparent.pk}}" selected>{{singleparent.first_name}} {{singleparent.last_name}} </option>
{% else %}
<option value="{{singleparent.pk}}">{{singleparent.first_name}} {{singleparent.last_name}} </option>
{% endif %}
{% endfor %}
</select>
</div>
<hr>
<p>Persönliches Profil</p>
{% csrf_token %}
<div class="row">
<div class="col-6">
{% for field in profileform %}
{% if forloop.counter|divisibleby:6 %}
</div>
<div class="col-6">
{{field|as_crispy_field}}
{% else %}
{{field|as_crispy_field}}
{% else %}
{{field|as_crispy_field}}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endfor %}
</div>
</div>
<hr>
{% if newuser == 1 %}
<button type="submit" class="btn btn-primary" style="float: right">Profilerstellung abschließen</button>
{% else %}
<button type="submit" name="submitprof" class="btn btn-primary" style="float: right">Profil Aktualisieren</button>
{% endif %}
<a class="btn" href="{% url 'dasettings' %} ">Profilbearbeitung abbrechen</a>
</form>
</div>
<hr>
{% if newuser == 1 %}
<button type="submit" class="btn btn-primary" style="float: right">Profilerstellung abschließen</button>
{% else %}
<button type="submit" name="submitprof" class="btn btn-primary" style="float: right">Profil Aktualisieren</button>
{% endif %}
<a class="btn" href="{% url 'dasettings' %} ">Profilbearbeitung abbrechen</a>
</form>
<div class="tab-pane fade" id="contract" role="tabpanel" aria-labelledby="contract-tab">
</div>
</div>
</div>
</div>
@ -176,6 +199,80 @@
</div>
</div>
<script>
/*
DYNAMIC USERDATA CHANGES
*/
//CHANGE MAILADDRESS
function ChangeMail(){
$("#user_email").html('<div class="input-group" style="margin-bottom: -38px;"><input type="email" class="form-control" id="newusermail" value="{{ mail }}"><div class="input-group-append"><button type="button" onclick="javascript:updateNewMail()" class="btn btn-secondary" ><i class="fas fa-check"></i></button></div></div>');
$("#changemailbutton").hide();
}
function updateNewMail(){
newmail = $("#newusermail").val();
$("#changemailbutton").show();
$("#user_email").html(newmail);
$.ajax(
{
type: "GET",
url: "/dasettings/ajax",
data:{
action : "update_usermail",
newmail : newmail,
userid: {{vieweduser}}
},
success: function( data )
{
if(data['success']){
$('#notchange_done').toast('show');
$("#toast_savecontent").html("E-Mailadresse aktualisiert");
}
else{
$('#notchange_err').toast('show');
$("#toast_errcontent").html("E-Mailadresse nicht aktualisiert! Valide Daten eingeben oder E-Mailadresse ist bereits vorhanden.");
$("#user_email").html(data["data"]["mail"]);
}
}
});
}
//CAHNGE USERNAME
function ChangeName(){
$("#user_fullname").html('<div class="input-group" style="margin-bottom: -38px;"><input type="text" class="form-control" size="40" id="user_first_name" value="{{first_name}}">&nbsp;&nbsp;<div class="input-group-append"><input type="text" class="form-control" id="user_last_name" value="{{last_name}}"><button type="button" onclick="javascript:updateNewNames()" class="btn btn-secondary" ><i class="fas fa-check"></i></button></div></div>');
$("#changenamebutton").hide();
}
function updateNewNames(){
$.ajax(
{
type: "GET",
url: "/dasettings/ajax",
data:{
action : "update_usernames",
new_first_name : $("#user_first_name").val(),
new_last_name : $("#user_last_name").val(),
userid: {{vieweduser}}
},
success: function( data )
{
if(data['success']){
$('#notchange_done').toast('show');
$("#toast_savecontent").html("Vor- und Nachname aktualisiert");
$("#user_fullname").html(data["data"]["userfullname"]);
$("#user_title_fullname").html(data["data"]["userfullname"]);
$("#changenamebutton").show();
}
else{
$('#notchange_err').toast('show');
$("#toast_errcontent").html("Vor- und Nachname konnte nicht aktualisiert werden!");
$("#user_fullname").html(data["data"]["userfullname"]);
$("#changenamebutton").show();
}
}
});
}
function showMainUserForm(){
$("#changeMainUserData").modal("toggle");
@ -187,6 +284,8 @@ $(document).ready(function(){
autohide: true,
delay : 3000
});
$('#profil-user').tab('show');
});
function updateUser(userid, groupid, newvalue){
@ -233,9 +332,7 @@ function removeUserFromGroup(userid, groupid){
},
success: function( data )
{
if(data["message"] == 0){
$("#mailsend").fadeIn().delay(4000).fadeOut();
}
$("#mailsend").fadeIn().delay(4000).fadeOut();
}
});
}

View File

@ -23,4 +23,5 @@ urlpatterns = [
path('managnag/acceptinv/<int:network>/<int:targetag>/<int:aginvpk>', permission_required('users.agencynetwork')(views.AddAgToNetwork), name='acceptinvite'),
path('managnag/deli/<int:pk>', permission_required('users.agencynetwork')(views.DelAgInv), name='delinvite'),
#path('managnag/delfromagn/<int:agn>/<int:ag>', permission_required('users.agencynetwork')(views.DelFromAgn), name='delagfromagn'),
path('modsettings/orga/', views.ModSettingsOrga, name="modsettings-orga"),
]

View File

@ -1,7 +1,7 @@
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
from .forms import UsersSelfChangeForm, UsersNotificationForm, AgencyGroupPerms, AgencyModulsForm, UserNewUserForm, UserProfileForm, AgencyNetworkForm
from .forms import UsersSelfChangeForm, UsersNotificationForm, AgencyGroupPerms, AgencyModulsForm, UserNewUserForm, UserProfileForm, AgencyNetworkForm, AgencyOrganigrammForm
from django.contrib import messages
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import PasswordChangeForm
@ -22,6 +22,7 @@ from datetime import datetime
from standards.models import Standards
from django.core.mail import send_mail
from django.conf import settings
import re
def randomString(stringLength=10):
"""Generate a random string of fixed length """
@ -61,6 +62,11 @@ def getAllForms(request, context):
modulform = AgencyModulsForm(instance=request.user.profile.agency)
context.update({'modulform' : modulform})
#MODULSETTUNGS
#Modulsettings ORGANIGRAMM
modsettings_organigramm = AgencyOrganigrammForm(instance=request.user.profile.agency)
context.update({'modsettings_organigramm' : modsettings_organigramm})
# USER FOR USERTABLE
users = User.objects.filter(profile__agency__pk=request.user.profile.agency.pk)
return context
@ -432,6 +438,44 @@ def SettingsAjaxRouter(request):
task.save()
data = {"newvalue" : task.name, "smoved" : standardsmoved}
success = True
# UPDATE USER MAIL
elif request.method == 'GET' and request.GET['action'] == "update_usermail" :
tempuser = User.objects.get(pk=request.GET['userid'])
if(request.user.profile.agency == tempuser.profile.agency and request.user.has_perm('usermanager')):
tempmail = tempuser.email
regex = '^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'
if(re.search(regex,request.GET['newmail'])):
newmail = request.GET['newmail']
usertest = User.objects.filter(email=newmail)
if(len(usertest) > 0):
data = {"mail" : tempmail}
success = False
else:
tempuser.email = newmail
tempuser.save()
success = True
else:
data = {"mail" : tempmail}
success = False
else:
success = False
# UPDATE USERNAME
elif request.method == 'GET' and request.GET['action'] == "update_usernames" :
tempuser = User.objects.get(pk=request.GET['userid'])
if(request.user.profile.agency == tempuser.profile.agency and request.user.has_perm('usermanager')):
regex = '^[a-zA-Z0-9_.-üöäÜÖÄ ]+$'
if(re.search(regex,request.GET['new_first_name']) and re.search(regex,request.GET['new_last_name'])):
tempuser.first_name = request.GET['new_first_name']
tempuser.last_name = request.GET['new_last_name']
tempuser.save()
data = {"userfullname" : tempuser.first_name + " " + tempuser.last_name}
success = True
else:
data = {"userfullname" : tempuser.first_name + " " + tempuser.last_name}
success = False
else:
data = {"userfullname" : tempuser.first_name + " " + tempuser.last_name}
success = False
else:
success = False
return JsonResponse({"success" : success, "data" : data})
@ -475,6 +519,8 @@ def UserProfileUpdate(request, pk, newuser=0):
context = {
'active_link' : 'dasettings',
'user_fullname' : user_fullname,
'first_name' : usertochange.first_name,
'last_name' : usertochange.last_name,
'newuser' : newuser,
'vieweduser' : usertochange.pk,
'parentuser' : parentuser,
@ -489,6 +535,8 @@ def UserProfileUpdate(request, pk, newuser=0):
context = {
'active_link' : 'dasettings',
'user_fullname' : user_fullname,
'first_name' : usertochange.first_name,
'last_name' : usertochange.last_name,
'newuser' : newuser,
'mail' : usertochange.email,
'vieweduser' : usertochange.pk,
@ -777,3 +825,17 @@ def AgencyNetworkAjaxSettings(request):
success = False
return JsonResponse(data)
@login_required
def ModSettingsOrga(request):
if request.method == 'GET':
if(request.GET['dynorga'] == "true"):
ag = request.user.profile.agency
ag.dynamicprofile = True
ag.save()
else:
ag = request.user.profile.agency
ag.dynamicprofile = False
ag.save()
return JsonResponse({})
else:
return JsonResponse({})

View File

@ -3,7 +3,7 @@ from django.urls import path, include
from django.contrib.auth import views as auth_views
from django.conf import settings
from django.conf.urls.static import static
from users.views import AgencyCreateView
from users.views import AgencyCreateView, registerNewAgency
from . import views
from django.contrib.auth.decorators import login_required
'''
@ -35,11 +35,11 @@ urlpatterns = [
path('standards/', include('standards.urls'), name="standards"),
path('news/', include('news.urls'), name="dashboard"),
path('orga/', include('orga.urls'), name="orga"),
path('password-reset/', auth_views.PasswordResetView.as_view(template_name='users/password_reset.html', html_email_template_name='users/password_reset_mail.html'), name='password-reset'),
path('password-reset/', auth_views.PasswordResetView.as_view(template_name='users/password_reset.html', html_email_template_name='users/password_reset_mail.html'), name='password-reset'),
path('password-reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='users/password_reset_done.html'), name='password_reset_done'),
path('password-reset-confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html'), name='password_reset_confirm'),
path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'), name='password_reset_complete'),
path('register/', AgencyCreateView.as_view(template_name='users/register.html'), name='register'),
path('register/', registerNewAgency, name='register'),
path('register/done', views.registerdone, name='register-done'),
path('summernote/', include('django_summernote.urls')),
path('notifications/', include('notificsys.urls'), name="notifications")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -150,11 +150,12 @@
newmesscount = newmesscount - 1;
if(newmesscount > 0){
$("#messcounter").html("(" + newmesscount + ")");
$("#messcounter_badge").show();
}
else{
$("#messcounter").html("");
}
$("#messcounter_badge").hide();
}
}
});
}

View File

@ -60,7 +60,7 @@
</p>
<h6><b>Mobil</b></h6>
<p>
{{ phonemobile }}
{{ phonemobile }}{% if phone_public %}&nbsp;<b>(nur Intern)</b>{% endif %}
</p>
</div>
</div>

View File

@ -15,7 +15,6 @@ def mainorga(request):
nonvisibleuser = list(User.objects.filter(profile__agency__pk=request.user.profile.agency.pk).filter(profile__visible=False).order_by('-id'))
invisible_users = 0;
# Check, if parented users are invisible. Remove them and give user an info!
for ele in nonvisibleuser:
for vis in agencyuser:
@ -27,7 +26,6 @@ def mainorga(request):
pass
agjobs = AgencyJob.objects.filter(agency=request.user.profile.agency)
context = {
'active_link' : 'orga',
@ -81,8 +79,7 @@ def singleorga(request, pk):
try:
userfuncname = AgencyJob.objects.get(pk=user.profile.func.pk).name
except:
userfuncname = "Nicht vergeben"
userfuncname = "Nicht vergeben"
context = {
'active_link' : 'orga',
@ -91,18 +88,15 @@ def singleorga(request, pk):
'user_last_name' : user_last_name,
'user_id' : user_id,
'prios' : prios,
'phone_public' : user.profile.phone_public,
'mail' : user.email,
'userfunc' : userfuncname,
'imageurl' : user.profile.get_photo_url,
'compfunc' : user.profile.compfunc,
'phoneland' : user.profile.phoneland,
'tasks' : tasks,
#'representative' : representative,
#'executor' : executor,
#'authority' : authority,
'phonemobile' : user.profile.phonemobile
}
print(context)
}
return render(request, 'orga/orga_single.html', context)
else:
return redirect('users-dashboard')

View File

@ -72,9 +72,6 @@ class Standards(models.Model):
# Quicklinks
addedquicklinks = models.ManyToManyField(QuickLinks, blank=True, related_name="standard_quicklinks")
#indi_name = models.CharField(max_length=200, blank=False, default="")
#indi_conmtent = models.CharField(max_length=500, blank=False, default="")
# FIELD FOR AGENCYNETWORK
comments = models.ManyToManyField("StandardComments", blank=True, related_name='comments')
parent_standard = models.ForeignKey("Standards", related_name='partentedstandard', on_delete=models.SET_NULL, blank=True, null=True, default=None)
@ -91,4 +88,4 @@ class Standards(models.Model):
# Hier Path für Templates des Models mit Parametern
def get_absolute_url(self):
return reverse('standards-update', kwargs={'pk':self.pk})
return reverse('standards-add', kwargs={'pk':self.pk})

View File

@ -37,7 +37,7 @@
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink"> <a class="dropdown-item" href="{% url 'standard-update' item.pk %}">Bearbeiten</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink"> <a class="dropdown-item" href="{% url 'standard-add' item.pk %}">Bearbeiten</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="{% url 'standard-delete' item.pk %}" >Löschen</a>
</div>

View File

@ -38,7 +38,7 @@
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink"> <a class="dropdown-item" href="{% url 'standard-update' item.pk %}">Bearbeiten</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink"> <a class="dropdown-item" href="{% url 'standard-add' item.pk %}">Bearbeiten</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="{% url 'standard-delete' item.pk %}" >Löschen</a>
</div>

View File

@ -28,7 +28,12 @@
</li>
{% if perms.users.standardmanager %}
<li class="nav-item" style="float: right !important;">
<a class="nav-link" id="agencys" data-toggle="tab" href="#t_agencys" role="tab" aria-controls="t_agencys" aria-selected="false">Unveröffentlichte Standards {% if unpubstandards_of_user|length > 0 %} ({{unpubstandards_of_user|length}}) {%endif%}</a>
<a class="nav-link" id="agencys" data-toggle="tab" href="#t_agencys" role="tab" aria-controls="t_agencys" aria-selected="false">
{% if unpubstandards_of_user|length > 0 %}
<span class="badge badge-primary badge-counter" style="float: right; margin-left: 5px; margin-top: 0px">{{unpubstandards_of_user|length}} </span>&nbsp;
{%endif%}
Unveröffentlichte Standards
</a>
</li>
{% endif %}
</div>

View File

@ -65,7 +65,7 @@
<h5 class="card-title">Dateien</h5>
<p class="card-text">
{% for files in standard.addedfiles.all %}
{{files.name|truncatechars:30}}
{{files.name|truncatechars:30}}<br />
{% endfor %}
</p>
</div>

View File

@ -11,7 +11,7 @@ urlpatterns = [
path('', StandardsManagement.as_view(template_name="standards/standards_management.html"), name='standards'),
path('standardadd/', views.StandardAdd, name='standard-add'),
path('standardadd/<int:id>', views.StandardAdd, name='standard-add'),
path('standardupdate/<int:id>', views.StandardUpdate, name='standard-update'),
#path('standardupdate/<int:id>', views.StandardUpdate, name='standard-update'),
path('ajax/loadtasks/', views.load_tasks, name='ajax_loadtasks'),
path('ajups/<int:pk>', views.updatesbyajax, name='update_standard_by_ajax'),
path('ajupsagn/<int:pk>', views.updatesbyajax_agn, name='update_standard_by_ajax_agn'),

View File

@ -444,7 +444,7 @@ def StandardAdd(request, id=False):
}
return render(request, 'standards/standards_add.html', context)
'''
@login_required
def StandardUpdate(request, id):
standard = Standards.objects.get(pk=id, agency=request.user.profile.agency)
@ -468,15 +468,6 @@ def StandardUpdate(request, id):
#existing_standard.executor.set(normalForm.cleaned_data['executor'])
#existing_standard.authority.set(normalForm.cleaned_data['authority'])
'''
AKTUALISIERUNG
Wennn der User selbst den Standard erstellt hat und Rechte zur Standardverwaltung hat,
dann wird der Status nicht verändert (public bleibt true bzw. false). Hat der User
aber keine Rechte und ist der Standarf public, wird er auf public=false gesetzt!
'''
if request.user.has_perm('users.standardmanager'):
messages.success(request, f'Standard {existing_standard.name} aktualisiert!')
else:
@ -492,10 +483,6 @@ def StandardUpdate(request, id):
normalForm = StandardUpdateStandard(instance=standard)
editorForm = StandardUpdateStandardEditor(instance=standard)
'''
Hier werden nur die Dateien dem aktuellen User zur Auswahl gestellt, auf die er auch Zugriff hat.
Das geht NICHT rekursiv! Es wird nur das oberste Verzeichnis geprüft! SPÄTER!
'''
possibleFilesByVisible = []
@ -560,7 +547,7 @@ def StandardUpdate(request, id):
"agencynetworks" : agencynetworks
}
return render(request, 'standards/standards_update.html', context)
'''
@login_required
def load_tasks(request):
areaid = request.GET.get('areaid')

View File

@ -6,7 +6,7 @@ from django.utils import timezone
# MAKE EMAIL UNIQUE
from django.contrib.auth.models import User, Group, Permission
from django.contrib.contenttypes.models import ContentType
import datetime
# UNIQUE and NO BLANK fields while user-registration
User._meta.get_field('email')._unique = True
@ -99,6 +99,7 @@ class Agency(models.Model):
# Steckbrief dynamisch aus Standard
dynamicprofile = models.BooleanField(default=True)
vve = models.CharField(default="", max_length=200, blank=True)
def __str__(self):
return f'{self.name}'
@ -151,6 +152,8 @@ class Profile(models.Model):
parent = models.ForeignKey(User, on_delete=models.PROTECT, blank=True, null=True, related_name='parent_user')
phoneland = models.CharField(max_length=60, blank=True)
phonemobile = models.CharField(max_length=60, blank=True)
phone_public = models.BooleanField(default=False)
# Wenn die Funktion gelöscht wird, wird die FUNC auf NULL gesetzt
func = models.ForeignKey("AgencyJob", blank=True, null=True, default=None, on_delete=models.SET_NULL)
# Wenn dieses Profil gelöscht wird, wird NICHT die Agency geslöscht
@ -194,6 +197,16 @@ class Profile(models.Model):
user_messages_mail = models.BooleanField(default=True)
user_messages_push = models.BooleanField(default=True)
# TIME ELEMENTS
wd_mo = models.IntegerField(default=8)
wd_tu = models.IntegerField(default=8)
wd_we = models.IntegerField(default=8)
wd_th = models.IntegerField(default=8)
wd_fr = models.IntegerField(default=8)
holiday = models.IntegerField(default=24)
loose_holidedate = models.DateField(default=datetime.date(datetime.datetime.now().year, 4,30))
def __str__(self):
return f'{self.user.last_name}'

View File

@ -124,8 +124,7 @@ def save_standard(sender, instance, **kwargs):
notificationtext = "Neuer Agenturstandard: " + instance.name
username = user.first_name + " " + user.last_name
msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : targeturl})
msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : targeturl})
if(GLOBALSENDMAILS):
send_mail(
@ -140,6 +139,12 @@ def save_standard(sender, instance, **kwargs):
if(user.profile.agency_new_standard_push):
newnotification = UserNotification(touser=user, notificationtext="Neuer Agenturstandard: " + instance.name, notificationtype="newstandard", elementid=instance.pk)
newnotification.save()
else:
for user in usersofagency:
if(user.has_perm("users.standardmanager")):
newnotification = UserNotification(touser=user, notificationtext="Neuer unveröffentlichter Agenturstandard: " + instance.name, notificationtype="newstandard", elementid=instance.pk)
newnotification.save()
# SIGNAL FOR NEWS

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

View File

@ -154,7 +154,11 @@
<a class="nav-link " href="{% url 'messages' %}" aria-expanded="true">
<i class="fas fa-envelope"></i>
<span>Mitteilungen</span>{% if gs > 0 %}&nbsp;<small id="messcounter">({{gs}})</small>{% endif %}
<span>Mitteilungen
{% if gs > 0 %}
<span class="badge badge-primary badge-counter" id="messcounter_badge" style="margin-right: 85px;"><span id="messcounter">{{gs}}</span></span>&nbsp;
{% endif %}
</span>
</a>
</li>
{% endif %}
@ -217,11 +221,11 @@
margin-left: 212px;
margin-top: -72px;
}
@media screen and (max-width: 768px) {
/*@media screen and (max-width: 768px) {
#content-wrapper {
margin-left: 105px;
margin-left: 0px !important;
}
}
}*/
</style>
<div id="content-wrapper">
<!-- Main Content -->
@ -398,7 +402,6 @@ function clearSF(){
},
success: function( data )
{
console.log(data);
$("#maincontent").hide();
$("#searchcontent").show();
$("#searchcontent").html(data);
@ -411,22 +414,45 @@ function clearSF(){
}
}
sidebar_toggled = false;
$(document).ready(function(){
if($( window ).width() < 768)
{
$("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "0px");
sidebar_hidden = false;
}
});
// Toggle the side navigation
function toggleSidebar(){
$("#accordionSidebar").toggleClass("sidebar-toggled");
if($("#accordionSidebar").hasClass("sidebar-toggled"))
{
$("#content-wrapper").css("margin-left" , "0px");
sidebar_toggled = true;
}
else{
$("#content-wrapper").css("margin-left" , "105px");
sidebar_toggled = false;
}
function toggleSidebar(){
if(sidebar_hidden == false){
$("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "105px");
sidebar_hidden = true;
}
else{
$("#accordionSidebar").removeClass("toggled");
$("#content-wrapper").css("margin-left" , "0px");
sidebar_hidden = false;
}
}
$( window ).resize(function() {
if($( window ).width() < 750)
{
$("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "0px");
sidebar_hidden = false;
}
else{
$("#accordionSidebar").removeClass("toggled");
$("#content-wrapper").css("margin-left" , "212px");
sidebar_hidden = true;
}
});
/*
delay = 250;
throttled = false;
function getDimensions() {
@ -452,7 +478,7 @@ window.addEventListener('resize', function() {
});
getDimensions();
*/
/*
AJAX CALL FOR NOTIFICATIONS

View File

@ -75,7 +75,6 @@
</div>
</div>
</div>
{% if not request.user.profile.agency.module_news %}
<div class="card d-block mb-3" style="width: 34.8%">
<div class="card-body">
@ -83,8 +82,6 @@
</div>
</div>
{% endif %}
</div>
<script type="text/javascript">
console.log("{{systemencode}}");

View File

@ -2,12 +2,20 @@
<!-- CRISPY -->
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section col-md-5">
<style type="text/css">
#logincard {
width: 25%;
margin-top: 7%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">
<h2>Digitale Agentur - Login</h2>
<fieldset class="form-group" >
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Digitale Agentur Login</h3>
</legend>
{{ form|crispy }}
</fieldset>
@ -21,11 +29,12 @@
</form>
<div class="border-top pt-3">
<small class="text-muted ml-2">
<a href="mailto:support@digitale-agentur.com" class="">Probleme beim anmelden?</a><br />
<a href="mailto:support@digitale-agentur.com" class="">Probleme beim anmelden?</a>
</small>
<small class="text-muted">
<!--<a class="ml-2" href="{% url 'register' %}">Agentur anmelden und jetzt digitalisieren!</a>-->
<a class="ml-2" href="{% url 'register' %}">Agentur registrieren</a>
</small>
</div>
</div>
</div>
{% endblock content %}

View File

@ -3,10 +3,20 @@
<!-- CRISPY -->
{% load crispy_forms_tags %}
{% block content %}
<legend class="border-bottom mb-3">
<h4>Erfolgreich abgemeldet!</h4>
</legend>
<small>
<a href="{% url 'login' %}">Wieder zurück?</a>
</small>
<style type="text/css">
#logincard {
width: 35%;
margin-top: 4%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Erfolgreich abgemeldet</h3>
</legend>
<p>Sie haben sich erfolgreich ausgeloggt.&nbsp;<a href="{% url 'login' %}">Wieder zurück?</a>
</p>
</div>
</div>
{% endblock content %}

View File

@ -1,15 +1,25 @@
{% extends "users/publicbase.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section col-6">
<h3>Passwort erstellen</h3>
<hr>
<!-- FORMS LADEN users/userforms.py und users/views.py -->
<form method="POST">
<style type="text/css">
#logincard {
width: 35%;
margin-top: 4%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Passwort anfordern</h3>
</legend>
<p>Bitte geben Sie ihre E-Mailadresse ein, mit der Sie sich bei der Digitalen Agentur registriert haben.</p>
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
<hr>
<button type="submit" class="btn btn-success">Passwort anfordern</button>&nbsp;
</form>
</div>
</div>
{% endblock content %}

View File

@ -2,6 +2,20 @@
{% extends "users/publicbase.html" %}
<!-- BLOCK NAME START -->
{% block content %}
<div class="alert alert-info">Passwort erfolgreich zurückgesetzt!</div>
<a href="{% url 'login' %}">Anmelden</a>
<style type="text/css">
#logincard {
width: 35%;
margin-top: 4%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Passwort aktualisiert</h3>
</legend>
<p>Ihr Password wurde erfolgreich aktualisiert.</p>
<a href="{% url 'login' %}">Anmelden</a>
</div>
</div>
{% endblock content %}

View File

@ -4,18 +4,27 @@
{% load crispy_forms_tags %}
<!-- BLOCK NAME START -->
{% block content %}
<div class="content-section col-5">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">
Neues Passwort eingeben
</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-success">Passwort zurücksetzen</button>
</div>
</form>
</div>
<style type="text/css">
#logincard {
width: 35%;
margin-top: 4%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Passwort vergeben</h3>
</legend>
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-success">Passwort aktualisieren</button>
</div>
</form>
</div>
</div>
{% endblock content %}

View File

@ -2,5 +2,19 @@
{% extends "users/publicbase.html" %}
<!-- BLOCK NAME START -->
{% block content %}
<div class="alert alert-info">Es wurde eine E-Mail mit einem Link verschickt.</div>
<style type="text/css">
#logincard {
width: 35%;
margin-top: 4%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Passwort angefordert</h3>
</legend>
<p>Es wurde eine E-Mail mit einem Link verschickt. Damit können Sie sich ein neues Passwort setzen.</p>
</div>
</div>
{% endblock content %}

View File

@ -116,20 +116,19 @@
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto;font-size:20px;line-height:1;text-align:left;color:#000000;">
<h2>Digitale Agentur | Passwort vergessen</h2>
<h2>Digitale Agentur | Passwort anfordern</h2>
</div>
</td>
</tr>
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Roboto;font-size:18px;line-height:1;text-align:left;color:#000000;">
<p>Hallo {{user.first_name}} {{user.last_name}},</p> Sie haben ein neues Passwort für den Zugang ihrer Agentur <b>{{user.profile.agency.name}}</b> angefordert. Bitte gehen Sie auf folgenden Link, um ein Passwort zu erstellen:
<p>Hallo {{user.first_name}} {{user.last_name}},</p> Sie haben ein Passwort für den Zugang Ihrer Agentur <b>{{user.profile.agency.name}}</b> angefordert. Bitte gehen Sie auf folgenden Link, um ein Passwort zu erstellen:
<p>
{% block reset_link %}
<h4><a href="{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}">{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}</a></h4> {% endblock %}
<h4>Ihr Benutzername: {{ user.get_username }}</h4>
</p> Sollten Sie kein Passwort angefordert haben, ignorieren Sie diese E-Mail.
<p>Weitere Informationen erhalten Sie von Ihrem Agenturleiter. Vielen Dank, dass Sie die Plattform <b>Digitale Agentur</b> nutzen!</p>
<h4>Ihr Benutzername: {{ user.email }}</h4>
</p>
<p>Mit freundlichen Grüßen</p>
<p>Ihr Team von Digitale Agentur</p>
</div>

View File

@ -13,117 +13,84 @@
<!-- Custom fonts for this template-->
<link rel="canonical" href="https://www.digitale-agentur.com">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
<link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="{%static 'users/css/sb-admin-2.css' %}" rel="stylesheet">
<link href="{% static 'users/css/theme.css' %}" rel="stylesheet">
<!--<link href="{%static 'users/css/bootstrap.min.css' %}" rel="stylesheet">-->
<link href='https://fonts.googleapis.com/css?family=Roboto&display=swap' rel='stylesheet' type='text/css'>
</head>
<!-- include summernote css/js -->
<!--<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.js"></script>-->
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<!--<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">-->
<ul class=" bg-gray-900 sidebar sidebar-dark accordion fixed-top" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}">
<i class="fas fa-laptop"></i>
<div class="sidebar-brand-text mx-3">Digitale Agentur</div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<div class="sidebar-heading">
<img src="{% static 'users/img/VVE-Logo.png' %}" width="30%" class="mt-2 mb-2">
<br />
<a style="color: #999; text-decoration: none;" href="{% url 'datenschutzda' %}">Datenschutz</a><br />
<a style="color: #999; text-decoration: none;" href="{% url 'impressumda' %}">Impressum</a>
</div>
<div style="margin-top: 10px; margin-bottom: 5px;" class="sidebar-heading">
Version 0.8.3
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<style scoped>
#content-wrapper {
margin-left: 212px;
margin-top: -72px;
}
@media screen and (max-width: 768px) {
#content-wrapper {
margin-left: 105px;
}
}
</style>
<div id="content-wrapper">
<!-- Main Content -->
<div id="content">
<!-- Begin Page Content -->
<div class="container-fluid mt-4">
{% block content %}
{% endblock %}
</div>
<!-- End of Main Content -->
<!-- Footer -->
<!--
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; digitale-agentur.com für <b>{{ user.profile.agency.name }}</b></span>
</div>
</div>
</footer>
-->
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
<!-- Bootstrap core JavaScript-->
<script src="{%static 'users/vendor/jquery/jquery.min.js' %}"></script>
<script src="{%static 'users/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Core plugin JavaScript-->
<script src="{%static 'users/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- Custom scripts for all pages-->
<script src="{%static 'users/js/sb-admin-2.min.js' %}"></script>
<!-- CUSTOM FONT -->
<!-- <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>-->
<!-- CROPPER -->
<link href="{% static 'users/css/cropper.min.css' %}" rel="stylesheet">
<!-- DATATABLES -->
<link href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="{% static 'users/css/sb-admin-2.css' %}" rel="stylesheet">
<link href="{% static 'users/css/theme.css' %}" rel="stylesheet">
<link href="{% static 'users/css/custom.css' %}" rel="stylesheet">
<!-- Page level plugins -->
<!--<script src="vendor/chart.js/Chart.min.js"></script>-->
<!-- Page level custom scripts -->
<!--<script src="js/demo/chart-area-demo.js"></script>-->
<!--<script src="js/demo/chart-pie-demo.js"></script>-->
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote-bs4.js"></script>
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote.css" rel="stylesheet">
<script src="{% static 'summernote/lang/summernote-de-DE.min.js' %}"></script>
<style type="text/css">
.background-image {
background-image: url('{% static 'users/img/registerbackground.jpg' %}');
background-size: cover; /* Resize the background image to cover the entire container */
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
filter: blur(8px);
}
</style>
</head>
<body id="page-top">
<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="">
</div>
</a>
</ul>
<style type="text/css">
#logincard {
width: 35%;
min-width: 500px !important;
margin-top: 4%;
}
</style>
{% block content %}
{% endblock %}
</body>
</html>

View File

@ -0,0 +1,129 @@
{% load static %}
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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' %}">
<title>Digitale Agentur</title>
<!-- Custom fonts for this template-->
<link rel="canonical" href="https://www.digitale-agentur.com">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="{%static 'users/css/sb-admin-2.css' %}" rel="stylesheet">
<link href="{% static 'users/css/theme.css' %}" rel="stylesheet">
<!--<link href="{%static 'users/css/bootstrap.min.css' %}" rel="stylesheet">-->
<link href='https://fonts.googleapis.com/css?family=Roboto&display=swap' rel='stylesheet' type='text/css'>
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<!--<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">-->
<ul class=" bg-gray-900 sidebar sidebar-dark accordion fixed-top" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}">
<i class="fas fa-laptop"></i>
<div class="sidebar-brand-text mx-3">Digitale Agentur</div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<div class="sidebar-heading">
<img src="{% static 'users/img/VVE-Logo.png' %}" width="30%" class="mt-2 mb-2">
<br />
<a style="color: #999; text-decoration: none;" href="{% url 'datenschutzda' %}">Datenschutz</a><br />
<a style="color: #999; text-decoration: none;" href="{% url 'impressumda' %}">Impressum</a>
</div>
<div style="margin-top: 10px; margin-bottom: 5px;" class="sidebar-heading">
Version 0.8.3
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<style scoped>
#content-wrapper {
margin-left: 212px;
margin-top: -72px;
}
@media screen and (max-width: 768px) {
#content-wrapper {
margin-left: 105px;
}
}
</style>
<div id="content-wrapper">
<!-- Main Content -->
<div id="content">
<!-- Begin Page Content -->
<div class="container-fluid mt-4">
{% block content %}
{% endblock %}
</div>
<!-- End of Main Content -->
<!-- Footer -->
<!--
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; digitale-agentur.com für <b>{{ user.profile.agency.name }}</b></span>
</div>
</div>
</footer>
-->
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Bootstrap core JavaScript-->
<script src="{%static 'users/vendor/jquery/jquery.min.js' %}"></script>
<script src="{%static 'users/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Core plugin JavaScript-->
<script src="{%static 'users/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- Custom scripts for all pages-->
<script src="{%static 'users/js/sb-admin-2.min.js' %}"></script>
<!-- CUSTOM FONT -->
<link href="{% static 'users/css/custom.css' %}" rel="stylesheet">
<!-- Page level plugins -->
<!--<script src="vendor/chart.js/Chart.min.js"></script>-->
<!-- Page level custom scripts -->
<!--<script src="js/demo/chart-area-demo.js"></script>-->
<!--<script src="js/demo/chart-pie-demo.js"></script>-->
</body>
</html>

View File

@ -4,7 +4,63 @@
{% load crispy_forms_tags %}
<!-- BLOCK NAME START -->
{% block content %}
<div class="content-section col-5">
<p>Aktuell können nur Agenturen innerhalb der Pilotphase registriert werden. Weitere Infos über support@digitale-agentur.com.</p>
</div>
<div class="card mx-auto" id="logincard">
<div class="card-body">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show " role="alert" id="message_{{forloop.counter}}">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close" onclick='javascript:$("#message_{{forloop.counter}}").fadeOut()'>
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
{% endif %}
<form method="POST">
{% csrf_token %}
<fieldset class="form-group" >
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Registrieren Sie Ihre Agentur</h3>
</legend>
{% for field in form %}
{{field.field_name}}
{% if field.name == 'agb' %}
{{field}}&nbsp;&nbsp;<a style="" href="{% url 'datenschutzda' %}" target="_blank">AGB's*</a><br />
{% elif field.name == 'av' %}
{{field}}&nbsp;&nbsp;<a style="" href="{% url 'impressumda' %}" target="_blank">Auftragsverarbeitung*</a>
{% else %}
{{field|as_crispy_field}}
{% endif %}
{% endfor %}
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="isvve" onclick="javascript:changeVVE()">
<label class="form-check-label" for="isvve">
VVE-Mitglied
</label>
</div>
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-success">Registrieren</button>
</div>
</form>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$("#div_id_vve").hide();
});
function changeVVE(){
var checkBox = document.getElementById("isvve");
if (checkBox.checked == true)
{
$("#div_id_vve").show();
} else {
$("#div_id_vve").hide();
}
}
</script>
{% endblock content %}

View File

@ -0,0 +1,10 @@
<!-- Base-Template einbinden -->
{% extends "users/publicbase.html" %}
<!-- CRISPY -->
{% load crispy_forms_tags %}
<!-- BLOCK NAME START -->
{% block content %}
<div class="content-section col-5">
<p>Aktuell können nur Agenturen innerhalb der Pilotphase registriert werden. Weitere Infos über support@digitale-agentur.com.</p>
</div>
{% endblock content %}

View File

@ -4,5 +4,21 @@
{% load crispy_forms_tags %}
<!-- BLOCK NAME START -->
{% block content %}
<div class="alert alert-info">Agentur angelegt! Es wurde eine E-Mail mit einem Link und weiteren Informationen verschickt.</div>
<style type="text/css">
#logincard {
width: 35%;
margin-top: 4%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Registrierung abgeschlossen</h3>
</legend>
<p>Ihre Agentur wurde erfolgreich angelegt! Bitte prüfen Sie Ihre E-Mails, um sich ein Passwort für Ihren Account zu erstellen. Anschließend können Sie sich in Ihrer Agentur anmelden.
</p>
</div>
</div>
{% endblock content %}

View File

@ -37,13 +37,14 @@ class UsersAddProfileForm(forms.ModelForm):
labels = {
"phoneland" : "Telefon",
"phonemobile" : "Mobil",
"phone_public" : "Interne Verwendung",
"func" : "Agenturfunktion",
"compfunc" : "Tätigkeit",
"image" : "Profilbild",
"visible" : "Im Organigramm sichtbar"
}
fields = ['phoneland','phonemobile', 'visible', 'func', 'compfunc', 'image', 'x', 'y', 'width', 'height']
fields = ['phoneland','phonemobile', 'phone_public', 'visible', 'func', 'compfunc', 'image', 'x', 'y', 'width', 'height']
def save(self):
photo = super(UsersAddProfileForm, self).save()
@ -77,11 +78,10 @@ class AgencyUpdateForm(forms.ModelForm):
"plz" : "PLZ",
"city" : "Stadt",
"agency_email" : "E-Mail",
"phone" : "Telefon",
"dynamicprofile" : "Dynamischer Steckbrief",
"phone" : "Telefon",
"agencypic" : "Agenturbild"
}
fields = ['name','inhaber','agency_email', 'phone', 'street', 'plz', 'city', 'dynamicprofile', 'agencypic', 'x', 'y', 'width', 'height', 'rotation']
fields = ['name','inhaber','agency_email', 'phone', 'street', 'plz', 'city', 'agencypic', 'x', 'y', 'width', 'height', 'rotation']
def save(self):
photo = super(AgencyUpdateForm, self).save()
@ -155,4 +155,17 @@ class SupportForm(forms.Form):
self.fields['problemconc'] = forms.CharField(required=True, label="Problemzusammenfassung")
self.fields['problem'] = forms.CharField(required=True, widget=forms.Textarea, label="Ausführliche Beschreibung")
self.fields['name'].widget.attrs['readonly'] = True
self.fields['mail'].widget.attrs['readonly'] = True
self.fields['mail'].widget.attrs['readonly'] = True
class NewAgencyForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['first_name'] = forms.CharField(required=True, label="Vorname")
self.fields['last_name'] = forms.CharField(required=True, label="Nachname")
self.fields['mail'] = forms.EmailField(required=True, label="E-Mail")
self.fields['agencyname'] = forms.CharField(required=True, label="Agenturname")
self.fields['vve'] = forms.CharField(required=False, label="VVE-Mitgliedsnummer")
self.fields['agb'] = forms.BooleanField(required=True, label="AGB's")
self.fields['av'] = forms.BooleanField(required=True, label="Auftragsverarbeitung")

View File

@ -2,7 +2,7 @@ from django.shortcuts import render, redirect, reverse
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.decorators import login_required
from django.conf import settings
from .usersforms import UsersAddNewUser, UsersAddProfileForm, UsersChangeProfil, AgencyUpdateForm, UsersPermForm, UserAreaTaskForm, SupportForm
from .usersforms import UsersAddNewUser, UsersAddProfileForm, UsersChangeProfil, AgencyUpdateForm, UsersPermForm, UserAreaTaskForm, SupportForm, NewAgencyForm
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, View
from django.contrib import messages
from django.contrib.auth.models import User, Permission
@ -36,7 +36,7 @@ from message.models import Message
from notificsys.models import UserNotification
from organizer.models import AGContacts, AGPassword
import socket
import sys
import sys, os
def randomString(stringLength=10):
"""Generate a random string of fixed length """
@ -101,13 +101,19 @@ def toUpdate(request):
print("NO MAIN DIR FOUND - CREATE")
rootdir = DataDir(is_root=True, agency=request.user.profile.agency)
rootdir.save()
print("AGENCY ROOT DIR CREATED")
print("AGENCY ROOT DIR CREATED")
else:
print("MAIN ROOT DIR FOUND - FILESMODULE READY")
# CHECK IF AGENCY DIRS EXIST
path = settings.MEDIA_ROOT + "/agencydata/agency_" + str(request.user.profile.agency.pk)
if(os.path.isdir(path) == False):
# CREATE AGENCY DEFAULT DIRS
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk)))
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/files"))
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/agencystats"))
os.mkdir(os.path.join(settings.MEDIA_ROOT + "/agencydata/", "agency_" + str(request.user.profile.agency.pk) + "/agencystats/profilepics"))
# DEF STANDARD DIR
defstandard = DataDir.objects.filter(is_defaultstandard=True, agency__pk=request.user.profile.agency.pk)
@ -128,7 +134,6 @@ def toUpdate(request):
a.group.permissions.add(Permission.objects.get(codename="agencynetwork"))
'''
DASHBOARD-View
View nach erfolgreichem Login Dashboard
@ -136,6 +141,79 @@ View nach erfolgreichem Login Dashboard
Templates: welcomeusers.html und base.html
'''
def registerNewAgency(request):
if request.method == "POST":
newagencyform = NewAgencyForm(request.POST)
if newagencyform.is_valid():
# Check Mail
email = newagencyform.cleaned_data.get('mail')
mailset = User.objects.filter(email=email)
if(len(mailset) == 0):
newuser_name = newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name')
agency = Agency()
agency.name = newagencyform.cleaned_data.get("agencyname")
agency.vve = newagencyform.cleaned_data.get("vve")
agency.save()
pr=Profile()
pr.agency=agency
user = ""
try:
user=User.objects.create_user(email, email, randomString(30))
except:
user = User.objects.get(username=email)
user.first_name = newagencyform.cleaned_data.get('first_name')
user.last_name = newagencyform.cleaned_data.get('last_name')
pr.user=user
pr.save()
user.profile = pr
user.save()
msg_html = render_to_string('users/register_mail.html', {'username': newuser_name})
# E-Mail für Passwort-Setzung!
form = PasswordResetForm({'email': email})
if form.is_valid():
form.save(request=request,html_email_template_name='users/password_reset_mail.html')
return render (request, 'users/registercomplete.html')
'''
send_mail(
'Agenturanmeldung',
'Hallo ' + newagencyform.cleaned_data.get('first_name') + ' ' + newagencyform.cleaned_data.get('last_name') + '! Bitte setzen sie sich auf https://digitale-agentur.com/password-reset/ ein Passwort. Anschließend können Sie weitere Details Ihrer Agentur eingeben.',
'support@digitale-agentur.com',
[email],
html_message=msg_html,
fail_silently=False
)
'''
return render (request, 'users/registercomplete.html')
else:
messages.success(request, f'Diese E-Mailadresse ist bereits vergeben!')
context = {
"form" : NewAgencyForm(request.POST)
}
return render (request, 'users/register.html',context)
else:
messages.success(request, f'Es ist ein Fehler aufgetreten.')
context = {
"form" : NewAgencyForm(request.POST)
}
return render (request, 'users/register.html',context)
else:
context = {
"form" : NewAgencyForm()
}
return render (request, 'users/register.html',context)
class AgencyCreateView(CreateView):
model = User
fields = ['first_name', 'last_name','username', 'email']
@ -673,12 +751,12 @@ Schickt eine E-Mail an den User inkl. Passwortlink zum zurücksetzen.
def sendpassmail(request):
if(request.method == 'GET'):
userid = request.GET['userid']
tempuser = User.objects.get(pk=userid)
tempuser = User.objects.get(pk=userid)
# E-Mail für Passwort-Setzung!
form = PasswordResetForm({'email': tempuser.email})
if form.is_valid():
request.META['SERVER_NAME'] = 'digitale-agentur.com'
request.META['SERVER_PORT'] = '443'
form.save(request= request,use_https=True,from_email="support@digitale-agentur.com",html_email_template_name='users/password_reset_mail.html')
form.save(request=request,html_email_template_name='users/password_reset_mail.html')
return render (request, 'users/registercomplete.html')
return JsonResponse({'message' : 0})
def datenschutz(request):