0.8.2 READY FOR QS!

This commit is contained in:
holger.trampe 2020-03-26 00:08:57 +01:00
parent 69d12f8658
commit a1ddc55206
74 changed files with 1276 additions and 290 deletions

View File

@ -358,6 +358,7 @@ a.disabled {
</div> </div>
</div> </div>
<!-- UPLOADING PROCESS -->
<div class="modal fade" id="uploadModalProgress" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal fade" id="uploadModalProgress" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">

View File

@ -19,13 +19,14 @@ class UsersNotificationForm(forms.ModelForm):
model = Profile model = Profile
labels = { labels = {
"news_mail" : "Agentur-News", "news_mail" : "Agentur-News",
"user_standard_public_mail" : "Veröffentlichung meiner Standards", #"user_standard_public_mail" : "Veröffentlichung meiner Standards",
"agency_new_standard_mail" : "Neue Agentur-Standards", "agency_new_standard_mail" : "Neue Agentur-Standards",
'add_new_group_mail' : "Gruppenmitgliedschaften", 'add_new_group_mail' : "Gruppenmitgliedschaften",
'add_task_mail' : "Tätigkeitsbereich", 'add_task_mail' : "Tätigkeitsbereich",
'user_messages_mail' : "Mitteilungen" 'user_messages_mail' : "Mitteilungen"
} }
fields = ['news_mail', 'news_push', 'user_standard_public_mail', 'user_standard_public_push', 'agency_new_standard_mail', 'agency_new_standard_push', 'add_new_group_mail', 'add_new_group_push', 'add_task_mail', 'add_task_push', 'user_messages_mail', 'user_messages_push'] #fields = ['news_mail', 'news_push', 'user_standard_public_mail', 'user_standard_public_push', 'agency_new_standard_mail', 'agency_new_standard_push', 'add_new_group_mail', 'add_new_group_push', 'add_task_mail', 'add_task_push', 'user_messages_mail', 'user_messages_push']
fields = ['news_mail', 'news_push', 'agency_new_standard_mail', 'agency_new_standard_push', 'add_new_group_mail', 'add_new_group_push', 'add_task_mail', 'add_task_push', 'user_messages_mail', 'user_messages_push']
# PERMISSION GROUPS FORM # PERMISSION GROUPS FORM
class AgencyGroupPerms(forms.Form): class AgencyGroupPerms(forms.Form):
@ -52,12 +53,12 @@ class AgencyModulsForm(forms.ModelForm):
model = Agency model = Agency
labels = { labels = {
'module_news' : "Agentur-News", 'module_news' : "Agentur-News",
'module_quicklinks' : "Quicklinks", 'module_organizer' : "Organizer",
'module_files' : "Dateien", 'module_files' : "Dateien",
'module_organigramm' : "Organigramm", 'module_organigramm' : "Organigramm",
'module_messages' : "Mitteilungen", 'module_messages' : "Mitteilungen",
} }
fields = ['module_news','module_quicklinks','module_files','module_organigramm', 'module_messages'] fields = ['module_news','module_organizer','module_files','module_organigramm', 'module_messages']
# NEW USER FORM # NEW USER FORM
class UserNewUserForm(forms.ModelForm): class UserNewUserForm(forms.ModelForm):

View File

@ -117,12 +117,12 @@
/* CHECK FOR ACTIVATED MODULS */ /* CHECK FOR ACTIVATED MODULS */
module_news = '{{request.user.profile.agency.module_news}}' module_news = '{{request.user.profile.agency.module_news}}'
module_quicklinks = '{{request.user.profile.agency.module_quicklinks}}' module_organizer = '{{request.user.profile.agency.module_organizer}}'
//module_files = '{{request.user.profile.agency.module_files}}' //module_files = '{{request.user.profile.agency.module_files}}'
//module_organigramm = '{{request.user.profile.agency.module_organigramm}}' //module_organigramm = '{{request.user.profile.agency.module_organigramm}}'
if(module_quicklinks == "False"){ if(module_organizer == "False"){
$(".modulequicklinks").remove(); $(".moduleorganizer").remove();
} }
if(module_news == "False"){ if(module_news == "False"){

View File

@ -46,7 +46,7 @@ INSTALLED_APPS = [
'message.apps.MessageConfig', 'message.apps.MessageConfig',
'cloud.apps.CloudConfig', 'cloud.apps.CloudConfig',
'tasks.apps.TasksConfig', 'tasks.apps.TasksConfig',
'quicklinks.apps.QuicklinksConfig', 'organizer.apps.OrganizerConfig',
'standards.apps.StandardsConfig', 'standards.apps.StandardsConfig',
'news.apps.NewsConfig', 'news.apps.NewsConfig',
'crispy_forms', 'crispy_forms',

View File

@ -30,7 +30,7 @@ urlpatterns = [
path('dashboard/', include('users.urls'), name="dashboard"), path('dashboard/', include('users.urls'), name="dashboard"),
path('areas/', include('areas.urls'), name="areas-management"), path('areas/', include('areas.urls'), name="areas-management"),
path('tasks/', include('tasks.urls'), name="tasks-management"), path('tasks/', include('tasks.urls'), name="tasks-management"),
path('ql/', include('quicklinks.urls'), name="ql-management"), path('organizer/', include('organizer.urls'), name="ql-management"),
path('cloud/', include('cloud.urls'), name="cloud-main"), path('cloud/', include('cloud.urls'), name="cloud-main"),
path('standards/', include('standards.urls'), name="standards"), path('standards/', include('standards.urls'), name="standards"),
path('news/', include('news.urls'), name="dashboard"), path('news/', include('news.urls'), name="dashboard"),

View File

@ -14,6 +14,10 @@
<a href="/news/news/{{notification.elementid}}/single" class="" style="text-decoration: none; color: #000000"> <a href="/news/news/{{notification.elementid}}/single" class="" style="text-decoration: none; color: #000000">
{{notification.notificationtext}} {{notification.notificationtext}}
</a><br /> </a><br />
{% elif notification.notificationtype == "newstandard" %}
<a href="/standards/standard/{{notification.elementid}}/single" class="" style="text-decoration: none; color: #000000">
{{notification.notificationtext}}
</a><br />
{% elif notification.notificationtype == "messagereceived" %} {% elif notification.notificationtype == "messagereceived" %}
<a href="/messages/sl/{{notification.elementid}}" class="" style="text-decoration: none; color: #000000"> <a href="/messages/sl/{{notification.elementid}}" class="" style="text-decoration: none; color: #000000">
{{notification.notificationtext}} {{notification.notificationtext}}

View File

@ -20,7 +20,9 @@ def CheckNotifications(request):
if notify.notificationtype == "agencynews": if notify.notificationtype == "agencynews":
elelink = "news/news/" + str(notify.elementid) + "/single" elelink = "news/news/" + str(notify.elementid) + "/single"
elif notify.notificationtype == "messagereceived": elif notify.notificationtype == "messagereceived":
elelink = "messages/sl/" + str(notify.elementid) elelink = "messages/sl/" + str(notify.elementid)
elif notify.notificationtype == "newstandard":
elelink = "standards/standard/" + str(notify.elementid) + "/single"
else: else:
elelink = "notifications/showallnotificaions/" elelink = "notifications/showallnotificaions/"
@ -55,7 +57,9 @@ def GetBasicNotifications(request):
if notify.notificationtype == "agencynews": if notify.notificationtype == "agencynews":
elelink = "news/news/" + str(notify.elementid) + "/single" elelink = "news/news/" + str(notify.elementid) + "/single"
elif notify.notificationtype == "messagereceived": elif notify.notificationtype == "messagereceived":
elelink = "messages/sl/" + str(notify.elementid) elelink = "messages/sl/" + str(notify.elementid)
elif notify.notificationtype == "newstandard":
elelink = "standards/standard/" + str(notify.elementid) + "/single"
else: else:
elelink = "notifications/showallnotificaions/" elelink = "notifications/showallnotificaions/"

View File

@ -11,11 +11,16 @@
Achtung! {{invisible_users}} Mitarbeiter sind anderen Mitarbeitern untergeordnet, die nicht im Organigramm sichtbar sein sollen. Bitte prüfen sie die Zuordnung der übergeordneten Mitarbeiter! Achtung! {{invisible_users}} Mitarbeiter sind anderen Mitarbeitern untergeordnet, die nicht im Organigramm sichtbar sein sollen. Bitte prüfen sie die Zuordnung der übergeordneten Mitarbeiter!
</div> </div>
{% endif %} {% endif %}
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<div id="diagram"></div> <div id="diagram" class="diagram_class"></div>
</div> </div>
</div> </div>
<style type="text/css">
div.diagram_class {
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
@ -53,7 +58,6 @@ for(i = 0; i < data.length; i++){
//Creates nested array from data //Creates nested array from data
function unflatten(arr) { function unflatten(arr) {
console.log(arr);
var tree = [], var tree = [],
mappedArr = {}, mappedArr = {},
arrElem, arrElem,
@ -117,5 +121,7 @@ function goToUser(id){
} }
$('#diagram').append(html.join('')); $('#diagram').append(html.join(''));
</script> </script>
{% endblock content %} {% endblock content %}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

4
organizer/apps.py Normal file
View File

@ -0,0 +1,4 @@
from django.apps import AppConfig
class OrganizerConfig(AppConfig):
name = 'organizer'

93
organizer/forms.py Normal file
View File

@ -0,0 +1,93 @@
from django import forms
from django.forms import ModelForm
from .models import QuickLinks, AGContacts, AGPassword
class OrganizerAddQlForm(forms.ModelForm):
class Meta:
model =QuickLinks
labels = {
"name" : "Name",
"link" : "Weblink",
#"logo" : "Logo",
}
#fields = ['name', 'link', 'logo']
fields = ['name', 'link']
# CONTACTS
class OrganizerAddContact(forms.ModelForm):
class Meta:
model = AGContacts
labels = {
'first_name' : "Vorname",
'last_name' : "Nachname",
'mail' : "E-Mailadresse",
'phone1' : "Telefon 1",
'phone2' : "Telefon 2",
'street' : "Straße und Hausnummer",
'city' : "Stadt",
'plz' : "PLZ",
'desc' : "Anmerkungen"
}
fields = ['first_name', 'last_name', 'mail', 'phone1', 'phone2', 'street', 'plz', 'city', 'desc']
def __init__(self, *args, **kwargs):
super(OrganizerAddContact, self).__init__(*args, **kwargs)
self.fields['phone1'].required = False
self.fields['phone2'].required = False
self.fields['desc'].widget.attrs['rows'] = 4
class OrganizerUpdateContact(forms.ModelForm):
class Meta:
model = AGContacts
labels = {
'first_name' : "Vorname",
'last_name' : "Nachname",
'mail' : "E-Mailadresse",
'phone1' : "Telefon 1",
'phone2' : "Telefon 2",
'street' : "Straße und Hausnummer",
'city' : "Stadt",
'plz' : "PLZ",
'desc' : "Anmerkungen"
}
fields = ['first_name', 'last_name', 'mail', 'phone1', 'phone2', 'street', 'plz', 'city', 'desc']
def __init__(self, *args, **kwargs):
super(OrganizerUpdateContact, self).__init__(*args, **kwargs)
self.fields['phone1'].required = False
self.fields['phone2'].required = False
self.fields['desc'].widget.attrs['rows'] = 4
# PASSWORDS
class AddAGPassword(forms.ModelForm):
class Meta:
model = AGPassword
labels = {
'name' : "Name der Anwendung",
'agpass_username' : "Benutzername in der Anwendung",
'compass' : "Passwort in der Anwendung",
'link' : "Weblink zur Anwendung"
}
fields = ['name', 'agpass_username', 'compass', 'link']
#widgets = {
# 'compass': forms.PasswordInput()
# }
def __init__(self, *args, **kwargs):
super(AddAGPassword, self).__init__(*args, **kwargs)
self.fields['link'].required = False

View File

@ -0,0 +1,26 @@
# Generated by Django 3.0.4 on 2020-03-22 19:57
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='QuickLinks',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('link', models.CharField(max_length=200)),
('logo', models.ImageField(blank=True, default='agencymain/linkdefault.png', upload_to='agencymain')),
('agency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='users.Agency')),
],
),
]

View File

@ -0,0 +1,31 @@
# Generated by Django 3.0.4 on 2020-03-25 19:04
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0006_auto_20200325_1655'),
('organizer', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='AGContacts',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('first_name', models.CharField(default='', max_length=200)),
('last_name', models.CharField(default='', max_length=200)),
('mail', models.CharField(default='', max_length=200)),
('phone1', models.CharField(default='', max_length=200)),
('phone2', models.CharField(default='', max_length=200)),
('street', models.CharField(blank=True, default='', max_length=200)),
('city', models.CharField(blank=True, default='', max_length=200)),
('plz', models.CharField(blank=True, default='', max_length=5)),
('desc', models.TextField(blank=True, max_length=3000)),
('agency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='users.Agency')),
],
),
]

View File

@ -0,0 +1,26 @@
# Generated by Django 3.0.4 on 2020-03-25 23:00
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0006_auto_20200325_1655'),
('organizer', '0002_agcontacts'),
]
operations = [
migrations.CreateModel(
name='AGPassword',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='', max_length=200)),
('compass', models.CharField(default='', max_length=200)),
('link', models.CharField(default='', max_length=200)),
('agency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='users.Agency')),
('visibleby', models.ManyToManyField(blank=True, to='users.AgencyGroup')),
],
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.4 on 2020-03-25 23:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('organizer', '0003_agpassword'),
]
operations = [
migrations.AddField(
model_name='agpassword',
name='usernname',
field=models.CharField(default='', max_length=200),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.4 on 2020-03-25 23:05
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('organizer', '0004_agpassword_usernname'),
]
operations = [
migrations.RenameField(
model_name='agpassword',
old_name='usernname',
new_name='agpass_username',
),
]

72
organizer/models.py Normal file
View File

@ -0,0 +1,72 @@
from django.db import models
from users.models import Agency, AgencyGroup
from django.urls import reverse
from colorful.fields import RGBColorField
from django.contrib.auth.models import User
import datetime
'''
Model Quicklinks
Verwaltet alle gespeicherten Bereiche für die Agentur. Wird eine neue erstellt,
wird dieser die Agency zugewiesen. Das Farb-Feld ist für später, damit im
Ogranigramm eine Farbe für den jeweiligen Bereich festgelegt wird.
users speichert alle primary-Keys der User, welche diesem Bereich zugeordnet sind!
'''
class QuickLinks(models.Model):
# Wenn die Area gelöscht wird, wird NICHT die Agency gelöscht
agency = models.ForeignKey(Agency, on_delete=models.PROTECT)
name = models.CharField(max_length=200, blank=False)
link = models.CharField(max_length=200, blank=False)
logo = models.ImageField(default='agencymain/linkdefault.png', upload_to='agencymain', blank=True)
def __str__(self):
return f'{self.name}'
def get_absolute_url(self):
return reverse('ql-update', kwargs={'pk':self.pk})
@property
def get_photo_url(self):
if self.logo and hasattr(self.logo, 'url'):
return self.logo.url
else:
return "/media/agencymain/linkdefault.png"
class AGContacts(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.PROTECT)
first_name = models.CharField(default="", max_length=200, blank=False)
last_name = models.CharField(default="", max_length=200, blank=False)
mail = models.CharField(default="", max_length=200, blank=False)
phone1 = models.CharField(default="", max_length=200, blank=False)
phone2 = models.CharField(default="", max_length=200, blank=False)
street = models.CharField(default="", max_length=200, blank=True)
city = models.CharField(default="", max_length=200, blank=True)
plz = models.CharField(default="", max_length=5, blank=True)
desc = models.TextField(max_length=3000, blank=True)
def __str__(self):
return f'{self.first_name + " " + self.last_name}'
def get_absolute_url(self):
return reverse('cont-update', kwargs={'pk':self.pk})
class AGPassword(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.PROTECT)
name = models.CharField(default="", max_length=200, blank=False)
agpass_username = models.CharField(default="", max_length=200, blank=False)
compass = models.CharField(default="", max_length=200, blank=False)
link = models.CharField(default="", max_length=200, blank=False)
visibleby = models.ManyToManyField(AgencyGroup, blank=True)
def __str__(self):
return f'{self.name}'
def get_absolute_url(self):
return reverse('aggpass-update', kwargs={'pk':self.pk})

View File

@ -0,0 +1,19 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_organizer %}
<div class="content-section col-6">
<h3>Passwort anlegen</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form|crispy}}
<hr>
<button type="submit" class="btn btn-success">Passwort speichern</button>&nbsp;
<a class="btn" href="{% url 'organizer-management' %} ">Abbrechen</a>
</form>
</div>
{% else %}
<h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,24 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_organizer %}
<div class="content-section">
<div class="media">
<div class="media-body">
<h2 class="account-heading">Passwort {{ object.name }} löschen?</h2>
<hr>
</div>
</div>
<!-- Für das Speichern der Bilder enctype -->
<form method="POST">
{% csrf_token %}
<div class="form-group">
<button type="submit" class="btn btn-danger">Passwort löschen</button>&nbsp;
<a href="{% url 'organizer-management' %}" class="btn btn-success">Abbrechen</a>
</div>
</form>
</div>
{% else %}
<h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,21 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_organizer %}
<div class="content-section col-12">
<h3>Passwort aktualisieren</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="row"><div class="col-4">
{{form|crispy}}
<hr>
<button type="submit" class="btn btn-success">Passwort aktualisieren</button>&nbsp;
<a class="btn" href="{% url 'organizer-management' %}">Abbrechen</a>
</form>
</div>
{% else %}
<h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,28 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_organizer %}
<div class="content-section col-9">
<h3>Kontakt anlegen</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="row"><div class="col-4">
{% for field in form %}
{% if forloop.counter|divisibleby:6 %}
</div><div class="col-4">
{{field|as_crispy_field }}
{% else %}
{{field|as_crispy_field }}
{% endif %}
{% endfor %}
</div></div>
<hr>
<button type="submit" class="btn btn-success">Kontakt speichern</button>&nbsp;
<a class="btn" href="{% url 'organizer-management' %} ">Abbrechen</a>
</form>
</div>
{% else %}
<h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,24 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_organizer %}
<div class="content-section">
<div class="media">
<div class="media-body">
<h2 class="account-heading">Kontakt {{ object.first_name }} {{ object.last_name }} löschen?</h2>
<hr>
</div>
</div>
<!-- Für das Speichern der Bilder enctype -->
<form method="POST">
{% csrf_token %}
<div class="form-group">
<button type="submit" class="btn btn-danger">Kontakt löschen</button>&nbsp;
<a href="{% url 'organizer-management' %}" class="btn btn-success">Abbrechen</a>
</div>
</form>
</div>
{% else %}
<h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,29 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_organizer %}
<div class="content-section col-12">
<h3>Kontakt aktualisieren</h3>
<hr>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="row"><div class="col-4">
{% for field in form %}
{% if forloop.counter|divisibleby:6 %}
</div><div class="col-4">
{{field|as_crispy_field }}
{% else %}
{{field|as_crispy_field }}
{% endif %}
{% endfor %}
</div></div>
<hr>
<button type="submit" class="btn btn-success">Kontakt aktualisieren</button>&nbsp;
<a class="btn" href="{% url 'organizer-management' %}">Abbrechen</a>
</form>
</div>
{% else %}
<h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,103 @@
{% load counter_tag %}
<div class="row">
<div class="content-section col-12">
<div class="row"><div class="content-section col-12">
{% if user|usergperm:"moduleorganizer" %}
<a class="btn btn-primary mb-3" href="{% url 'addcontact' %}"><i class="fas fa-plus"></i>&nbsp;Kontakt</a>
{% endif %}
<div class="form-group mb-2">
<input class="form-control" id="contacts_search" style="max-width: 400px;" size="20" type="text" onkeyup="javascript:checkSearchContactCards()" placeholder="Suche nach Kontakt...">
</div>
<hr>
</div></div>
{% for agc in contacts %}
<div class="card col-3 mr-1 mb-2 contactscards" style="float: left;" id="card_{{agc.pk}}" name="{{agc.first_name}} {{agc.last_name}}">
<div class="card-body">
<h5 class="card-title" data-toggle="modal" data-target="#infos_{{agc.pk}}"><a href="#">{{agc.first_name}} {{agc.last_name}}
</a>
</h5>
<p class="card-text">
{% if agc.mail|length > 0 %}
E-Mailadresse: <a href="mailto:{{agc.mail}}">{{agc.mail}}</a><br/>
{% endif %}
{% if agc.phone1|length > 0 %}
Telefon 1: <a href="tel::{{agc.phone1}}">{{agc.phone1}}</a>
{% endif %}
</p>
<span style="float: right">
{% if user|usergperm:"moduleorganizer" %}
<a style="float: right" class="btn btn-secondary btn-sm ml-2" href="{% url 'cont-delete' agc.pk %}"><small><i class="fas fa-trash"></i></small></a>
<a style="float: right" class="btn btn-secondary btn-sm " href="{% url 'cont-update' agc.pk %}"><small><i class="fas fa-pen"></i></small></a>
{% endif %}
</span>
</div>
</div>
{% endfor %}
</div>
</div>
{% for agc in contacts %}
<div class="modal fade " id="infos_{{agc.pk}}" tabindex="-1" role="dialog" data-backdrop="static" aria-hidden="true">
<div class="modal-dialog " role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">{{agc.first_name}} {{agc.last_name}}</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 agc.mail|length > 0 %}
E-Mailadresse: <a href="mailto:{{agc.mail}}">{{agc.mail}}</a><br />
{% endif %}
{% if agc.phone1|length > 0 %}
Telefon 1: <a href="tel::{{agc.phone1}}">{{agc.phone1}}</a><br />
{% endif %}
{% if agc.phone2|length > 0 %}
Telefon 1: <a href="tel::{{agc.phone2}}">{{agc.phone2}}</a><br />
{% endif %}
{% if agc.street|length > 0 %}
Adresse: {{agc.street}} {{agc.plz}} {{agc.city}} <br />
{% endif %}
{% if agc.desc|length > 0 %}
Anmerkungen: {{agc.desc}}<br />
{% endif %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success" data-dismiss="modal">Schließen</button>
</div>
</div>
</div>
</div>
{% endfor %}
<script>
//SEARCH CONTACTS
var contactscards = $(".contactscards");
function checkSearchContactCards(){
if($("#contacts_search").val().length > 0)
{
for(i = 0; i < contactscards.length; i++){
var cardname = contactscards[i].getAttribute("name").toLowerCase();
var value = $("#contacts_search").val().toLowerCase();
if(cardname.indexOf(value) == -1){
$("#" + contactscards[i].getAttribute("id")).hide();
}
else{
$("#" + contactscards[i].getAttribute("id")).show();
}
}
}else{
for(i = 0; i < contactscards.length; i++){
$("#" + contactscards[i].getAttribute("id")).show();
}
}
}
</script>

View File

@ -0,0 +1,107 @@
{% extends "users/base.html" %}
{% load counter_tag %}
{% block content %}
{% if request.user.profile.agency.module_organizer %}
<div class="content-section col-12">
<h3>Organizer{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verwalten Sie hier Quicklinks, Kontakte und Passwörter." class="far fa-question-circle"></i></small>{% endif %}</h3>
<hr>
<ul class="nav nav-tabs" id="organizerTabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="quicklinks-tab" data-toggle="tab" href="#quicklinks" role="tab" aria-controls="quicklinks" aria-selected="false" >Quicklinks</a>
</li>
<li class="nav-item">
<a class="nav-link" id="contacts-tab" data-toggle="tab" href="#contacts" role="tab" aria-controls="contacts" aria-selected="false" >Kontakte</a>
</li>
<li class="nav-item">
<a class="nav-link" id="passwords-tab" data-toggle="tab" href="#passwords" role="tab" aria-controls="passwords" aria-selected="false" >Passwörter</a>
</li>
</ul>
<div class="tab-content" id="organizerTabscontent">
<div class="tab-pane fade show" id="quicklinks" role="tabpanel" aria-labelledby="quicklinks-tab">
<h5 class="mt-3">Quicklinks{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verwalten Sie hier Links auf andere Webseiten." class="far fa-question-circle"></i></small>{% endif %}</h5>
<hr>
{% block quicklinks_content %}
{% include "organizer/quicklinks_content.html" %}
{% endblock %}
</div>
<div class="tab-pane fade show" id="contacts" role="tabpanel" aria-labelledby="contacts-tab">
<h5 class="mt-3">Kontakte{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Speichern Sie hier wichtige Kontakte." class="far fa-question-circle"></i></small>{% endif %}</h5>
<hr>
{% block contacts_content %}
{% include "organizer/contacts_content.html" %}
{% endblock %}
</div>
<div class="tab-pane fade show" id="passwords" role="tabpanel" aria-labelledby="passwords-tab">
<h5 class="mt-3">Passwörter{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Speichern Sie hier Passwörter für andere Portale, die für ihre gessamte Agentur zugreifbar sein sollen. Sie können die Einsicht der Passwörter mit entsprechenden Gruppen einschränken." class="far fa-question-circle"></i></small>{% endif %}</h5>
<hr>
{% block passwords_content %}
{% include "organizer/passwords_content.html" %}
{% endblock %}
</div>
</div>
</div>
<script>
$('#organizerTabs a').on('click', function (e) {
e.preventDefault();
$(this).tab('show');
lastview_name = $(this)[0]['hash'].substring(1);
localStorage.setItem('activeTab', lastview_name);
});
$(document).ready(function(){
var activeTab = localStorage.getItem('activeTab');
if(activeTab){
if($('#' + activeTab).find().prevObject.length != 0){
$('#' + activeTab).tab('show');
$(".nav-link").removeClass("active");
$("#" + activeTab + "-tab").addClass("active");
}
else{
$("#quicklinks-tab").addClass("active");
$('#quicklinks').tab('show');
}
}
else{
$("#quicklinks-tab").addClass("active");
$('#quicklinks').tab('show');
}
});
function saveDefQL(){
$.ajax(
{
type: "GET",
url: "lerg/",
data:{
action: "adddefql"
},
success: function( data )
{
location.reload();
}
});
}
</script>
{% else %}
<h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,107 @@
{% load counter_tag %}
<div class="row">
<div class="content-section col-10">
<div class="row"><div class="content-section col-9">
{% if user|usergperm:"moduleorganizer" %}
<a class="btn btn-primary mb-3" href="{% url 'add-agpass' %}"><i class="fas fa-plus"></i>&nbsp;Passwort</a>
{% endif %}
<div class="form-group mb-2">
<input class="form-control" id="passwords_search" style="max-width: 400px;" size="20" type="text" onkeyup="" placeholder="Suche nach Passwort...">
</div>
</div></div>
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Link</th>
<th scope="col">Benutzername</th>
<th scope="col">Passwort</th>
{% if user|usergperm:"moduleorganizer" %}
<th scope="col">&nbsp;</th>
{% endif %}
</tr>
</thead>
<tbody id="table_passwords">
{% for ap in agpass %}
<tr>
<td>{{ap.name }}</td>
<td><a href="{{ap.link }}" target="_blank">{{ap.link}}</a></td>
<td>
<span id="uname_cl_{{ap.pk}}">{{ap.agpass_username }}</span>
<a href="#" onclick="javascript:copyUsernameToCB({{ap.pk}})"><i class="far fa-copy"></i></a>
<span id="uname_cl_cop_{{ap.pk}}" style="display: none;">Kopiert!</span>
</td>
<td><span id="pass_cl_{{ap.pk}}" style="display: none;">{{ap.compass}}</span><span id="pass_{{ap.pk}}">*********</span>
<a href="#" onclick="javascript:showAgPass({{ap.pk}})"><i class="far fa-eye"></i></a>&nbsp;&nbsp;&nbsp;
<a href="#" onclick="javascript:copyPassToCB({{ap.pk}})"><i class="far fa-copy"></i></a>
<span id="pass_cl_cop_{{ap.pk}}" style="display: none;">Kopiert!</span>
</td>
<td>
{% if user|usergperm:"moduleorganizer" %}
<div class="dropdown no-arrow">
<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 'aggpass-update' ap.pk %}">Bearbeiten</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="{% url 'pass-delete' ap.pk %}" >Löschen</a>
</div>
</div>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
function showAgPass(id){
$("#pass_" + id).toggle();
$("#pass_cl_" + id).toggle();
}
function copyPassToCB(id){
var val = $("#pass_cl_" + id).html();
var $temp = $("<input>");
$("body").append($temp);
$temp.val(val).select();
document.execCommand("copy");
$temp.remove();
$("#pass_cl_cop_" + id).show();
}
function copyUsernameToCB(id){
var val = $("#uname_cl_" + id).html();
var $temp = $("<input>");
$("body").append($temp);
$temp.val(val).select();
document.execCommand("copy");
$temp.remove();
$("#uname_cl_cop_" + id).show();
}
$(document).ready(function(){
$("#passwords_search").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#table_passwords tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>

View File

@ -1,7 +1,7 @@
{% extends "users/base.html" %} {% extends "users/base.html" %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block content %} {% block content %}
{% if request.user.profile.agency.module_quicklinks %} {% if request.user.profile.agency.module_organizer %}
<div class="content-section col-6"> <div class="content-section col-6">
<h3>Quicklink anlegen</h3> <h3>Quicklink anlegen</h3>
<hr> <hr>
@ -11,7 +11,7 @@
<hr> <hr>
<p><small>Hinweis zum Weblink: Bitte setzen Sie den vollständigen Link in das Formular!<br/>Z.B. <i>https://digitale-agentur.com</i></small></p> <p><small>Hinweis zum Weblink: Bitte setzen Sie den vollständigen Link in das Formular!<br/>Z.B. <i>https://digitale-agentur.com</i></small></p>
<button type="submit" class="btn btn-success">Quicklink speichern</button>&nbsp; <button type="submit" class="btn btn-success">Quicklink speichern</button>&nbsp;
<a class="btn" href="{% url 'ql-management' %} ">Abbrechen</a> <a class="btn" href="{% url 'organizer-management' %} ">Abbrechen</a>
</form> </form>
</div> </div>
{% else %} {% else %}

View File

@ -1,7 +1,7 @@
{% extends "users/base.html" %} {% extends "users/base.html" %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block content %} {% block content %}
{% if request.user.profile.agency.module_quicklinks %} {% if request.user.profile.agency.module_organizer %}
<div class="content-section"> <div class="content-section">
<div class="media"> <div class="media">
<div class="media-body"> <div class="media-body">
@ -14,11 +14,11 @@
{% csrf_token %} {% csrf_token %}
<div class="form-group"> <div class="form-group">
<button type="submit" class="btn btn-danger">Quicklink löschen</button>&nbsp; <button type="submit" class="btn btn-danger">Quicklink löschen</button>&nbsp;
<a href="{% url 'ql-management' %}" class="btn btn-success">Abbrechen</a> <a href="{% url 'organizer-management' %}" class="btn btn-success">Abbrechen</a>
</div> </div>
</form> </form>
</div> </div>
{% else %} {% else %}
<h3>Das Modul Quicklinks wurden in ihrer Agentur deaktiviert.</h3> <h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}

View File

@ -1,7 +1,7 @@
{% extends "users/base.html" %} {% extends "users/base.html" %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block content %} {% block content %}
{% if request.user.profile.agency.module_quicklinks %} {% if request.user.profile.agency.module_organizer %}
<div class="content-section col-6"> <div class="content-section col-6">
<h3>Quicklink aktualisieren</h3> <h3>Quicklink aktualisieren</h3>
<hr> <hr>
@ -13,10 +13,10 @@
</small> </p> </small> </p>
<button type="submit" class="btn btn-success">Quicklink aktualisieren</button>&nbsp; <button type="submit" class="btn btn-success">Quicklink aktualisieren</button>&nbsp;
<a class="btn" href="{% url 'ql-management' %} ">Abbrechen</a> <a class="btn" href="{% url 'organizer-management' %} ">Abbrechen</a>
</form> </form>
</div> </div>
{% else %} {% else %}
<h3>Das Modul Quicklinks wurden in ihrer Agentur deaktiviert.</h3> <h3>Das Modul Organizer wurden in ihrer Agentur deaktiviert.</h3>
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}

View File

@ -1,11 +1,5 @@
{% extends "users/base.html" %} {% load counter_tag %}
{% load counter_tag %} {% if user|usergperm:"moduleorganizer" %}
{% block content %}
{% if request.user.profile.agency.module_quicklinks %}
<div class="content-section col-12">
<h3>Quicklinks&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Quicklinks helfen zur schnellen Verlinkung von oft genutzten Diensten." class="far fa-question-circle"></i></small></h3>
<hr>
{% if user|usergperm:"modulequicklinks" %}
<div class="row"> <div class="row">
<div class="content-section col-4"> <div class="content-section col-4">
<a class="btn btn-primary" href="{% url 'ql-addql' %}"><i class="fas fa-plus"></i>&nbsp;Quicklink</a> <a class="btn btn-primary" href="{% url 'ql-addql' %}"><i class="fas fa-plus"></i>&nbsp;Quicklink</a>
@ -14,7 +8,7 @@
{% endif %} {% endif %}
<div class="row mt-3"> <div class="row mt-3">
<div class="form-group mb-2"> <div class="form-group mb-2">
<input class="form-control" id="tableSearch" size="50" type="text" placeholder="Suche in Tabelle..."> <input class="form-control" id="quicklinks_search" size="50" type="text" placeholder="Suche in Tabelle...">
</div> </div>
</div> </div>
<div class="row mt-3 col-9" > <div class="row mt-3 col-9" >
@ -24,20 +18,20 @@
<tr> <tr>
<th scope="col">Name</th> <th scope="col">Name</th>
<th scope="col">Link</th> <th scope="col">Link</th>
<th scope="col">Logo</th> <!--<th scope="col">Logo</th> -->
{% if perms.users.ql_management %} {% if user|usergperm:"moduleorganizer" %}
<th scope="col">&nbsp;</th> <th scope="col">&nbsp;</th>
{% endif %} {% endif %}
</tr> </tr>
</thead> </thead>
<tbody id="tableresults"> <tbody id="table_quicklinks">
{% for ql in quicklinks %} {% for ql in quicklinks %}
<tr> <tr>
<td>{{ql.name }}</td> <td>{{ql.name }}</td>
<td><a href="{{ ql.link }}" target="_blank">{{ ql.link }}</a></td> <td><a href="{{ ql.link }}" target="_blank">{{ ql.link }}</a></td>
<td><img src="{{ ql.get_photo_url }}" width="15%"></td> <!--<td><img src="{{ ql.get_photo_url }}" width="15%"></td> -->
<td> <td>
{% if perms.users.ql_management %} {% if user|usergperm:"moduleorganizer" %}
<div class="dropdown no-arrow"> <div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <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> <i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
@ -55,19 +49,21 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if perms.users.ql_management %} {% if user|usergperm:"moduleorganizer" %}
<a class="btn btn-primary" href="#" onclick="saveDefQL()">ERGO-Quicklinks laden</a> <a class="btn btn-primary" href="#" onclick="saveDefQL()">ERGO-Quicklinks laden</a>
{% endif %} {% endif %}
</div> </div>
</div> </div>
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
$("#tableSearch").on("keyup", function() { $("#quicklinks_search").on("keyup", function() {
var value = $(this).val().toLowerCase(); var value = $(this).val().toLowerCase();
$("#tableresults tr").filter(function() { $("#table_quicklinks tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1) $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
}); });
}); });
}); });
function saveDefQL(){ function saveDefQL(){
@ -85,7 +81,3 @@ function saveDefQL(){
}); });
} }
</script> </script>
{% else %}
<h3>Das Modul Quicklinks wurden in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

