Organigramm getauscht und Quick-Links-Ladebutton

This commit is contained in:
holger.trampe 2020-01-18 16:33:35 +01:00
parent c6e198a590
commit 37887f153c
13 changed files with 487 additions and 111 deletions

View File

@ -1,59 +1,207 @@
{% extends "users/base.html" %}
{% load static %}
{% block content %}
<script src="https://cdn.syncfusion.com/ej2/dist/ej2.min.js" type="text/javascript"></script>
<link href="https://cdn.syncfusion.com/ej2/material.css" rel="stylesheet">
<link href="{% static 'users/css/custom.css' %}" rel="stylesheet">
<div class="content-section">
<h3>{{request.user.profile.agency.name}}</h3>
<hr>
<h4>Organigramm</h4>
<div class="text-center">
<div class="d-flex justify-content-center">
<div id="diagram"></div>
</div>
<div id="spinner" class="text-center" style="margin-top: 15%; width: 100%; height: 100%; display: none;">
<div id="spinner" class="text-center" style="margin-top: 15%; width: 100%; height: 100%; display: none;margin-left:auto;
margin-right:auto;">
<div class="spinner-border text-danger" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
<script type="text/javascript">
var data = [
{ 'id': 'parent', 'role': "", 'name': '{{request.user.profile.agency.name}}', 'color': '#71AF17', "imageUrl": ""},
{ 'id' : '{{request.user.profile.agency.pk}}', 'parent' : "", 'role': "", 'name': '{{request.user.profile.agency.name}}', 'color': '#71AF17', "imageUrl": ""},
{% for u in agencyuser %}
{% if u.profile.parent == u %}
{ 'id': '{{u.pk}}' , 'name': "{{u.first_name}} {{u.last_name}}",'role': '{{u.profile.get_func_display}}\n{{u.profile.compfunc}}', 'manager': 'parent', 'color': '#1859B7', "imageUrl": "{{u.profile.get_photo_url}}", 'userid' : '{{u.pk}}' },
{ 'id': '{{u.pk}}' , 'name': "{{u.first_name}} {{u.last_name}}",'role': '<b>{{u.profile.get_func_display}}</b></br >{{u.profile.compfunc}}', 'parent': "{{request.user.profile.agency.pk}}", 'color': '#1859B7', "imageUrl": "{{u.profile.get_photo_url}}", 'userid' : '{{u.pk}}' },
{% else %}
{ 'id': '{{u.pk}}', 'name': "{{u.first_name}} {{u.last_name}}", 'role': '{{u.profile.get_func_display}}\n{{u.profile.compfunc}}', 'manager': '{{u.profile.parent.pk}}', 'color': '#1859B7', "imageUrl": "{{u.profile.get_photo_url }}", 'userid' : '{{u.pk}}'},
{ 'id': '{{u.pk}}', 'name': "{{u.first_name}} {{u.last_name}}", 'role': '<b>{{u.profile.get_func_display}}</b></br >{{u.profile.compfunc}}', 'parent': '{{u.profile.parent.pk}}', 'color': '#1859B7', "imageUrl": "{{u.profile.get_photo_url }}", 'userid' : '{{u.pk}}'},
{% endif %}
{% endfor %}
];
var items = new ej.data.DataManager(data);
/*
var data = [
{'id' : 11, 'name' : 'AGENCY', 'parent' : "", 'children': []},
{'id' : 2, 'name' : 'Holger', 'parent' : 11, 'children' : []},
{'id' : 9, 'name' : 'Felix', 'parent' : 11, 'children' : []},
{'id' : 1, 'name' : 'Marko', 'parent' : 2, 'children' : []},
{'id' : 23, 'name' : 'Janina', 'parent' : 1, 'children' : []},
{'id' : 6, 'name' : 'Franziska', 'parent' : 1, 'children' : []},
{'id' : 12, 'name' : 'Berthold', 'parent' : 6, 'children' : []},
{'id' : 7, 'name' : 'Jürgen', 'parent' : 23, 'children' : []}
];
var diagram = new ej.diagrams.Diagram({
width: "1350px", height: "800px",
/*tool: ej.diagrams.DiagramTools.ZoomPan,*/
dataSourceSettings: {
// set the unique field from data source
id: 'id',
// set the field which is used to identify the reporting person
parentId: 'manager',
// define the employee data
dataManager: items
},
layout: {
// set the layout type
type: 'OrganizationalChart',
},
getConnectorDefaults: connectorDefaults,
setNodeTemplate: setNodeTemplate,
// hide the gridlines in the diagram
snapSettings: { constraints: ej.diagrams.SnapConstraints.None }
*/
function unflatten(arr) {
var tree = [],
mappedArr = {},
arrElem,
mappedElem;
// First map the nodes of the array to an object -> create a hash table.
for(var i = 0, len = arr.length; i < len; i++) {
arrElem = arr[i];
mappedArr[arrElem.id] = arrElem;
mappedArr[arrElem.id]['children'] = [];
}
for (var id in mappedArr) {
if (mappedArr.hasOwnProperty(id)) {
mappedElem = mappedArr[id];
// If the element is not at the root level, add it to its parent array of children.
if (mappedElem.parent) {
mappedArr[mappedElem['parent']]['children'].push(mappedElem);
}
// If the element is at the root level, add it to first level elements array.
else {
tree.push(mappedElem);
}
}
}
return tree;
}
function unflattenList(arr) {
var tree = [],
mappedArr = {},
arrElem,
mappedElem;
// First map the nodes of the array to an object -> create a hash table.
for(var i = 0, len = arr.length; i < len; i++) {
arrElem = arr[i];
mappedArr[arrElem.id] = arrElem;
mappedArr[arrElem.id]['children'] = [];
}
for (var id in mappedArr) {
if (mappedArr.hasOwnProperty(id)) {
mappedElem = mappedArr[id];
// If the element is not at the root level, add it to its parent array of children.
if (mappedElem.parent) {
mappedArr[mappedElem['parent']]['children'].push(mappedElem);
}
// If the element is at the root level, add it to first level elements array.
else {
tree.push(mappedElem);
}
}
}
return tree;
}
var html = ['<ul class="tree">'];
function createList(arr) {
html.push('<ul>');
$.each(arr, function(i, val) {
if(val.parent == ""){
html.push('<li><a href="#"><h4>' + val.name + "</h4></a>");
}
else {
html.push('<li><a href="#" onclick="goToUser('+ val.id +')"><img src="'+val.imageUrl+'" width="125px"><h5>' + val.name + "</h5></ br><small>"+val.role+"</small></a>");
}
if (val.children) {
createList(val.children)
}
html.push('</li>');
});
diagram.appendTo('#diagram');
html.push('</ul>');
}
diagram.selectionChange = goToUser
createList(unflatten(data));
for(i = 0; i < html.length; i++){
if(html[i+1] != undefined){
if(html[i] == "<ul>" && html[i+1] == "</ul>"){
html.splice(i,2);
}
}
}
function goToUser(id){
window.location.href = "/orga/single/"+id;
}
$('#diagram').append(html.join(''));
//html = addLiEle(data[0]['children'], "<ul class='tree'><li>" + data[0]['name'] + "</li><ul>");
//$("#diagram").html(html);
/*
function createList(parent, array) {
console.log(parent);
for(i = 0; i < array.length; i++){
var li = document.createElement("li"),
ul;
li.textContent = array[i].name;
parent.appendChild(li);
if (array[i].children) {
ul = document.createElement("ul");
li.appendChild(ul);
//createList(ul, array[i].id);
}
}
}*/
/*
var obj = data;
var x = "";
$.each(obj, function(index, value) {
x += '<li>'+value.parent+'</li>';
if(value.children[0]){
var s = '<ul>';
$.each(value.children, function(i, v) {
s += "<li>"+v.name+"</li>";
});
s += '</ul>'
x += s;
}
});
*/
/*
for(i = 0; i < agdata.length; i++){
//Wenn ID und PARENT gleich sind, wrid nichts gemacht
for(k = i+1; k < agdata.length; k++){
if(agdata[i]['id'] == agdata[k]['parent']){
agdata[i]['children'].push(agdata[k]);
agdata.splice(k, 1);
k = k - 1;
}
}
}
for(i = 0; i < agdata.length; i++){
if(agdata[i]['children'].length > 0){
}
}
*/
/*
function goToUser(){
if(diagram.selectedItems['nodes'][0] != undefined){
selected_id = diagram.selectedItems['nodes'][0]['properties']['data']['id'];
@ -71,83 +219,8 @@ function goToUser(){
}
}
//Define the common settings for connectors.
function connectorDefaults(connector) {
connector.targetDecorator.shape = 'None';
connector.type = 'Orthogonal';
connector.style.strokeColor = 'gray';
return connector;
}
//Funtion to add the Template of the Node.
function setNodeTemplate(obj, diagram) {
// create the stack panel
var content = new ej.diagrams.StackPanel();
content.id = obj.id + '_outerstack';
content.orientation = 'Horizontal';
content.style.strokeColor = 'gray';
content.padding = { left: 5, right: 10, top: 5, bottom: 5 };
// create the image element to map the image data from the data source
var image = new ej.diagrams.ImageElement();
if(obj['properties']['data']['id'] == 'parent'){
image.id = obj.id + '_pic';
image.width = 0; image.height = 0; image.style.strokeColor = 'none';
image.source = obj.data.imageUrl;
}
else{
image.id = obj.id + '_pic';
image.width = 75; image.height = 75; image.style.strokeColor = 'none';
image.source = obj.data.imageUrl;
}
// create the stack panel to append the text elements.
var innerStack = new ej.diagrams.StackPanel();
innerStack.style.strokeColor = 'none';
innerStack.margin = { left: 5, right: 0, top: 0, bottom: 0 };
innerStack.id = obj.id + '_innerstack';
if(obj['properties']['data']['id'] == 'parent'){
var text = new ej.diagrams.TextElement();
text.style.bold = true;
text.style.fontSize = 24;
text.id = obj.id + '_name';
text.content = obj.data.name;
}
else{
var text = new ej.diagrams.TextElement();
text.style.bold = true;
text.style.fontSize = 18;
text.id = obj.id + '_name';
text.content = obj.data.name;
}
// create the text element to map the name data from the data source
if(obj['properties']['data']['id'] == 'parent'){
var desigText = new ej.diagrams.TextElement();
desigText.id = obj.id + '_desig';
desigText.style.fontSize = 0;
desigText.content = obj.data.role;
}
else{
var desigText = new ej.diagrams.TextElement();
desigText.id = obj.id + '_desig';
desigText.style.fontSize = 16;
desigText.content = obj.data.role;
}
// create the text element to map the role data from the data source
*/
// append the text elements
innerStack.children = [text, desigText];
// append the image and inner stack elements
content.children = [image, innerStack];
return content;
}
</script>
{% endblock content %}

