Erste Adminoberfläche implementiert

This commit is contained in:
holger.trampe 2020-10-09 17:24:57 +02:00
parent 847f01fb1f
commit 9ff6268b8a
18 changed files with 935 additions and 2 deletions

5
.gitignore vendored
View File

@ -22,6 +22,11 @@ areas/migrations/*
!areas/migrations/__init__.py !areas/migrations/__init__.py
areas/__pycache__/* areas/__pycache__/*
adm/migrations/*
!adm/migrations/__init__.py
adm/__pycache__/*
standards/migrations/* standards/migrations/*
!standards/migrations/__init__.py !standards/migrations/__init__.py
standards/__pycache__/* standards/__pycache__/*

0
adm/__init__.py Normal file
View File

3
adm/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

5
adm/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class AdmConfig(AppConfig):
name = 'adm'

View File

12
adm/models.py Normal file
View File

@ -0,0 +1,12 @@
from django.db import models
from django.utils import timezone
# Create your models here.
# MAIN RECOVERDIR PASSWORD AND CONFIG
class MainStatistic(models.Model):
staticdate = models.DateField(default=timezone.now)
agencys = models.IntegerField(default=0)
users = models.IntegerField(default=0)
standards = models.IntegerField(default=0)
chatmessages = models.IntegerField(default=0)

View File

@ -0,0 +1,50 @@
{% extends "adm/adm_base.html" %}
{% block content %}
<div class="content-section col-12">
<h4>Agenturübersicht</h4>
<hr>
<table class="table table-hover" id="agdata" >
<thead>
<tr>
<th scope="col">Agenturname</th>
<th scope="col">Mitarbeiter</th>
<th scope="col">Standards</th>
</tr>
</thead>
<tbody >
{% for ele in agencys %}
<tr>
<td>{{ele.name}}</td>
<td></td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script type="text/javascript">
$(document).ready(function(){
$('#agdata').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
},
},
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
});
})
</script>
{% endblock content %}

View File

@ -0,0 +1,694 @@
{% load static %}
{% load counter_tag %}
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="shortcut icon" type="image/x-icon" href="{% static 'users/img/favicon.ico' %}">
<title>Digitale Agentur - Administrativer Bereich</title>
<!-- Custom fonts for this template-->
<link rel="canonical" href="https://www.digitale-agentur.com">
<!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.js" type="text/javascript"></script>-->
<script src="{%static 'users/js/jquery.js' %}" type="text/javascript"></script>
<link href="{%static 'users/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css">
<!--<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">-->
<link href="{%static 'users/css/google_font.css' %}" rel="stylesheet" type="text/css">
<!--<link href="{%static 'users/css/bootstrap.min.css' %}" rel="stylesheet">-->
<!--<link href='https://fonts.googleapis.com/css?family=Roboto&display=swap' rel='stylesheet' type='text/css'>-->
<link href="{%static 'users/css/google_swap.css' %}" rel="stylesheet" type="text/css">
<!-- include summernote css/js -->
<!--<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.15/dist/summernote.min.js"></script>-->
<!--<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>-->
<script src="{%static 'users/js/jquery_ui_min.js' %}" type="text/javascript"></script>
<!-- <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>-->
<!-- CROPPER -->
<link href="{% static 'users/css/cropper.min.css' %}" type="text/css" rel="stylesheet">
<!-- DATATABLES -->
<!--<link href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css" type="text/css" rel="stylesheet">-->
<link href="{% static 'users/css/jquery_datatables.css' %}" type="text/css" rel="stylesheet">
<!--<link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" type="text/css" rel="stylesheet">-->
<link href="{% static 'users/css/datatables_bs4.css' %}" type="text/css" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="{% static 'users/css/sb-admin-2.css' %}" type="text/css" rel="stylesheet">
<link href="{% static 'users/css/theme.css' %}" type="text/css" rel="stylesheet">
<script src="{%static 'users/js/bs4_summernote.js' %}" type="text/javascript"></script>
<!--<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote-bs4.js"></script>-->
<link href="{% static 'users/css/bs4_summernote.css' %}" type="text/css" rel="stylesheet">
<!--<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.16/dist/summernote.css" rel="stylesheet" type="text/css">-->
<script type="text/javascript" src="{% static 'summernote/lang/summernote-de-DE.min.js' %}"></script>
</head>
<body>
<!-- Page Wrapper -->
<div id="wrapper" >
<!-- Sidebar -->
<ul class=" bg-gray-900 sidebar sidebar-dark accordion fixed-top " style="overflow: all; height: 100vh;"id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="{% url 'users-dashboard' %}">
<i class="fas fa-laptop"></i>
<div class="sidebar-brand-text mx-2" style="">Digitale Agentur</div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
{% if active_link == 'adm-statistic' %}
<li class="nav-item active">
{% else %}
<li class="nav-item">
{%endif%}
<a class="nav-link" href="{% url 'adm-main' %}">
<i class="fas fa-chart-bar"></i>
<span>Statistik</span></a>
</li>
<!-- Nav Item - Dashboard -->
{% if active_link == 'adm-agencys' %}
<li class="nav-item active">
{% else %}
<li class="nav-item">
{%endif%}
<a class="nav-link" href="{% url 'adm-agencys' %}">
<i class="fas fa-user-friends"></i>
<span>Agenturen</span></a>
</li>
<!-- Sidebar Toggler (Sidebar) -->
<!--
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
-->
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<style scoped>
.sidebar{
overflow-y: auto;
overflow-x: hidden;
height : 100%; or
height : 100vh; or
height : 450px;
}
#content-wrapper {
margin-left: 212px;
margin-top: -72px;
}
/* MARGIN TOP FOR FIREFOX */
@-moz-document url-prefix() {
#content-wrapper {
margin-left: 212px;
margin-top: -158px;
}
}
/* MARGIN FOR IOS/SAFARI 10+ and 6+ */
@media not all and (min-resolution:.001dpcm) {
@media {
#content-wrapper {
margin-left: 212px;
margin-top: -158px;
}
}
}
@media screen and (min-color-index:0) and(-webkit-min-device-pixel-ratio:0) {
@media {
#content-wrapper {
margin-left: 212px;
margin-top: -158px;
}
}
}
/*@media screen and (max-width: 768px) {
#content-wrapper {
margin-left: 0px !important;
}
}*/
</style>
<div id="content-wrapper">
<!-- Main Content -->
<!-- Topbar -->
<nav id="topnavbarmain" class="navbar navbar-expand navbar-light bg-white topbar fixed-top mb-4 static-top shadow" style="margin-left: 224px;">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3" onclick="javascript:toggleSidebar()">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<!-- <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input list="searchres" placeholder="Agenturweite Suche..." id="search_string" onkeyup="javascript:startSearch(this.value)" class="form-control bg-light border-0 small" >
-->
<!--
<input type="text" onkeyup="javascript:startSearch(this.value)" class="form-control bg-light border-0 small" placeholder="Suche..." aria-label="Suche" aria-describedby="basic-addon2" id="searchfield">
-->
<!--
<div class="input-group-append">
<button class="btn btn-primary" type="button" onclick="javascript:clearSF()">
<i class="fas fa-times fa-sm"></i>
</button>
</div>
</div>
</form> -->
<style type="text/css">
.dropdown-header {
background-color: #5a5c69 !important;
border-color: #5a5c69 !important;
}
</style>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto ">
<!-- ALERT_AREA -->
<!-- Nav Item - Alerts -->
<style type="text/css">
{% getonlinestatuscolor request.user as onlinecolor %}
.roundimg_base {
border-radius: 50%;
-webkit-box-shadow: 0px 0px 4px 5px {{onlinecolor}};
-moz-box-shadow: 0px 0px 4px 5px {{onlinecolor}};
box-shadow: 0px 0px 4px 5px {{onlinecolor}};
}
</style>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">{{request.user.first_name}} {{request.user.last_name}}
</span>
<img id="userbaseprofilepicture" class="img-profile roundimg_base ml-2" src="{{ user.profile.get_photo_url }}">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
<a class="dropdown-item" onclick="javascript:changeOnlineStatus(0)" href="#/">
<i class="fas fa-circle mr-2" style="color: green"></i>
Online
</a>
<a class="dropdown-item" onclick="javascript:changeOnlineStatus(1)" href="#/">
<i class="fas fa-circle mr-2" style="color: red"></i>
Beschäftigt
</a>
<a class="dropdown-item" onclick="javascript:changeOnlineStatus(2)" href="#/">
<i class="fas fa-circle mr-2" style="color: yellow"></i>
Abwesend
</a>
<a class="dropdown-item" onclick="javascript:changeOnlineStatus(3)" href="#/">
<i class="fas fa-circle mr-2" style="color: grey"></i>
Offline anzeigen
</a>
<div class="dropdown-divider"></div>
<!--<a class="dropdown-item" onclick="userGoToSettings({{user.pk}})" href="{% url 'orga-single' user.pk %}">-->
<a class="dropdown-item" onclick="userGoToSettings()" href="#/">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Einstellungen
</a>
<a class="dropdown-item" onclick="userGoToNotification()" href="#/">
<i class="fas fa-bell fa-sm fa-fw mr-2 text-gray-400"></i>
Benachrichtigungen
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{% url 'users-logout' %}">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Abmelden
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid" >
<div id="maincontent" style="min-height: 100%; margin-top: 85px;" >
<!-- MESSAGES -->
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show col-6" role="alert" id="message_{{forloop.counter}}">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
{% endif %}
{% block content %}
{% endblock %}
</div>
<div style="height: 300px">&nbsp;</div>
</div> <!-- End of Main Content CONTAINER FLUID-->
</div>
</div>
<!-- CHAT BUTTON -->
<!-- End of Page Wrapper -->
<!--
<footer class="sticky-footer bg-white" style="width: 86.2%;position: absolute;
bottom: 0; margin-top: 80px; padding-top: 20px; padding-bottom: 20px;
">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; digitale-agentur.com für <b>{{ user.profile.agency.name }}</b></span><br /><small>Version 0.0.5</small>
</div>
</div>
</footer>
-->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Bootstrap core JavaScript-->
<!--<script src="{%static 'users/vendor/jquery/jquery.min.js' %}"></script>-->
<script type="text/javascript" src="{%static 'users/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Core plugin JavaScript-->
<script type="text/javascript" src="{%static 'users/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- DATABLES JS -->
<!--<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>-->
<script type="text/javascript" src="{%static 'users/js/jquery_dataTables.min.js' %}"></script>
<!--<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js"></script>-->
<script type="text/javascript" src="{%static 'users/js/bs4_dt.js' %}"></script>
<!-- Custom scripts for all pages-->
<script type="text/javascript" src="{%static 'users/js/sb-admin-2.js' %}"></script>
<!-- CUSTOM FONT -->
<!--<link href="{% static 'users/css/custom.css' %}" rel="stylesheet">-->
<!-- TABLE SORT -->
<!--<script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>-->
<!-- Page level plugins -->
<!--<script src="vendor/chart.js/Chart.min.js"></script>-->
<!-- Page level custom scripts -->
<!--<script src="js/demo/chart-area-demo.js"></script>-->
<!--<script src="js/demo/chart-pie-demo.js"></script>-->
<link href="{% static 'users/css/custom.css' %}" type="text/css" rel="stylesheet">
</body>
</html>
{% if request.user.profile.showtooltips %}
<script type="text/javascript">
$(document).ready(function(){
$('[data-toggle="tooltip"]').tooltip()
});
</script>
{% endif %}
<script type="text/javascript">
function userGoToSettings(){
localStorage.setItem('activeTabSettings', "profil");
location.href = "{% url 'dasettings' %}"
}
function userGoToNotification(){
localStorage.setItem('activeTabSettings', "notifications");
location.href = "{% url 'dasettings' %}"
}
function clearSF(){
$("#searchcontent").empty();
$("#searchcontent").hide();
$("#maincontent").show();
$("#search_string").val("");
}
function startSearch(searchstring){
if(searchstring.length > 2){
$.ajax(
{
type: "GET",
url: "/dashboard/globalsearch",
data:{
searchstring: searchstring
},
success: function( data )
{
$("#maincontent").hide();
$("#searchcontent").show();
$("#searchcontent").html(data);
}
});
} else {
$("#searchcontent").empty();
$("#searchcontent").hide();
$("#maincontent").show();
}
}
$(document).ready(function(){
if($( window ).width() < 768)
{
$("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "0px");
$("#topnavbarmain").css("margin-left" , "0px");
sidebar_hidden = false;
}
});
// Toggle the side navigation
function toggleSidebar(){
if(sidebar_hidden == false){
$("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "105px");
$("#topnavbarmain").css("margin-left" , "105px");
sidebar_hidden = true;
}
else{
$("#accordionSidebar").removeClass("toggled");
$("#content-wrapper").css("margin-left" , "0px");
$("#topnavbarmain").css("margin-left" , "0px");
sidebar_hidden = false;
}
}
$( window ).resize(function() {
if($( window ).width() < 750)
{
$("#accordionSidebar").addClass("toggled");
$("#content-wrapper").css("margin-left" , "0px");
$("#topnavbarmain").css("margin-left" , "0px");
sidebar_hidden = false;
}
else{
$("#accordionSidebar").removeClass("toggled");
$("#content-wrapper").css("margin-left" , "212px");
$("#topnavbarmain").css("margin-left" , "224px");
sidebar_hidden = true;
}
});
/*
AJAX CALL FOR NOTIFICATIONS
*/
newunknownotificationscounter = 0;
function loadUnsendNotifications(){
$.ajax(
{
type: "GET",
url: "/notifications/checknotifications",
data : {
action : "checknotifications"
},
success: function( data )
{
$("#notification_items").html("");
notifications = data['unknownnotification'];
var i = 0;
for (var key in notifications) {
$("#notification_items").append('<span><a href="/'+notifications[i]['elelink']+'" id="notifyid_'+notifications[i]['not_id']+'" class="dropdown-item d-flex align-items-center"><div><div class="small text-gray-500">'+notifications[i]['date']+'</div>'+notifications[i]['text']+'</div></a></span>')
i = i + 1;
newunknownotificationscounter = newunknownotificationscounter + 1;
}
$("#notificationcounter").html("");
if(i > 0){$("#notificationcounter").html(i);}
}
});
}
function loadUnviewnNotifications(){
$.ajax(
{
type: "GET",
url: "/notifications/getnotifications",
data : {
action : "oldnotifications"
},
success: function( data )
{
notifications = data['oldnotifications'];
i = 0;
$("#notification_items").html("");
for (var key in notifications) {
if(newunknownotificationscounter <= 5){
$("#notification_items").append('<a href="/'+notifications[i]['elelink']+'" id="notifyid_'+notifications[i]['not_id']+'" class="dropdown-item d-flex align-items-center"><div><div class="small text-gray-500">'+notifications[i]['date']+'</div>'+notifications[i]['text']+'</div></a>')
i = i + 1;
}
}
}
});
}
function changeNewNotToViewed(){
$.ajax(
{
type: "GET",
url: "/notifications/newnotificationsviewed",
data : {
action : "newnotificationsviewed"
},
success: function( data )
{
$("#notificationcounter").html("");
}
});
}
function removeNotification(notifyid){
//$("#notifyid_" + notifyid).remove()
//$("#allnotificationsarea").show();
}
$(document).on('click', function (e) {
if(e.target["id"] != 'chatButton'){
if ($(e.target).closest("#chat_alluserscontent").length === 0) {
$("#chat_alluserscontent").fadeOut();
}
}
});
</script>
<!-- WEBSOCKETS -->
<script type="text/javascript">
$(document).ready(function(){
$("#chat_alluserscontent").hide();
ws_string = 'wss://'
if (location.protocol !== 'https:') {
ws_string = 'ws://'
}
const mainwebsocket = new WebSocket(ws_string+window.location.host+"/ws/")
mainwebsocket.onmessage = function(e) {
console.log(e);
if(e["data"] != "presence_update")
{
//HANDLER FOR ALL PUSHNOTIFICATIONS
if(e["data"].split("__")[0] == "pushnotification"){
/*
Check for Chat-Message in CHatview or invisible-Browser
*/
tempsplit = e["data"].split("__");
finalsplit = tempsplit[1].split(" ");
if(finalsplit[0] != "Chat"){
var notify = new Notification('Digitale Agentur', {
body: e["data"].split("__")[1]
});
}
else{
{% if active_link == "chat" %}
chatopen= true;
{% else %}
chatopen= false;
{% endif %}
windowvisible = false;
//Get Minimized-Window-Status to show up chat message, when window is in chat, but not focused by user
if(!document.hasFocus()){
var notify = new Notification('Digitale Agentur', {
body: e["data"].split("__")[1]
});
}
else if(chatopen == false){
if($("#dynamicchatwindow").is(":visible")){
console.log("user in chat...")
}
else{
var notify = new Notification('Digitale Agentur', {
body: e["data"].split("__")[1]
});
}
}
}
}
loadUnsendNotifications();
loadUnviewnNotifications();
}
else{
{% if active_link == "chat" %}
if(preventUpdatePresLive == false){
updatePresenceLive();
}
{% endif %}
}
};
mainwebsocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
//HEARTBEAT every minute
setInterval(function()
{
mainwebsocket.send(JSON.stringify("heartbeat"));
console.log("heartbeat is alive...");
},60000);
});
function changeOnlineStatus(newstat){
$.ajax(
{
type: "GET",
url: "{% url 'users-updateonlinestat' %}",
data : {
newstat : newstat
},
success: function( data )
{
if(data["newstat"] == "0"){
$("#userbaseprofilepicture").css({
'-webkit-box-shadow' : '0px 0px 4px 5px green',
'-moz-box-shadow': '0px 0px 4px 5px green',
'box-shadow': '0px 0px 4px 5px green'
})
}
else if(data["newstat"] == "1"){
$("#userbaseprofilepicture").css({
'-webkit-box-shadow' : '0px 0px 4px 5px red',
'-moz-box-shadow': '0px 0px 4px 5px red',
'box-shadow': '0px 0px 4px 5px red'
})
}
else if(data["newstat"] == "2"){
$("#userbaseprofilepicture").css({
'-webkit-box-shadow' : '0px 0px 4px 5px orange',
'-moz-box-shadow': '0px 0px 4px 5px orange',
'box-shadow': '0px 0px 4px 5px orange'
})
}
else if(data["newstat"] == "3"){
$("#userbaseprofilepicture").css({
'-webkit-box-shadow' : '0px 0px 4px 5px grey',
'-moz-box-shadow': '0px 0px 4px 5px grey',
'box-shadow': '0px 0px 4px 5px grey'
})
}
}
});
}
window.onerror = function (msg, url, line) {
return false;
}
if (!window.Notification) {
console.log('Browser does not support notifications.');
} else {
// check if permission is already granted
if (Notification.permission === 'granted') {
// show notification here
} else {
// request permission from user
Notification.requestPermission().then(function(p) {
if(p === 'granted') {
// show notification here
console.log("User receive notifications.")
} else {
console.log('User blocked notifications.');
}
}).catch(function(err) {
console.error(err);
});
}
}
$("#chatButton").click(function(){
$.ajax(
{
type: "GET",
url: "{% url 'chat:chtaajax-getloggedusers' %}",
data : {
action : "getloggedusers"
},
success: function( data )
{
$("#chat_alluserscontent").fadeToggle();
$("#chat_alluserscontent").html(data);
}
});
});
</script>

View File

@ -0,0 +1,52 @@
{% extends "adm/adm_base.html" %}
{% block content %}
<div class="content-section col-12">
<h4>Statistikdaten über alle</h4>
<hr>
<table class="table table-hover" id="statistics" >
<thead>
<tr>
<th scope="col">Datum</th>
<th scope="col">Agenturen</th>
<th scope="col">Benutzer</th>
<th scope="col">Standards</th>
<th scope="col">Chatnachrichten</th>
</tr>
</thead>
<tbody >
{% for ele in statistik %}
<tr>
<td>{{ele.staticdate|date:"d.m.Y"}}</td>
<td>{{ele.agencys}}</td>
<td>{{ele.users}}</td>
<td>{{ele.standards}}</td>
<td>{{ele.chatmessages}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script type="text/javascript">
$(document).ready(function(){
$('#statistics').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
},
},
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
});
})
</script>
{% endblock content %}