21
organizer/urls.py Normal file
View File

@ -0,0 +1,21 @@
from django.urls import path
from django.contrib.auth import views as auth_views
from django.contrib.auth.decorators import login_required, permission_required
from .views import OrganizerManagement, OrganizerAdd, OrganizerDeleteView, OrganizerUpdateView, OrganizerAddContact, OrganizerDelContact, OrganizerUpdateContact, OrganizerAddPassword, OrganizerDelPassword, OrganizerUpdatePassword
from . import views
'''
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
'''
urlpatterns = [
path('', OrganizerManagement.as_view(template_name="organizer/organizer_management.html"), name='organizer-management'),
path('addql/', permission_required('users.moduleorganizer')(OrganizerAdd.as_view(template_name="organizer/ql_add.html")), name='ql-addql'),
path('addcontact/', permission_required('users.moduleorganizer')(OrganizerAddContact.as_view(template_name="organizer/contact_add.html")), name='addcontact'),
path('addql/<int:pk>/delete', permission_required('users.moduleorganizer')(OrganizerDeleteView.as_view()), name='ql-delete'),
path('remco/<int:pk>/delete', permission_required('users.moduleorganizer')(OrganizerDelContact.as_view()), name='cont-delete'),
path('rempa/<int:pk>/delete', permission_required('users.moduleorganizer')(OrganizerDelPassword.as_view()), name='pass-delete'),
path('addql/<int:pk>/', permission_required('users.moduleorganizer')(OrganizerUpdateView.as_view()), name='ql-update'),
path('upco/<int:pk>/', permission_required('users.moduleorganizer')(OrganizerUpdateContact.as_view()), name='cont-update'),
path('uppass/<int:pk>/', permission_required('users.moduleorganizer')(OrganizerUpdatePassword.as_view()), name='aggpass-update'),
path('addpass/', permission_required('users.moduleorganizer')(OrganizerAddPassword.as_view(template_name="organizer/agpass_add.html")), name='add-agpass'),
path('lerg/', views.loaddefaultql, name="ql-ajaxloaddef"),
]