View File

@ -0,0 +1,153 @@
{% extends "users/base.html" %}
{% block content %}
<script src="https://cdn.syncfusion.com/ej2/dist/ej2.min.js" type="text/javascript"></script>
<link href="https://cdn.syncfusion.com/ej2/material.css" rel="stylesheet">
<div class="content-section">
<h3>{{request.user.profile.agency.name}}</h3>
<hr>
<h4>Organigramm</h4>
<div class="text-center">
<div id="diagram"></div>
</div>
<div id="spinner" class="text-center" style="margin-top: 15%; width: 100%; height: 100%; display: none;">
<div class="spinner-border text-danger" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</div>
<script type="text/javascript">
var data = [
{ 'id': 'parent', 'role': "", 'name': '{{request.user.profile.agency.name}}', 'color': '#71AF17', "imageUrl": ""},
{% for u in agencyuser %}
{% if u.profile.parent == u %}
{ 'id': '{{u.pk}}' , 'name': "{{u.first_name}} {{u.last_name}}",'role': '{{u.profile.get_func_display}}\n{{u.profile.compfunc}}', 'manager': 'parent', 'color': '#1859B7', "imageUrl": "{{u.profile.get_photo_url}}", 'userid' : '{{u.pk}}' },
{% else %}
{ 'id': '{{u.pk}}', 'name': "{{u.first_name}} {{u.last_name}}", 'role': '{{u.profile.get_func_display}}\n{{u.profile.compfunc}}', 'manager': '{{u.profile.parent.pk}}', 'color': '#1859B7', "imageUrl": "{{u.profile.get_photo_url }}", 'userid' : '{{u.pk}}'},
{% endif %}
{% endfor %}
];
var items = new ej.data.DataManager(data);
var diagram = new ej.diagrams.Diagram({
width: "1350px", height: "800px",
/*tool: ej.diagrams.DiagramTools.ZoomPan,*/
dataSourceSettings: {
// set the unique field from data source
id: 'id',
// set the field which is used to identify the reporting person
parentId: 'manager',
// define the employee data
dataManager: items
},
layout: {
// set the layout type
type: 'OrganizationalChart',
},
getConnectorDefaults: connectorDefaults,
setNodeTemplate: setNodeTemplate,
// hide the gridlines in the diagram
snapSettings: { constraints: ej.diagrams.SnapConstraints.None }
});
diagram.appendTo('#diagram');
diagram.selectionChange = goToUser
function goToUser(){
if(diagram.selectedItems['nodes'][0] != undefined){
selected_id = diagram.selectedItems['nodes'][0]['properties']['data']['id'];
if(selected_id != 'parent'){
$("#diagram").hide();
$("#spinner").show();
window.location.href = "/orga/single/"+selected_id;
}
else{
$("#diagram").hide();
$("#spinner").show();
window.location.href = "/orga/";
}
}
}
//Define the common settings for connectors.
function connectorDefaults(connector) {
connector.targetDecorator.shape = 'None';
connector.type = 'Orthogonal';
connector.style.strokeColor = 'gray';
return connector;
}
//Funtion to add the Template of the Node.
function setNodeTemplate(obj, diagram) {
// create the stack panel
var content = new ej.diagrams.StackPanel();
content.id = obj.id + '_outerstack';
content.orientation = 'Horizontal';
content.style.strokeColor = 'gray';
content.padding = { left: 5, right: 10, top: 5, bottom: 5 };
// create the image element to map the image data from the data source
var image = new ej.diagrams.ImageElement();
if(obj['properties']['data']['id'] == 'parent'){
image.id = obj.id + '_pic';
image.width = 0; image.height = 0; image.style.strokeColor = 'none';
image.source = obj.data.imageUrl;
}
else{
image.id = obj.id + '_pic';
image.width = 75; image.height = 75; image.style.strokeColor = 'none';
image.source = obj.data.imageUrl;
}
// create the stack panel to append the text elements.
var innerStack = new ej.diagrams.StackPanel();
innerStack.style.strokeColor = 'none';
innerStack.margin = { left: 5, right: 0, top: 0, bottom: 0 };
innerStack.id = obj.id + '_innerstack';
if(obj['properties']['data']['id'] == 'parent'){
var text = new ej.diagrams.TextElement();
text.style.bold = true;
text.style.fontSize = 24;
text.id = obj.id + '_name';
text.content = obj.data.name;
}
else{
var text = new ej.diagrams.TextElement();
text.style.bold = true;
text.style.fontSize = 18;
text.id = obj.id + '_name';
text.content = obj.data.name;
}
// create the text element to map the name data from the data source
if(obj['properties']['data']['id'] == 'parent'){
var desigText = new ej.diagrams.TextElement();
desigText.id = obj.id + '_desig';
desigText.style.fontSize = 0;
desigText.content = obj.data.role;
}
else{
var desigText = new ej.diagrams.TextElement();
desigText.id = obj.id + '_desig';
desigText.style.fontSize = 16;
desigText.content = obj.data.role;
}
// create the text element to map the role data from the data source
// append the text elements
innerStack.children = [text, desigText];
// append the image and inner stack elements
content.children = [image, innerStack];
return content;
}
</script>
{% endblock content %}