3
adm/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

14
adm/urls.py Normal file
View File

@ -0,0 +1,14 @@
from django.urls import path
from .views import *
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.admin.views.decorators import staff_member_required
'''
Permissions definiert in models.py bei USERS und dann hier vor die View geschrieben!
'''
urlpatterns = [
path('', AdmMain.as_view(), name='adm-main'),
path('ag/', AdmAgencys.as_view(), name="adm-agencys"),
path('cron/<slug:code>', statisticCronJob, name="adm-cron")
]

70
adm/views.py Normal file
View File

@ -0,0 +1,70 @@
from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, FormView, TemplateView
from django.contrib import messages
from django.shortcuts import render, redirect, reverse
from django.conf import settings
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
from .models import MainStatistic
from django.contrib.auth.models import User
from chat.models import ChatMessage
from users.models import Agency
from standards.models import Standards
def checkForStuffUser(request):
if request.user.is_staff:
return True
else:
return False
class AdmMain(TemplateView):
template_name = "adm/adm_main.html"
def dispatch(self, *args, **kwargs):
if(checkForStuffUser(self.request)):
return super().dispatch(*args, **kwargs)
else:
messages.warning(self.request, f'Sie benötigen einen Mitarbeiter-Account, um diese Seiten aufzurufen!')
return redirect("login")
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : "adm-statistic"})
context.update({'statistik' : MainStatistic.objects.all().order_by('-staticdate')})
return context
class AdmAgencys(TemplateView):
template_name = "adm/adm_agencys.html"
def dispatch(self, *args, **kwargs):
if(checkForStuffUser(self.request)):
return super().dispatch(*args, **kwargs)
else:
messages.warning(self.request, f'Sie benötigen einen Mitarbeiter-Account, um diese Seiten aufzurufen!')
return redirect("login")
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'active_link' : "adm-agencys"})
context.update({'agencys' : Agency.objects.all()})
return context
# CRONJOB, um die Statistik zu füllen!
def statisticCronJob(request, code):
data = {}
if(code == settings.CRONAPIKEY_STATSTIC):
print("STATISTIC is running...")
newMainS = MainStatistic(agencys=len(Agency.objects.all()),users=len(User.objects.all().exclude(is_staff=True, is_superuser=True)),standards=len(Standards.objects.all()),chatmessages=len(ChatMessage.objects.all()))
newMainS.save()
data.update({"status" : "success"})
else:
print("API STATISTIC CODE FAILED")
data.update({"status" : "failed"})
return JsonResponse(data)