196
organizer/views.py Normal file
View File

@ -0,0 +1,196 @@
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView
from .models import QuickLinks, AGContacts, AGPassword
from .forms import OrganizerAddQlForm, OrganizerAddContact, OrganizerUpdateContact, AddAGPassword
from django.contrib import messages
from django.shortcuts import redirect
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.urls import reverse_lazy
# Create your views here.
class OrganizerManagement(LoginRequiredMixin, ListView):
model = QuickLinks
# Adding active_link
# Loading only user same agency
# Change context and return for template-data
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
quicklinks = QuickLinks.objects.filter(agency__pk=self.request.user.profile.agency.pk).order_by('name')
context.update({'active_link' : 'organizer', 'quicklinks' : quicklinks, 'contacts' : AGContacts.objects.filter(agency__pk=self.request.user.profile.agency.pk).order_by('last_name'), 'agpass' : AGPassword.objects.filter(agency__pk=self.request.user.profile.agency.pk).order_by('name')})
return context
class OrganizerAdd(LoginRequiredMixin, CreateView):
model = QuickLinks
success_url = reverse_lazy('organizer-management')
form_class = OrganizerAddQlForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'organizer'})
return context
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Quicklink angelegt!')
# SAVE OBJECTS TO SIGNALE!
form.instance.agency = self.request.user.profile.agency
return super().form_valid(form)
class OrganizerDeleteView(LoginRequiredMixin, DeleteView):
model = QuickLinks
success_url = reverse_lazy('organizer-management')
template_name = 'organizer/ql_confirm_delete.html'
def delete(self, request, *args, **kwargs):
response = super(OrganizerDeleteView, self).delete(request, *args, **kwargs)
messages.success(request, f'Quicklink wurde gelöscht!')
return response
def get_context_data(self, **kwargs):
context = super(OrganizerDeleteView, self).get_context_data(**kwargs)
context['active_link'] = 'organizer'
return context
class OrganizerUpdateView(LoginRequiredMixin, UpdateView):
model = QuickLinks
template_name = 'organizer/ql_update.html'
success_url = reverse_lazy('organizer-management')
form_class = OrganizerAddQlForm
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Quicklink aktualisiert!')
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super(OrganizerUpdateView, self).get_context_data(**kwargs)
context['active_link'] = 'organizer'
return context
# CONTACTS
class OrganizerAddContact(LoginRequiredMixin, CreateView):
model = AGContacts
success_url = reverse_lazy('organizer-management')
form_class = OrganizerAddContact
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'organizer'})
return context
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Kontakt angelegt!')
# SAVE OBJECTS TO SIGNALE!
form.instance.agency = self.request.user.profile.agency
return super().form_valid(form)
class OrganizerDelContact(LoginRequiredMixin, DeleteView):
model = AGContacts
success_url = reverse_lazy('organizer-management')
template_name = 'organizer/contact_delete.html'
def delete(self, request, *args, **kwargs):
response = super(OrganizerDelContact, self).delete(request, *args, **kwargs)
messages.success(request, f'Kontakt wurde gelöscht!')
return response
def get_context_data(self, **kwargs):
context = super(OrganizerDelContact, self).get_context_data(**kwargs)
context['active_link'] = 'organizer'
return context
class OrganizerUpdateContact(LoginRequiredMixin, UpdateView):
model = AGContacts
template_name = 'organizer/contact_update.html'
success_url = reverse_lazy('organizer-management')
form_class = OrganizerUpdateContact
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Kontakt aktualisiert!')
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super(OrganizerUpdateContact, self).get_context_data(**kwargs)
context['active_link'] = 'organizer'
return context
# PASSWORDS
class OrganizerAddPassword(LoginRequiredMixin, CreateView):
model = AGPassword
success_url = reverse_lazy('organizer-management')
form_class = AddAGPassword
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'organizer'})
return context
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Passwort angelegt!')
# SAVE OBJECTS TO SIGNALE!
form.instance.agency = self.request.user.profile.agency
return super().form_valid(form)
class OrganizerDelPassword(LoginRequiredMixin, DeleteView):
model = AGPassword
success_url = reverse_lazy('organizer-management')
template_name = 'organizer/agpass_delete.html'
def delete(self, request, *args, **kwargs):
response = super(OrganizerDelPassword, self).delete(request, *args, **kwargs)
messages.success(request, f'Passwort wurde gelöscht!')
return response
def get_context_data(self, **kwargs):
context = super(OrganizerDelPassword, self).get_context_data(**kwargs)
context['active_link'] = 'organizer'
return context
class OrganizerUpdatePassword(LoginRequiredMixin, UpdateView):
model = AGPassword
template_name = 'organizer/agpass_update.html'
success_url = reverse_lazy('organizer-management')
form_class = AddAGPassword
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Kontakt aktualisiert!')
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super(OrganizerUpdatePassword, self).get_context_data(**kwargs)
context['active_link'] = 'organizer'
return context
@login_required
def loaddefaultql(request):
if request.method == 'GET':
if request.GET['action'] == 'adddefql':
defaultlinks = [
["EASY", "https://easy.ergo.com "],
["ERGO Ansprechpartner Navigator", "http://ansprechpartner-navigator.de/ "],
["ERGO Lokales Marketing", "https://ergo.ergo-mein-lokales-marketing.de/marcapo_platform/WelcomePre.cms "],
["ERGO Meine Druckstücke", "https://www.ergo-meine-druckstuecke.de/?client-check=2 "],
["ERGO Vertriebsportal", "https://vertriebsportal.ergo.com/"],
["myVVE", "https://www.myvve.de/"],
["Wiki", "https://wiki.digitale-agentur.com/"]
]
for ele in defaultlinks:
print(ele[0] + " " + ele[1])
tempql = QuickLinks(agency=request.user.profile.agency, name=ele[0], link=ele[1])
tempql.save()
return redirect("ql-addql")
return redirect("ql-addql")