View File

@ -56,6 +56,9 @@
{% endfor %}
</tbody>
</table>
{% if perms.users.ql_management %}
<a class="btn btn-primary" href="#" onclick="saveDefQL()">ERGO-Quicklinks laden</a>
{% endif %}
</div>
</div>
<script>
@ -67,5 +70,20 @@ $(document).ready(function(){
});
});
});
function saveDefQL(){
$.ajax(
{
type: "GET",
url: "lerg/",
data:{
action: "adddefql"
},
success: function( data )
{
location.reload();
}
});
}
</script>
{% endblock content %}

View File

@ -2,6 +2,7 @@ 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!
'''
@ -11,5 +12,5 @@ urlpatterns = [
path('addql/', permission_required('users.ql_management')(QlAdd.as_view(template_name="quicklinks/ql_add.html")), name='ql-addql'),
path('addql/<int:pk>/delete', permission_required('users.ql_management')(QlDeleteView.as_view()), name='ql-delete'),
path('addql/<int:pk>/', permission_required('users.ql_management')(QlUpdateView.as_view()), name='ql-update'),
path('lerg/', views.loaddefaultql, name="ql-ajaxloaddef"),
]

View File

@ -4,6 +4,8 @@ from django.views.generic import CreateView, ListView, UpdateView, DetailView, D
from .models import QuickLinks
from .forms import QlAddQlForm
from django.contrib import messages
from django.shortcuts import redirect
from django.http import HttpResponse
# Create your views here.
class QlManagement(LoginRequiredMixin, ListView):
@ -65,3 +67,22 @@ class QlUpdateView(LoginRequiredMixin, UpdateView):
context = super(QlUpdateView, self).get_context_data(**kwargs)
context['active_link'] = 'quicklinks'
return context
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

@ -53,3 +53,113 @@ html h1 {
body{
background-color: #f8f9fc;
}
/*
FOR TREE ORGA
*/
/*Now the CSS*/
.profpic_orga {
max-width: 50px;
}
* {margin: 0; padding: 0;}
.tree ul {
padding-top: 20px; position: relative;
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}
.tree li {
float: left; text-align: center;
list-style-type: none;
position: relative;
padding: 20px 5px 0 5px;
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}
/*We will use ::before and ::after to draw the connectors*/
.tree li::before, .tree li::after{
content: '';
position: absolute; top: 0; right: 50%;
border-top: 2px solid #ccc;
width: 50%; height: 20px;
}
.tree li::after{
right: auto; left: 50%;
border-left: 2px solid #ccc;
}
/*We need to remove left-right connectors from elements without
any siblings*/
.tree li:only-child::after, .tree li:only-child::before {
display: none;
}
/*Remove space from the top of single children*/
.tree li:only-child{ padding-top: 0;}
/*Remove left connector from first child and
right connector from last child*/
.tree li:first-child::before, .tree li:last-child::after{
border: 0 none;
}
/*Adding back the vertical connector to the last nodes*/
.tree li:last-child::before{
border-right: 2px solid #ccc;
border-radius: 0 5px 0 0;
-webkit-border-radius: 0 5px 0 0;
-moz-border-radius: 0 5px 0 0;
}
.tree li:first-child::after{
border-radius: 5px 0 0 0;
-webkit-border-radius: 5px 0 0 0;
-moz-border-radius: 5px 0 0 0;
}
/*Time to add downward connectors from parents*/
.tree ul ul::before{
content: '';
position: absolute; top: 0; left: 50%;
border-left: 2px solid #ccc;
width: 0; height: 20px;
}
.tree li a{
border: 1px solid #ccc;
padding: 5px 10px;
text-decoration: none;
color: #666;
font-size: 1.2em;
display: inline-block;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}
/*Time for some hover effects*/
/*We will apply the hover effect the the lineage of the element also*/
.tree li a:hover, .tree li a:hover+ul li a {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}
/*Connector styles on hover*/
.tree li a:hover+ul li::after,
.tree li a:hover+ul li::before,
.tree li a:hover+ul::before,
.tree li a:hover+ul ul::before{
border-color: #94a0b4;
}
/*Thats all. I hope you enjoyed it.
Thanks :)*/

View File

@ -193,7 +193,7 @@
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
<div style="bottom: 10px; position: absolute;" class="sidebar-heading">
Version 0.7.3
Version 0.7.4
</div>
<div style="bottom: 40px; position: absolute;" class="sidebar-heading">
<a style="color: #999; text-decoration: none;" href="{% url 'datenschutzda' %}">Datenschutz</a><br />

View File

@ -27,7 +27,7 @@
<p>
{{ user.profile.compfunc }}
</p>
<h6><b>Fesetznetz</b></h6>
<h6><b>Festnetz</b></h6>
<p>
{{ user.profile.phoneland }}
</p>

View File

@ -27,7 +27,7 @@
<p>
{{ prof_user.profile.compfunc }}
</p>
<h6><b>Fesetznetz</b></h6>
<h6><b>Festnetz</b></h6>
<p>
{{ prof_user.profile.phoneland }}
</p>

View File

@ -396,7 +396,7 @@ def GlobalSearch(request):
if request.method == 'GET':
searchfor = request.GET['searchstring']
ag = request.user.profile.agency.pk
res_standard = Standards.objects.filter(agency__pk=ag, public=True).filter(name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(content__contains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(area__name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(task__name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(created_standard_by__last_name__icontains=searchfor)|Standards.objects.filter(agency__pk=ag, public=True).filter(created_standard_by__first_name__icontains=searchfor)
res_standard = Standards.objects.filter(agency__pk=ag, public=True).filter(name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(content__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(area__name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(task__name__icontains=searchfor) | Standards.objects.filter(agency__pk=ag, public=True).filter(created_standard_by__last_name__icontains=searchfor)|Standards.objects.filter(agency__pk=ag, public=True).filter(created_standard_by__first_name__icontains=searchfor)
res_areas = Areas.objects.filter(agency__pk=ag).filter(name__icontains=searchfor)
res_tasks = Tasks.objects.filter(agency__pk=ag).filter(name__icontains=searchfor) |Tasks.objects.filter(agency__pk=ag).filter(area__name__icontains=searchfor)
res_pers = User.objects.filter(profile__agency__pk=ag).filter(first_name__icontains=searchfor) | User.objects.filter(profile__agency__pk=ag).filter(last_name__icontains=searchfor)