View File

@ -38,6 +38,7 @@ X_FRAME_OPTIONS = 'SAMEORIGIN'
SECRET_KEY = '_qv2t2lmsctjxpbb4rrp=op%_20_hxzonv^mvty1o85c)l$s^q' SECRET_KEY = '_qv2t2lmsctjxpbb4rrp=op%_20_hxzonv^mvty1o85c)l$s^q'
CRONAPIKEY = "gCddsaz6NOnE9QbXZM5LasdEk122D" CRONAPIKEY = "gCddsaz6NOnE9QbXZM5LasdEk122D"
CRONAPIKEY_STATSTIC = "aiszdausd876asdtuzagshjdajgAHGJHSDSD67daiuhdj"
MAILINFOKEY = "jka7sd8iukashdna78skduJAHDsu6dilaksdjba65a68iadbhjak" MAILINFOKEY = "jka7sd8iukashdna78skduJAHDsu6dilaksdjba65a68iadbhjak"
# API KEY LEXOFFICE # API KEY LEXOFFICE
LEX_API = "8f9ba01f-9e84-42c7-9548-48c254f14c19" LEX_API = "8f9ba01f-9e84-42c7-9548-48c254f14c19"
@ -68,6 +69,7 @@ INSTALLED_APPS = [
'timemanagement.apps.TimemanagementConfig', 'timemanagement.apps.TimemanagementConfig',
'recoverdir.apps.RecoverdirConfig', 'recoverdir.apps.RecoverdirConfig',
'news.apps.NewsConfig', 'news.apps.NewsConfig',
'adm.apps.AdmConfig',
'crispy_forms', 'crispy_forms',
'colorful', 'colorful',
'django_summernote', 'django_summernote',

View File

@ -22,6 +22,7 @@ urlpatterns = [
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('organizer/', include('organizer.urls'), name="ql-management"), path('organizer/', include('organizer.urls'), name="ql-management"),
path('adm/', include('adm.urls'), name="adm"),
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('rd/', include('recoverdir.urls'), name="recoverdir"), path('rd/', include('recoverdir.urls'), name="recoverdir"),

View File

@ -232,7 +232,18 @@
</style> </style>
<div id="bottom_info" style="z-index: -200"> <div id="bottom_info" style="z-index: -200">
<hr class="sidebar-divider d-none d-md-block"> <hr class="sidebar-divider d-none d-md-block">
{% if active_link == 'dasettings' %} {% if request.user.is_staff %}
<li class="nav-item">
<a class="nav-link " href="{% url 'adm-main' %}" aria-expanded="true" style="margin-top: -15px">
<i class="fas fa-user-shield"></i>
<span>Adminoberfläche</span>
</a>
</li>
{% endif %}
{% if active_link == 'dasettings' %}
<li class="nav-item active"> <li class="nav-item active">
{% else%} {% else%}
<li class="nav-item"> <li class="nav-item">
@ -242,7 +253,8 @@
<span>Einstellungen</span> <span>Einstellungen</span>
</a> </a>
</li> </li>
{% if active_link == 'support' %}
{% if active_link == 'support' %}
<li class="nav-item active"> <li class="nav-item active">
{% else%} {% else%}
<li class="nav-item"> <li class="nav-item">

View File

@ -17,6 +17,16 @@
<i class="fas fa-laptop"></i> <i class="fas fa-laptop"></i>
<h3>Digitale Agentur Login</h3> <h3>Digitale Agentur Login</h3>
</legend> </legend>
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert" id="message_{{forloop.counter}}">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
{% endif %}
{{ form|crispy }} {{ form|crispy }}
</fieldset> </fieldset>
<div class="form-group"> <div class="form-group">