View File

@ -1,4 +0,0 @@
from django.apps import AppConfig
class QuicklinksConfig(AppConfig):
name = 'quicklinks'

View File

@ -1,15 +0,0 @@
from django import forms
from django.forms import ModelForm
from .models import QuickLinks
class QlAddQlForm(forms.ModelForm):
class Meta:
model =QuickLinks
labels = {
"name" : "Name",
"link" : "Weblink",
"logo" : "Logo",
}
fields = ['name', 'link', 'logo']

View File

@ -1,38 +0,0 @@
from django.db import models
from users.models import Agency
from django.urls import reverse
from colorful.fields import RGBColorField
from django.contrib.auth.models import User
import datetime
'''
Model Quicklinks
Verwaltet alle gespeicherten Bereiche für die Agentur. Wird eine neue erstellt,
wird dieser die Agency zugewiesen. Das Farb-Feld ist für später, damit im
Ogranigramm eine Farbe für den jeweiligen Bereich festgelegt wird.
users speichert alle primary-Keys der User, welche diesem Bereich zugeordnet sind!
'''
class QuickLinks(models.Model):
# Wenn die Area gelöscht wird, wird NICHT die Agency gelöscht
agency = models.ForeignKey(Agency, on_delete=models.PROTECT)
name = models.CharField(max_length=200, blank=False)
link = models.CharField(max_length=200, blank=False)
logo = models.ImageField(default='agencymain/linkdefault.png', upload_to='agencymain', blank=True)
def __str__(self):
return f'{self.name}'
def get_absolute_url(self):
return reverse('ql-update', kwargs={'pk':self.pk})
@property
def get_photo_url(self):
if self.logo and hasattr(self.logo, 'url'):
return self.logo.url
else:
return "/media/agencymain/linkdefault.png"

View File

@ -1,15 +0,0 @@
from django.urls import path
from django.contrib.auth import views as auth_views
from django.contrib.auth.decorators import login_required, permission_required
from .views import QlManagement, QlAdd, QlDeleteView, QlUpdateView
from . import views
'''
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
'''
urlpatterns = [
path('', QlManagement.as_view(template_name="quicklinks/ql_management.html"), name='ql-management'),
path('addql/', permission_required('users.modulequicklinks')(QlAdd.as_view(template_name="quicklinks/ql_add.html")), name='ql-addql'),
path('addql/<int:pk>/delete', permission_required('users.modulequicklinks')(QlDeleteView.as_view()), name='ql-delete'),
path('addql/<int:pk>/', permission_required('users.modulequicklinks')(QlUpdateView.as_view()), name='ql-update'),
path('lerg/', views.loaddefaultql, name="ql-ajaxloaddef"),
]

View File

@ -1,89 +0,0 @@
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView
from .models import QuickLinks
from .forms import QlAddQlForm
from django.contrib import messages
from django.shortcuts import redirect
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import login_required
# Create your views here.
class QlManagement(LoginRequiredMixin, ListView):
model = QuickLinks
# Adding active_link
# Loading only user same agency
# Change context and return for template-data
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
quicklinks = QuickLinks.objects.filter(agency__pk=self.request.user.profile.agency.pk).order_by('name')
context.update({'active_link' : 'quicklinks', 'quicklinks' : quicklinks})
return context
class QlAdd(LoginRequiredMixin, CreateView):
model = QuickLinks
success_url = '/ql'
form_class = QlAddQlForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : 'quicklinks'})
return context
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Quicklink angelegt!')
# SAVE OBJECTS TO SIGNALE!
form.instance.agency = self.request.user.profile.agency
return super().form_valid(form)
class QlDeleteView(LoginRequiredMixin, DeleteView):
model = QuickLinks
success_url = '/ql'
template_name = 'quicklinks/ql_confirm_delete.html'
def delete(self, request, *args, **kwargs):
response = super(QlDeleteView, self).delete(request, *args, **kwargs)
messages.success(request, f'Quicklink wurde gelöscht!')
return response
def get_context_data(self, **kwargs):
context = super(QlDeleteView, self).get_context_data(**kwargs)
context['active_link'] = 'quicklinks'
return context
class QlUpdateView(LoginRequiredMixin, UpdateView):
model = QuickLinks
template_name = 'quicklinks/ql_update.html'
success_url = '/ql'
form_class = QlAddQlForm
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Quicklink aktualisiert!')
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super(QlUpdateView, self).get_context_data(**kwargs)
context['active_link'] = 'quicklinks'
return context
@login_required
def loaddefaultql(request):
if request.method == 'GET':
if request.GET['action'] == 'adddefql':
defaultlinks = [
["EASY", "https://easy.ergo.com "],
["ERGO Ansprechpartner Navigator", "http://ansprechpartner-navigator.de/ "],
["ERGO Lokales Marketing", "https://ergo.ergo-mein-lokales-marketing.de/marcapo_platform/WelcomePre.cms "],
["ERGO Meine Druckstücke", "https://www.ergo-meine-druckstuecke.de/?client-check=2 "],
["ERGO Vertriebsportal", "https://vertriebsportal.ergo.com/"],
["myVVE", "https://www.myvve.de/"],
["Wiki", "https://wiki.digitale-agentur.com/"]
]
for ele in defaultlinks:
print(ele[0] + " " + ele[1])
tempql = QuickLinks(agency=request.user.profile.agency, name=ele[0], link=ele[1])
tempql.save()
return redirect("ql-addql")
return redirect("ql-addql")

View File

@ -22,8 +22,8 @@ class StandardAddStandard(forms.ModelForm):
"task" : "Tätigkeitsbereich", "task" : "Tätigkeitsbereich",
"content": "Inhalt", "content": "Inhalt",
"public" : "Direkt veröffentlichen?", "public" : "Direkt veröffentlichen?",
"freefield_title" : "Freifeld Titel", "freefield_title" : "Titel und Text",
"freefield_content" : "Freifeld Inhalt", "freefield_content" : "",
} }
fields = ['name', 'area', 'task', 'content', 'public',"freefield_title", "freefield_content"] fields = ['name', 'area', 'task', 'content', 'public',"freefield_title", "freefield_content"]
@ -91,8 +91,8 @@ class StandardUpdateStandard(forms.ModelForm):
"area" : "Übergeordneter Bereich", "area" : "Übergeordneter Bereich",
"task" : "Tätigkeitsbereich", "task" : "Tätigkeitsbereich",
"content": "Inhalt", "content": "Inhalt",
"freefield_title" : "Freifeld Titel", "freefield_title" : "Titel und Text",
"freefield_content" : "Freifeld Inhalt", "freefield_content" : "",
} }
fields = ['name', 'area', 'task', 'content',"freefield_title", "freefield_content"] fields = ['name', 'area', 'task', 'content',"freefield_title", "freefield_content"]
''' '''

View File

@ -59,4 +59,4 @@ class Standards(models.Model):
# Hier Path für Templates des Models mit Parametern # Hier Path für Templates des Models mit Parametern
def get_absolute_url(self): def get_absolute_url(self):
return reverse('standards-update', kwargs={'pk':self.pk}) return reverse('standards-update', kwargs={'pk':self.pk})

View File

@ -12,9 +12,13 @@
{% if field.is_hidden == False %} {% if field.is_hidden == False %}
{% if forloop.counter|divisibleby:6 %} {% if forloop.counter|divisibleby:6 %}
</div><div class="col-3"> </div><div class="col-3">
{{field|as_crispy_field }} {% if field.name != 'freefield_content' and field.name != 'freefield_title' %}
{{field|as_crispy_field }}
{% endif %}
{% else %} {% else %}
{{field|as_crispy_field }} {% if field.name != 'freefield_content' and field.name != 'freefield_title' %}
{{field|as_crispy_field }}
{% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
@ -26,14 +30,60 @@
{% endfor %} {% endfor %}
<button type="button" class="btn btn-primary mb-2" onclick="javascript:changeAddedUsers()">Mitarbeiter zuweisen</button>
<!-- COLLAPSE AREA FOR GROUPS FILES AND LINKED STANDARDS --> <!-- COLLAPSE AREA FOR GROUPS FILES AND LINKED STANDARDS -->
<div class="accordion" id="additionalStandardInfos"> <div class="accordion" id="additionalStandardInfos">
<div class="card">
<div class="card-header" id="st_freefield">
<h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#freefield_content" aria-expanded="false" aria-controls="freefield_content">
<i class="fas fa-file-alt"></i>&nbsp;Freifeld{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Vergeben Sie für ein freies Textfeld einen Titel und einen entsprechenden Inhalt." class="far fa-question-circle"></i></small>{% endif %}
</button>
</h5>
</div>
<div id="freefield_content" class="collapse" aria-labelledby="st_freefield" data-parent="#additionalStandardInfos">
<div class="card-body">
{{ normalForm.freefield_title|as_crispy_field }}
{{ normalForm.freefield_content|as_crispy_field }}
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="st_useraut">
<h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#useraut_content" aria-expanded="false" aria-controls="useraut_content">
<i class="fas fa-user"></i>&nbsp;Mitarbeiterzuweisung{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Weisen Sie dem Standard verantwortliche, ausführende und vertretende Mitarbeiter zu." class="far fa-question-circle"></i></small>{% endif %}
</button>
</h5>
</div>
<div id="useraut_content" class="collapse" aria-labelledby="st_useraut" data-parent="#additionalStandardInfos">
<div class="card-body">
<button type="button" class="btn btn-primary mb-2" onclick="javascript:changeAddedUsers()">Mitarbeiter zuweisen</button>
</div>
</div>
</div>
<div class="card"> <div class="card">
<div class="card-header" id="st_groups"> <div class="card-header" id="st_groups">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#stgroups_content" aria-expanded="false" aria-controls="stgroups_content"> <button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#stgroups_content" aria-expanded="false" aria-controls="stgroups_content">
Gruppen{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, welche Gruppe diesen Standard sehen kann. Ist keine ausgewählt, ist der Standard für alle sichtbar." class="far fa-question-circle"></i></small>{% endif %} <i class="fas fa-lock"></i>&nbsp;Zugriffsbeschränkung{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, welche Gruppe diesen Standard sehen kann. Ist keine ausgewählt, ist der Standard für alle sichtbar." class="far fa-question-circle"></i></small>{% endif %}
</button> </button>
</h5> </h5>
</div> </div>
@ -54,7 +104,7 @@
<div class="card-header" id="st_files"> <div class="card-header" id="st_files">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#st_files_content" aria-expanded="false" aria-controls="st_files_content"> <button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#st_files_content" aria-expanded="false" aria-controls="st_files_content">
Dateien{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Fügen Sie ihren Standards Dateien zu. Diese liegen entweder bereits unter Dateien oder können iher direkt hochgeladen werden. Neu hochgeladene Dateien werden im Heimverzeichnis gespeichert." class="far fa-question-circle"></i></small>{% endif %} <i class="fas fa-file"></i>&nbsp;Dateien{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Fügen Sie ihren Standards Dateien zu. Diese liegen entweder bereits unter Dateien oder können iher direkt hochgeladen werden. Neu hochgeladene Dateien werden im Heimverzeichnis gespeichert." class="far fa-question-circle"></i></small>{% endif %}
</button> </button>
</h5> </h5>
</div> </div>
@ -91,7 +141,7 @@
<div class="card-header" id="st_linked"> <div class="card-header" id="st_linked">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#st_linked_content" aria-expanded="false" aria-controls="st_linked_content"> <button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#st_linked_content" aria-expanded="false" aria-controls="st_linked_content">
Standards{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verlinken Sie hier andere Standards, die etwas mit diesem Standard zutun haben." class="far fa-question-circle"></i></small>{% endif %} <i class="fas fa-fw fa-lightbulb"></i>&nbsp;Standards{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verlinken Sie hier andere Standards, die etwas mit diesem Standard zutun haben." class="far fa-question-circle"></i></small>{% endif %}
</button> </button>
</h5> </h5>
</div> </div>
@ -250,6 +300,24 @@
</div> </div>
</div> </div>
<!-- UPLOADING PROCESS -->
<div class="modal fade" id="uploadModalProgress" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Hochladen</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<i class="fas fa-spinner fa-spin"></i> Datei wird hochgeladen...
</div>
</div>
</div>
</div>
<script type="text/javascript"> <script type="text/javascript">
var ua = window.navigator.userAgent; var ua = window.navigator.userAgent;
var isIE = /MSIE|Trident/.test(ua); var isIE = /MSIE|Trident/.test(ua);
@ -444,14 +512,20 @@ function uploadAction(filetodo){
cache: false, cache: false,
processData: false, processData: false,
contentType: false, contentType: false,
beforeSend: function(){
$("#uploadModalProgress").modal("toggle");
},
success: function(data) { success: function(data) {
if(data["success"] == true){ if(data["success"] == true){
actualFiles.push(String(data["data"]["savedobj_id"])); setTimeout(function(){
$("#id_added_files").val(actualFiles); $("#uploadModalProgress").modal("toggle");
$("#linkedfiles") .append('<tr id="fileadded_'+data["data"]["savedobj_id"]+'"><td>' + data["data"]["savedobj_name"] + '</td><td><button type="button" class="btn btn-danger btn-sm" onclick="javascript:remFile('+data["data"]["savedobj_id"]+', \''+data["data"]["savedobj_name"]+'\')"><i class="fas fa-trash-alt"></i></button></td></tr>'); actualFiles.push(String(data["data"]["savedobj_id"]));
$("#id_added_files").val(actualFiles);
$("#linkedfiles") .append('<tr id="fileadded_'+data["data"]["savedobj_id"]+'"><td>' + data["data"]["savedobj_name"] + '</td><td><button type="button" class="btn btn-danger btn-sm" onclick="javascript:remFile('+data["data"]["savedobj_id"]+', \''+data["data"]["savedobj_name"]+'\')"><i class="fas fa-trash-alt"></i></button></td></tr>');
}, 1000);
} }
else{ else{
$("#forbiddenFileType").modal("toggle") $("#forbiddenFileType").modal("toggle")
} }
} }
}); });

View File

@ -187,10 +187,38 @@
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function(){
$('[data-toggle="popover"]').popover();
$('#area_tabs li:first-child a').tab('show');
$('#area_tabs a').on('click', function (e) {
e.preventDefault();
$(this).tab('show');
lastview_name = $(this)[0]['hash'].substring(1);
localStorage.setItem('activeTab', lastview_name);
});
$(document).ready(function(){
var activeTab = localStorage.getItem('activeTab');
if(activeTab){
if($('#' + activeTab).find().prevObject.length != 0){
$('#' + activeTab).tab('show');
$(".nav-link").removeClass("active");
areaid = activeTab.split("_")[1];
$("#" + areaid).addClass("active");
}
else{
$('#area_tabs li:first-child a').tab('show');
}
}
else{
$('#area_tabs li:first-child a').tab('show');
}
$('[data-toggle="popover"]').popover();
$("#tableSearch").on("keyup", function() { $("#tableSearch").on("keyup", function() {
var value = $(this).val().toLowerCase(); var value = $(this).val().toLowerCase();
$("#tableresults tr").filter(function() { $("#tableresults tr").filter(function() {

View File

@ -12,20 +12,62 @@
{% for field in normalForm %} {% for field in normalForm %}
{% if forloop.counter|divisibleby:5 %} {% if forloop.counter|divisibleby:5 %}
</div><div class="col-3"> </div><div class="col-3">
{{field|as_crispy_field }} {% if field.name != 'freefield_content' and field.name != 'freefield_title' %}
{{field|as_crispy_field }}
{% endif %}
{% else %} {% else %}
{{field|as_crispy_field }} {% if field.name != 'freefield_content' and field.name != 'freefield_title' %}
{{field|as_crispy_field }}
{% endif %} {% endif %}
{% endfor %} {% endif %}
<button type="button" class="btn btn-primary mb-2" onclick="javascript:showUpdateUsersStandard()">Zugewiesene Mitarbeiter</button> {% endfor %}
<!-- COLLAPSE AREA FOR GROUPS FILES AND LINKED STANDARDS --> <!-- COLLAPSE AREA FOR GROUPS FILES AND LINKED STANDARDS -->
<div class="accordion" id="additionalStandardInfos"> <div class="accordion" id="additionalStandardInfos">
<div class="card">
<div class="card-header" id="st_freefield">
<h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#freefield_content" aria-expanded="false" aria-controls="freefield_content">
<i class="fas fa-file-alt"></i>&nbsp;Freifeld{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Vergeben Sie für ein freies Textfeld einen Titel und einen entsprechenden Inhalt." class="far fa-question-circle"></i></small>{% endif %}
</button>
</h5>
</div>
<div id="freefield_content" class="collapse" aria-labelledby="st_freefield" data-parent="#additionalStandardInfos">
<div class="card-body">
{{ normalForm.freefield_title|as_crispy_field }}
{{ normalForm.freefield_content|as_crispy_field }}
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="st_useraut">
<h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#useraut_content" aria-expanded="false" aria-controls="useraut_content">
<i class="fas fa-user"></i>&nbsp;Mitarbeiterzuweisung{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Weisen Sie dem Standard verantwortliche, ausführende und vertretende Mitarbeiter zu." class="far fa-question-circle"></i></small>{% endif %}
</button>
</h5>
</div>
<div id="useraut_content" class="collapse" aria-labelledby="st_useraut" data-parent="#additionalStandardInfos">
<div class="card-body">
<button type="button" class="btn btn-primary mb-2" onclick="javascript:showUpdateUsersStandard()">Mitarbeiter Zuweisen</button>
</div>
</div>
</div>
<div class="card"> <div class="card">
<div class="card-header" id="st_groups"> <div class="card-header" id="st_groups">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#stgroups_content" aria-expanded="false" aria-controls="stgroups_content"> <button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#stgroups_content" aria-expanded="false" aria-controls="stgroups_content">
Gruppen{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, welche Gruppe diesen Standard sehen kann. Ist keine ausgewählt, ist der Standard für alle sichtbar." class="far fa-question-circle"></i></small>{% endif %} <i class="fas fa-lock"></i>&nbsp;Zugriffsbeschränkung{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Legen Sie fest, welche Gruppe diesen Standard sehen kann. Ist keine ausgewählt, ist der Standard für alle sichtbar." class="far fa-question-circle"></i></small>{% endif %}
</button> </button>
</h5> </h5>
</div> </div>
@ -51,7 +93,7 @@
<div class="card-header" id="st_files"> <div class="card-header" id="st_files">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#st_files_content" aria-expanded="false" aria-controls="st_files_content"> <button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#st_files_content" aria-expanded="false" aria-controls="st_files_content">
Dateien{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Fügen Sie ihren Standards Dateien zu. Diese liegen entweder bereits unter Dateien oder können iher direkt hochgeladen werden. Neu hochgeladene Dateien werden im Heimverzeichnis gespeichert." class="far fa-question-circle"></i></small>{% endif %} <i class="fas fa-file"></i>&nbsp;Dateien{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Fügen Sie ihren Standards Dateien zu. Diese liegen entweder bereits unter Dateien oder können iher direkt hochgeladen werden. Neu hochgeladene Dateien werden im Heimverzeichnis gespeichert." class="far fa-question-circle"></i></small>{% endif %}
</button> </button>
</h5> </h5>
</div> </div>
@ -90,7 +132,7 @@
<div class="card-header" id="st_linked"> <div class="card-header" id="st_linked">
<h5 class="mb-0"> <h5 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#st_linked_content" aria-expanded="false" aria-controls="st_linked_content"> <button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#st_linked_content" aria-expanded="false" aria-controls="st_linked_content">
Standards{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verlinken Sie hier andere Standards, die etwas mit diesem Standard zutun haben." class="far fa-question-circle"></i></small>{% endif %} <i class="fas fa-fw fa-lightbulb"></i>&nbsp;Standards{% if request.user.profile.showtooltips %}&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verlinken Sie hier andere Standards, die etwas mit diesem Standard zutun haben." class="far fa-question-circle"></i></small>{% endif %}
</button> </button>
</h5> </h5>
</div> </div>
@ -251,6 +293,24 @@
</div> </div>
</div> </div>
<!-- UPLOADING PROCESS -->
<div class="modal fade" id="uploadModalProgress" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Hochladen</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<i class="fas fa-spinner fa-spin"></i> Datei wird hochgeladen...
</div>
</div>
</div>
</div>
<script type="text/javascript"> <script type="text/javascript">
var ua = window.navigator.userAgent; var ua = window.navigator.userAgent;
@ -530,9 +590,15 @@ function uploadAction(filetodo){
cache: false, cache: false,
processData: false, processData: false,
contentType: false, contentType: false,
beforeSend: function(){
$("#uploadModalProgress").modal("toggle");
},
success: function(data) { success: function(data) {
if(data["success"] == true){ if(data["success"] == true){
setTimeout(function(){
$("#uploadModalProgress").modal("toggle");
$("#linkedfiles") .append('<tr id="fileadded_'+data["data"]["savedobj_id"]+'"><td>' + data["data"]["savedobj_name"] + '</td><td><button type="button" class="btn btn-danger btn-sm" onclick="javascript:remFile('+data["data"]["savedobj_id"]+', \''+data["data"]["savedobj_name"]+'\')"><i class="fas fa-trash-alt"></i></button></td></tr>'); $("#linkedfiles") .append('<tr id="fileadded_'+data["data"]["savedobj_id"]+'"><td>' + data["data"]["savedobj_name"] + '</td><td><button type="button" class="btn btn-danger btn-sm" onclick="javascript:remFile('+data["data"]["savedobj_id"]+', \''+data["data"]["savedobj_name"]+'\')"><i class="fas fa-trash-alt"></i></button></td></tr>');
}, 1000);
$.ajax({ $.ajax({
url: "{% url 'update_standard_by_ajax' standard.pk %}", url: "{% url 'update_standard_by_ajax' standard.pk %}",
data: { data: {
@ -543,7 +609,7 @@ function uploadAction(filetodo){
}); });
} }
else{ else{
$("#forbiddenFileType").modal("toggle") $("#forbiddenFileType").modal("toggle")
} }
} }

View File

@ -49,7 +49,7 @@ class Agency(models.Model):
# MODULEEINSTELLUNGEN FÜR DIE AGENTUR # MODULEEINSTELLUNGEN FÜR DIE AGENTUR
module_news = models.BooleanField(default=True) module_news = models.BooleanField(default=True)
module_quicklinks = models.BooleanField(default=True) module_organizer = models.BooleanField(default=True)
module_files = models.BooleanField(default=True) module_files = models.BooleanField(default=True)
module_organigramm = models.BooleanField(default=True) module_organigramm = models.BooleanField(default=True)
module_messages = models.BooleanField(default=True) module_messages = models.BooleanField(default=True)
@ -209,7 +209,7 @@ class AgencyGroup(models.Model):
('standardmanager', 'Standards bearbeiten und freischalten'), ('standardmanager', 'Standards bearbeiten und freischalten'),
('modulenews', 'News bearbeiten und veröffentlichen'), ('modulenews', 'News bearbeiten und veröffentlichen'),
('modulesconfig', 'Module verwalten'), ('modulesconfig', 'Module verwalten'),
('modulequicklinks', 'Quicklinks bearbeiten'), ('moduleorganizer', 'Organizer bearbeiten'),
('filesmanager', 'Dateien bearbeiten'), ('filesmanager', 'Dateien bearbeiten'),
('filedirmanager', 'Ordner bearbeiten'), ('filedirmanager', 'Ordner bearbeiten'),
('filesviewer', 'Dateien lesen') ('filesviewer', 'Dateien lesen')

View File

@ -1,4 +1,4 @@
from django.db.models.signals import post_save, pre_delete, m2m_changed from django.db.models.signals import post_save, pre_delete, m2m_changed, pre_save
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from django.dispatch import receiver from django.dispatch import receiver
from .models import Profile, Agency, AgencyGroup from .models import Profile, Agency, AgencyGroup
@ -12,6 +12,7 @@ from cloud.models import DataFile
import os import os
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone
from standards.models import Standards
# Deletes all Notifications added to to delete news # Deletes all Notifications added to to delete news
@receiver(pre_delete, sender=News) @receiver(pre_delete, sender=News)
@ -101,7 +102,44 @@ def adjust_group_notifications(instance, action, reverse, model, pk_set, using,
fail_silently=False fail_silently=False
) )
# SIGNAL FOR STANDARDS POST SAVE
@receiver(post_save, sender=Standards)
def save_standard(sender, instance, **kwargs):
GLOBALSENDMAILS = True
# NEW STANDARD AND DIRECT PUBLIC
if(kwargs["created"]):
usersofagency = User.objects.filter(profile__agency__pk=instance.agency.pk)
targeturl = settings.BASE_URL + "standards/standard/" + str(instance.pk) + "/single"
if(instance.public):
for user in usersofagency:
if(user.profile.agency_new_standard_mail):
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})
if(GLOBALSENDMAILS):
send_mail(
'Agentur-Benachrichtigung',
'Hallo ' + user.first_name + ' ' + user.last_name + '! ' + notificationtext,
'support@digitale-agentur.com',
[user.email],
html_message=msg_html,
fail_silently=False
)
if(user.profile.agency_new_standard_push):
newnotification = UserNotification(touser=user, notificationtext="Neuer Agenturstandard: " + instance.name, notificationtype="newstandard", elementid=instance.pk)
newnotification.save()
# SIGNAL FOR NEWS # SIGNAL FOR NEWS
@receiver(post_save, sender=News) @receiver(post_save, sender=News)

View File

@ -80,9 +80,6 @@ body{
font-size: 2em; font-size: 2em;
} }
/* /*
FOR TREE ORGA FOR TREE ORGA
@ -94,6 +91,8 @@ body{
* {margin: 0; padding: 0;} * {margin: 0; padding: 0;}
.tree ul { .tree ul {
padding-top: 20px; position: relative; padding-top: 20px; position: relative;
@ -191,5 +190,6 @@ right connector from last child*/
border-color: #94a0b4; border-color: #94a0b4;
} }
/*Thats all. I hope you enjoyed it. /*Thats all. I hope you enjoyed it.
Thanks :)*/ Thanks :)*/

View File

@ -118,27 +118,15 @@
<span>Organigramm</span> <span>Organigramm</span>
</a> </a>
</li> </li>
<!-- {% if request.user.profile.agency.module_organizer %}
{% if active_link == 'agencyinfo' %} {% if active_link == 'organizer' %}
<li class="nav-item active">
{% else%}
<li class="nav-item">
{%endif%}
<a class="nav-link " href="#" aria-expanded="true">
<i class="fas fa-fw fa-info"></i>
<span>Agentur</span>
</a>
</li>
-->
{% if request.user.profile.agency.module_quicklinks %}
{% if active_link == 'quicklinks' %}
<li class="nav-item active"> <li class="nav-item active">
{% else%} {% else%}
<li class="nav-item"> <li class="nav-item">
{%endif%} {%endif%}
<a class="nav-link " href="{% url 'ql-management' %}" aria-expanded="true"> <a class="nav-link " href="{% url 'organizer-management' %}" aria-expanded="true">
<i class="fas fa-external-link-alt"></i> <i class="fas fa-address-book"></i>
<span>Quicklinks</span> <span>Organizer</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
@ -175,44 +163,13 @@
<!--
{% if perms.users.users_usermanagement %}
{% if active_link == 'usersmanagement' %}
<li class="nav-item active">
{% else%}
<li class="nav-item">
{%endif%}
<a class="nav-link" href="{% url 'users-management' %}">
<i class="fas fa-fw fa-users"></i>
<span>Benutzer</span></a>
</li>
{%endif%}
-->
<!--
{% if perms.users.news_management %}
{% if active_link == 'newsmanagement' %}
<li class="nav-item active">
{% else%}
<li class="nav-item">
{%endif%}
<a class="nav-link " href="{% url 'news-management' %}" aria-expanded="true">
<i class="far fa-newspaper"></i>
<span>News</span>
</a>
</li>
{%endif%}
-->
<!-- Divider -->
<!-- Sidebar Toggler (Sidebar) --> <!-- Sidebar Toggler (Sidebar) -->
<!-- <!--
<div class="text-center d-none d-md-inline"> <div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button> <button class="rounded-circle border-0" id="sidebarToggle"></button>
</div> </div>
--> -->
<style scoped> <style scoped>
#bottom_info { #bottom_info {
position: absolute; position: absolute;
@ -247,7 +204,7 @@
<a style="color: #999; text-decoration: none;" href="{% url 'impressumda' %}">Impressum</a> <a style="color: #999; text-decoration: none;" href="{% url 'impressumda' %}">Impressum</a>
</div> </div>
<div style="margin-top: 10px; margin-bottom: 5px;" class="sidebar-heading"> <div style="margin-top: 10px; margin-bottom: 5px;" class="sidebar-heading">
Version 0.8.1 Version 0.8.2
</div> </div>
</div> </div>
</ul> </ul>
@ -577,5 +534,8 @@ $(window).click(function() {
loadUnsendNotifications(); loadUnsendNotifications();
loadUnviewnNotifications(); loadUnviewnNotifications();
}); });
</script> </script>

View File

@ -45,7 +45,7 @@
<!-- Divider --> <!-- Divider -->
<hr class="sidebar-divider my-0"> <hr class="sidebar-divider my-0">
<div style="bottom: 10px; position: absolute;" class="sidebar-heading"> <div style="bottom: 10px; position: absolute;" class="sidebar-heading">
Version 0.8.1 Version 0.8.2
</div> </div>
<div style="bottom: 40px; position: absolute;" class="sidebar-heading"> <div style="bottom: 40px; position: absolute;" class="sidebar-heading">
<a style="color: #999; text-decoration: none;" href="{% url 'datenschutzda' %}">Datenschutz</a><br /> <a style="color: #999; text-decoration: none;" href="{% url 'datenschutzda' %}">Datenschutz</a><br />

View File

@ -12,7 +12,7 @@ from django.core.mail import send_mail
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
from areas.models import Areas from areas.models import Areas
from tasks.models import Tasks from tasks.models import Tasks
from quicklinks.models import QuickLinks from organizer.models import QuickLinks
from .priomodel import Prio from .priomodel import Prio
from standards.models import Standards from standards.models import Standards
from datetime import datetime from datetime import datetime
@ -113,6 +113,12 @@ def toUpdate(request):
else: else:
print("AGENCY DEF STANDARD DIR - FILESMODULE READY") print("AGENCY DEF STANDARD DIR - FILESMODULE READY")
# CHANGE RIGHTS ORGNAIZER
admingroups = AgencyGroup.objects.filter(is_admin=True)
for a in admingroups:
a.group.permissions.add(Permission.objects.get(codename="moduleorganizer"))
''' '''
DASHBOARD-View DASHBOARD-View