This commit is contained in:
Holger Trampe 2020-05-31 01:57:41 +02:00
parent ee77bb43c4
commit 984751c59b
17 changed files with 660 additions and 92 deletions

39
chat/forms.py Normal file
View File

@ -0,0 +1,39 @@
from django import forms
from .models import ChatRoom
from users.models import UserFullName
class ChatUpdateChatRoom(forms.ModelForm):
class Meta:
model = ChatRoom
labels = {
"roomname" : "Raumname",
"chatmembers" : "Mitglieder",
"chatmembers_admin" : "Verwalter",
}
fields = ['roomname', 'chatmembers', 'chatmembers_admin']
def __init__(self, *args, **kwargs):
print(kwargs)
super(ChatUpdateChatRoom, self).__init__(*args, **kwargs)
self.fields['chatmembers'] = forms.MultipleChoiceField(required=True, label="Mitglieder", choices=[(u.id, u) for u in UserFullName.objects.filter(profile__agency__pk=kwargs["instance"].creator.profile.agency.pk).exclude(pk=kwargs["instance"].creator.pk)], widget=forms.CheckboxSelectMultiple())
self.fields['chatmembers_admin'] = forms.MultipleChoiceField(required=False, label="Raumverwalter", choices=[(u.id, u) for u in UserFullName.objects.filter(profile__agency__pk=kwargs["instance"].creator.profile.agency.pk).exclude(pk=kwargs["instance"].creator.pk)], widget=forms.CheckboxSelectMultiple())
class ChatAddChatRoom(forms.ModelForm):
class Meta:
model = ChatRoom
labels = {
"roomname" : "Raumname",
"chatmembers" : "Mitglieder",
"chatmembers_admin" : "Verwalter",
}
fields = ['roomname', 'chatmembers', 'chatmembers_admin']
def __init__(self, *args, **kwargs):
super(ChatAddChatRoom, self).__init__(*args, **kwargs)
self.fields['chatmembers'] = forms.MultipleChoiceField(required=True, label="Mitglieder", choices=[(u.id, u) for u in UserFullName.objects.filter(profile__agency__pk=kwargs["instance"].profile.agency.pk).exclude(pk=kwargs["instance"].pk)], widget=forms.CheckboxSelectMultiple())
self.fields['chatmembers_admin'] = forms.MultipleChoiceField(required=False, label="Raumverwalter", choices=[(u.id, u) for u in UserFullName.objects.filter(profile__agency__pk=kwargs["instance"].profile.agency.pk).exclude(pk=kwargs["instance"].pk)], widget=forms.CheckboxSelectMultiple())

View File

@ -3,7 +3,7 @@ from django.contrib.auth.models import User
from users.models import Agency from users.models import Agency
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django_cryptography.fields import encrypt
''' '''
@ -13,7 +13,7 @@ MODEL ChatMessage
''' '''
class ChatMessage(models.Model): class ChatMessage(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE) author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.CharField(max_length=5000, blank=False, default="") content = encrypt(models.CharField(max_length=5000, blank=False, default=""))
sendtime = models.DateTimeField(default=timezone.now, blank=True) sendtime = models.DateTimeField(default=timezone.now, blank=True)
room = models.ForeignKey("ChatRoom", on_delete=models.CASCADE) room = models.ForeignKey("ChatRoom", on_delete=models.CASCADE)
''' '''
@ -24,7 +24,7 @@ Model ChatRoom
class ChatRoom(models.Model): class ChatRoom(models.Model):
creator = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) creator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
''' '''
chatroomtype chatroomtype
@ -34,9 +34,11 @@ class ChatRoom(models.Model):
''' '''
chatroomtype = models.IntegerField(default=0) chatroomtype = models.IntegerField(default=0)
roomname = models.CharField(max_length=200, blank=False, default="") roomname = models.CharField(max_length=200, blank=False, default="")
grouproomname = models.CharField(max_length=200, blank=False, default="")
# This field is for random-String Django Channels # This field is for random-String Django Channels
roomname_channel = models.CharField(max_length=200, blank=False) roomname_channel = models.CharField(max_length=200, blank=False)
chatmembers = models.ManyToManyField(User, blank=True, related_name='users_in_chatroom') chatmembers = models.ManyToManyField(User, blank=True, related_name='users_in_chatroom')
chatmembers_admin = models.ManyToManyField(User, blank=True, related_name='adminusers_in_chatroom')
chatroom_createddate = models.DateTimeField(blank=True) chatroom_createddate = models.DateTimeField(blank=True)
chatmember_single = models.ForeignKey(User, related_name='singleuserchat', on_delete=models.CASCADE, null=True, blank=True) chatmember_single = models.ForeignKey(User, related_name='singleuserchat', on_delete=models.CASCADE, null=True, blank=True)
''' '''
@ -53,6 +55,8 @@ class ChatRoom(models.Model):
def __str__(self): def __str__(self):
return f'{self.roomname}' return f'{self.roomname}'
def get_absolute_url(self):
return reverse('chat-update', kwargs={'pk':self.pk})

View File

@ -32,11 +32,11 @@
{% endif %} {% endif %}
{% if message.author == request.user %} {% if message.author == request.user %}
<div style="" class="chatmessageele_me col-7 mb-3 "> <div style="" class="chatmessageele_me col-7 mb-3 " id="usermessage_{{message.pk}}">
<div class='icon-container ml-2 mt-1 ' style="float: right;"> <div class='icon-container ml-2 mt-1 ' style="float: right;">
<img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}"> <img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}">
</div> </div>
<h6 class="mt-3"><small>{{message.sendtime|date:"H:i"}}</small></h6> <h6 class="mt-3"><button class="btn btn-small" onclick="javascript:deleteOwnMessage({{message.pk}})"><small><i class="fas fa-trash"></i></small></button>&nbsp;<small>{{message.sendtime|date:"H:i"}}</small></h6>
<div style="text-align: left;" class="mt-1"> <div style="text-align: left;" class="mt-1">
<span style="float: right !important; font-size: 1.0em;"> <span style="float: right !important; font-size: 1.0em;">
{{message.content}} {{message.content}}
@ -44,7 +44,7 @@
</div> </div>
</div> </div>
{% else %} {% else %}
<div style="" class="chatmessageele_other col-7 mb-3"> <div style="" class="chatmessageele_other col-7 mb-3" id="usermessage_{{message.pk}}">
<div class='icon-container mr-2 mt-1 ' style="float: left;"> <div class='icon-container mr-2 mt-1 ' style="float: left;">
<img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}"> <img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}">
</div> </div>
@ -103,6 +103,7 @@ $(document).ready(function(){
datainfo = e["data"].split("__"); datainfo = e["data"].split("__");
if(datainfo[0] == "starttyping") if(datainfo[0] == "starttyping")
{ {
typingname = (datainfo[1].split("_"))[1]; typingname = (datainfo[1].split("_"))[1];
@ -136,7 +137,11 @@ $(document).ready(function(){
} }
}); });
} }
}; console.log(datainfo)
if(datainfo[0] == "delete_message"){
$("#usermessage_" + datainfo[1]).remove();
}
}
chatwebsocket.onclose = function(e) { chatwebsocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly'); console.error('Chat socket closed unexpectedly');
@ -179,8 +184,22 @@ $(document).ready(function(){
}); });
} }
} }
function deleteOwnMessage(id){
$.ajax(
{
type: "GET",
url: "{% url 'chat:chat-ajax' %}",
data : {
action : "delmessage",
messageid : id
},
success: function( data )
{
chatwebsocket.send("delmessage__" + id + "__privatechat_{{roomdata.creator.pk}}_{{roomdata.chatmember_single.pk}}");
}
});
}
$(document).on('keypress',function(e) { $(document).on('keypress',function(e) {
if(e.which == 13) { if(e.which == 13) {
if($("#message").val().length > 0 && sending){ if($("#message").val().length > 0 && sending){

View File

@ -69,11 +69,11 @@
{% endif %} {% endif %}
{% if message.author == request.user %} {% if message.author == request.user %}
<div style="" class="chatmessageele_me col-7 mb-3 "> <div style="" class="chatmessageele_me col-7 mb-3 " id="usermessage_{{message.pk}}"">
<div class='icon-container ml-2 mt-1 ' style="float: right;"> <div class='icon-container ml-2 mt-1 ' style="float: right;">
<img class="img-profile roundimg-chat" src="{{ message.author.profile.get_photo_url }}"> <img class="img-profile roundimg-chat" src="{{ message.author.profile.get_photo_url }}">
</div> </div>
<h6 class="mt-3"><small>{{message.sendtime|date:"H:i"}}</small></h6> <h6 class="mt-3"><button class="btn btn-small" onclick="javascript:deleteOwnMessage({{message.pk}})"><small><i class="fas fa-trash"></i></small></button>&nbsp;<small>{{message.sendtime|date:"H:i"}}</small></h6>
<div style="text-align: left;" class="mt-1"> <div style="text-align: left;" class="mt-1">
<span style="float: right !important; font-size: 1.0em;"> <span style="float: right !important; font-size: 1.0em;">
{{message.content}} {{message.content}}
@ -81,7 +81,7 @@
</div> </div>
</div> </div>
{% else %} {% else %}
<div style="" class="chatmessageele_other col-7 mb-3"> <div style="" class="chatmessageele_other col-7 mb-3" id="usermessage_{{message.pk}}">
<div class='icon-container mr-2 mt-1 ' style="float: left;"> <div class='icon-container mr-2 mt-1 ' style="float: left;">
<img class="img-profile roundimg-chat" src="{{ message.author.profile.get_photo_url }}"> <img class="img-profile roundimg-chat" src="{{ message.author.profile.get_photo_url }}">
</div> </div>
@ -180,6 +180,10 @@ $(document).ready(function(){
} }
}); });
} }
if(datainfo[0] == "delete_message"){
$("#usermessage_" + datainfo[1]).remove();
}
}; };
chatwebsocket.onclose = function(e) { chatwebsocket.onclose = function(e) {
@ -224,6 +228,22 @@ $(document).ready(function(){
} }
} }
function deleteOwnMessage(id){
$.ajax(
{
type: "GET",
url: "{% url 'chat:chat-ajax' %}",
data : {
action : "delmessage",
messageid : id
},
success: function( data )
{
chatwebsocket.send("delmessage__" + id + "__privatechat_{{roomdata.creator.pk}}_{{roomdata.chatmember_single.pk}}");
}
});
}
$(document).on('keypress',function(e) { $(document).on('keypress',function(e) {
if(e.which == 13) { if(e.which == 13) {

View File

@ -0,0 +1,253 @@
{% load counter_tag %}
<h4 id="chattitle" style="margin-top: -3px">{{roomdata.roomname}}
{% if user in roomdata.chatmembers_admin.all or user == roomdata.creator %}
<button class="btn btn-secondary btn-sm ml-2 " style="float: right;" onclick="javascript:$('#confirm-delete_{{roomdata.pk}}').modal('toggle')"><small><i class="fas fa-trash"></i></small></button>
<button class="btn btn-secondary btn-sm " onclick="window.location.href='{% url 'chat:chat-update' roomdata.pk %}'" style="float: right;"><small><i class="fas fa-pen"></i></small></button>
{% endif %}
</h4>
<hr>
<div class="card" >
<div class="card-body scroll" id="chatcontentcomplete">
<div id="roomstart" style="min-width: 100%; text-align: center;">
<small>Unterhaltung gestartet am {{roomdata.chatroom_createddate}}</small>
</div>
<hr>
<div id="chatmessages">
{% for message in roomdata.messages.all %}
{% if forloop.counter0 == 0 %}
{% setMessageDayInfo message %}
{% else %}
{% getMessageDayInfo message as newday %}
{% if newday == True %}
<div style="" class="chatmessageele_breaker col-12 mb-3">
<div class="col-12 mb-3" style="text-align: center;">
<hr>
<small>{{message.sendtime|date:"d.m.Y"}}</small>
</div>
</div>
{% endif %}
{% endif %}
{% if message.author == request.user %}
<div style="" class="chatmessageele_me col-7 mb-3 " id="usermessage_{{message.pk}}">
<div class='icon-container ml-2 mt-1 ' style="float: right;">
<img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}">
</div>
<h6 class="mt-3"><button class="btn btn-small" onclick="javascript:deleteOwnMessage({{message.pk}})"><small><i class="fas fa-trash"></i></small></button>&nbsp;<small>{{message.sendtime|date:"H:i"}}</small>
</h6>
<div style="text-align: left;" class="mt-1">
<span style="float: right !important; font-size: 1.0em;">
{{message.content}}
</span>
</div>
</div>
{% else %}
<div style="" class="chatmessageele_other col-7 mb-3" id="usermessage_{{message.pk}}">
<div class='icon-container mr-2 mt-1 ' style="float: left;">
<img class="img-profile roundimg" src="{{ message.author.profile.get_photo_url }}">
</div>
<h6 class="mt-3"><small>{{message.author.first_name}} {{message.author.last_name}},&nbsp;{{message.sendtime|date:"H:i"}}</small></h6>
<div style="text-align: left;" class="mt-1">
<span style="float: left !important; font-size: 1.0em;">
{{message.content}}
</span>
</div>
</div>
{% endif %}
{% endfor %}
</div><!-- END CHAT MESSAGES -->
<span id="scrolltarget">&nbsp;</span>
</div><!-- END CARD BODY-->
<div id="is_typing" class="ml-2">
<div class="spinner-grow spinner-border-sm" id="typingspinner" role="status" style="display: none;">
<span class="sr-only">Jemand tippt...</span>
</div>
<small id="is_typing_name" class="">&nbsp;
</small>
</div>
<div class="card-footer bg-transparent border-success">
<div class="input-group">
<input type="text" class="form-control" placeholder="Neue Nachricht" id="message" aria-describedby="">
<div class="input-group-append">
<button class="btn btn-primary" id="sendNewMessgeButton" onclick="javascript:sendNewMessage()" type="button"><i class="fas fa-location-arrow"></i></button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$('#chatcontentcomplete').scrollTop( $('#chatcontentcomplete').height()*200 )
});
userownid = "{{user.pk}}";
ws_string = 'wss://'
if (location.protocol !== 'https:') {
ws_string = 'ws://'
}
if(typeof chatwebsocket != "undefined"){
chatwebsocket = new WebSocket(ws_string+window.location.host+"/ws/groupchat/{{roomdata.pk}}/")
}
else{
chatwebsocket = new WebSocket(ws_string+window.location.host+"/ws/groupchat/{{roomdata.pk}}/")
}
chatwebsocket.onmessage = function(e) {
datainfo = e["data"].split("__");
if(datainfo[0] == "starttyping")
{
typingname = (datainfo[1].split("_"))[1];
typingid = (datainfo[1].split("_"))[0];
if(typingid != userownid){
$("#is_typing_name").html("" + typingname);
$("#typingspinner").show();
}
}
if(datainfo[0] == "stoptyping")
{
$("#is_typing_name").html("&nbsp;");
$("#typingspinner").hide();
}
if(datainfo[0] == "reloadmessages")
{
$.ajax(
{
type: "GET",
url: "{% url 'chat:chat-ajax' %}",
data : {
action : "loadnewestmessage",
room : {{roomdata.pk}}
},
success: function( data )
{
$("#chatmessages").append(data);
$('#chatcontentcomplete').scrollTop( $('#chatcontentcomplete').height()*200 );
}
});
}
if(datainfo[0] == "delete_message"){
$("#usermessage_" + datainfo[1]).remove();
}
}
chatwebsocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
$("#message").keyup(function(){
if($("#message").val().length > 0){
chatwebsocket.send("starttyping__{{user.pk}}__groupchat_{{roomdata.pk}}");
}
else{
chatwebsocket.send("stoptyping__{{user.pk}}__groupchat_{{roomdata.pk}}");
}
})
sending = true;
function sendNewMessage()
{
if($("#message").val().length > 0 && sending)
{
sending = false;
$.ajax(
{
type: "GET",
url: "{% url 'chat:chat-ajax' %}",
data : {
action : "addnewmessage",
new_chat_userid : userownid,
message : $("#message").val(),
room : {{roomdata.pk}}
},
success: function( data )
{
$("#message").val("");
chatwebsocket.send("load__{{user.pk}}__groupchat_{{roomdata.pk}}");
chatwebsocket.send("stoptyping__{{user.pk}}__groupchat_{{roomdata.pk}}");
sending = true;
}
});
}
}
$(document).on('keypress',function(e) {
if(e.which == 13) {
if($("#message").val().length > 0 && sending){
sendNewMessage();
}
}
});
function deleteOwnMessage(id){
$.ajax(
{
type: "GET",
url: "{% url 'chat:chat-ajax' %}",
data : {
action : "delmessage",
messageid : id
},
success: function( data )
{
chatwebsocket.send("delmessage__" + id + "__groupchat_{{roomdata.pk}}");
}
});
}
</script>
{% if user in roomdata.chatmembers_admin.all or user == roomdata.creator %}
<div class="modal fade" id="confirm-delete_{{roomdata.pk}}" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Chatraum löschen</h5>
</div>
<div class="modal-body">
Möchten Sie wirklich den Chatraum {{roomdata.roomname}} löschen? Alle Nachrichten werden entfernt!
</div>
<div class="modal-footer">
<button class="btn btn-primary" id="dodel_{{roomdata.pk}}" >Löschen</button>
<button type="button" class="btn" data-dismiss="modal">Abbrechen</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$("#dodel_{{roomdata.pk}}").click(function(){
$.ajax(
{
type: "GET",
url: "{% url 'chat:chat-ajax' %}",
data:{
action : "remove_chatroom",
groupchatid: {{roomdata.pk}},
},
success: function( data )
{
location.href = location.href;
}
});
});
</script>
{% endif %}

View File

@ -1,4 +1,4 @@
<div style="" class="chatmessageele_other col-7 mb-3 "> <div style="" class="chatmessageele_other col-7 mb-3 " id="usermessage_{{newmessage.pk}}">
<div class='icon-container mr-2 mt-1 ' style="float: left;"> <div class='icon-container mr-2 mt-1 ' style="float: left;">
<img class="img-profile roundimg" src="{{ newmessage.author.profile.get_photo_url }}"> <img class="img-profile roundimg" src="{{ newmessage.author.profile.get_photo_url }}">
</div> </div>

View File

@ -1,8 +1,8 @@
<div style="" class="chatmessageele_me col-7 mb-3 "> <div style="" class="chatmessageele_me col-7 mb-3 " id="usermessage_{{newmessage.pk}}">
<div class='icon-container ml-2 mt-1 ' style="float: right;"> <div class='icon-container ml-2 mt-1 ' style="float: right;">
<img class="img-profile roundimg" src="{{ newmessage.author.profile.get_photo_url }}"> <img class="img-profile roundimg" src="{{ newmessage.author.profile.get_photo_url }}">
</div> </div>
<h6 class="mt-3"><small>{{newmessage.sendtime|date:"H:i"}}</small></h6> <h6 class="mt-3"><button class="btn btn-small" onclick="javascript:deleteOwnMessage({{newmessage.pk}})"><small><i class="fas fa-trash"></i></small></button>&nbsp;<small>{{newmessage.sendtime|date:"H:i"}}</small></h6>
<div style="text-align: left;" class="mt-1"> <div style="text-align: left;" class="mt-1">
<span style="float: right !important; font-size: 1.0em;"> <span style="float: right !important; font-size: 1.0em;">
{{newmessage.content}} {{newmessage.content}}

View File

@ -53,23 +53,22 @@
min-height: 600px; min-height: 600px;
overflow-y: auto; overflow-y: auto;
} }
</style> </style>
<div class="content-section col-12"> <div class="content-section col-12">
<h3>Chat&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verwalten Sie hier Ihre Chatverläufe und starten Sie neue Unterhaltungen mit Mitarbeitern und anderen Agenturen." class="far fa-question-circle"></i></small> <h3>Chat&nbsp;<small><i data-toggle="tooltip" data-placement="top" title="Verwalten Sie hier Ihre Chatverläufe und starten Sie neue Unterhaltungen mit Mitarbeitern und anderen Agenturen." class="far fa-question-circle"></i></small>
</h3> </h3>
<small><b>ACHTUNG! Der Chat befindet sich im Beta-Stadium! Bitte vermeiden Sie es daher, persönliche oder intime Informationen zu verschicken, bis alle Funktionen ausreichend erprobt sind. Vielen Dank!</b></small>
<hr> <hr>
</div> </div>
<div class="row col"> <div class="row col">
<div class="col-3"> <div class="col-3">
<h4>Mitarbeiter und Räume</h4> <h5>Mitarbeiter
</h5>
<hr> <hr>
{% for user in usersofagency %} {% for user in usersofagency %}
<div class="card mb-2 hoverchatcard" id="userchat_{{user.pk}}"> <div class="card mb-2 hoverchatcard" id="userchat_{{user.pk}}">
<div class="card-body"> <div class="card-body" style="margin: -15px !important;" >
<div style="float: left;" class="col-12 "> <div style="float: left;" class="col-12 ">
<div class='icon-container mr-2'> <div class='icon-container mr-2'>
<img class="img-profile roundimg" src="{{ user.profile.get_photo_url }}"> <img class="img-profile roundimg" src="{{ user.profile.get_photo_url }}">
@ -91,6 +90,29 @@
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
<hr>
<h5>Chaträume
<button class="btn btn-primary btn-sm" style="float: right; margin-top: -6px !important;" data-toggle="tooltip" data-placement="top" title="Erstellen Sie einen Gruppenchat." onclick="window.location.href='{% url 'chat:chat-addgroup' %}'"><i class="fas fa-plus"></i></button>
</h5>
<hr>
{% for chatroom in chatrooms %}
{% if user in chatroom.chatmembers.all or user in chatroom.chatmembers_admin.all or user == chatroom.creator and chatroom.chatroomtype == 1 %}
<div class="card mb-2 hoverchatcard" id="groupchat_{{chatroom.pk}}">
<div class="card-body" style="margin: -15px !important;">
<div style="float: left;" class="col-12 ">
<h5 class="mt-3">{{chatroom.roomname}}
</h5>
<small style="font-size: 10pt;">{% for member in chatroom.chatmembers.all %}
{{member.first_name}} {{member.last_name}}{% if forloop.counter < chatroom.chatmembers.all|length %}, {% endif %}
{% endfor %}
</small>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div> </div>
<div class="col-9" style="" id="mainchatcontent"> <div class="col-9" style="" id="mainchatcontent">
@ -112,7 +134,10 @@
) )
$(".hoverchatcard").click(function(){ $(".hoverchatcard").click(function(){
clickedroomtype = $(this)[0]["id"].split("_")[0];
clickedroomid = $(this)[0]["id"].split("_")[1];
if (clickedroomtype == "userchat"){
$.ajax( $.ajax(
{ {
type: "GET", type: "GET",
@ -130,6 +155,27 @@
$("#mainchatcontent").html(data); $("#mainchatcontent").html(data);
} }
}); });
}
//Open Groupchat
else{
$.ajax(
{
type: "GET",
url: "{% url 'chat:chat-ajax' %}",
data : {
action : "startnewchat_groupchat",
groupchatid : clickedroomid,
is_basechat : 0
},
success: function( data )
{
if(creator_id != false && chatmember_id != false){
chatwebsocket.close();
}
$("#mainchatcontent").html(data);
}
});
}
}); });
function updatePresenceLive() { function updatePresenceLive() {

View File

@ -0,0 +1,48 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% if request.user.profile.agency.module_chat %}
<div class="content-section col-6">
<h3>Gruppenchat</h3>
<hr>
<form method="POST">
{% csrf_token %}
{{form|crispy}}
<small>Sie selbst sind Raumverwalter und können auch später weitere Mitglieder hinzufügen.</small>
<hr>
<a class="btn" href="{% url 'chat:chat-management' %} ">Abbrechen</a>
<button type="submit" class="btn btn-primary" style="float: right">Chatraum speichern</button>
</form>
</div>
<script type="text/javascript">
preventUpdatePresLive = true;
members = [{% for mem in object.chatmembers.all %} "{{mem.pk}}",{% endfor %}];
admins = [{% for mem in object.chatmembers_admin.all %} "{{mem.pk}}",{% endfor %}];
boxes = $(":checkbox");
for(i = 0; i < boxes.length; i++){
if(members.indexOf(boxes[i]["value"]) !== -1){
if(boxes[i]["id"].indexOf("chatmembers_admin") === -1 && boxes[i]["id"].indexOf("chatmembers") !== -1){
$("#" + boxes[i]["id"]).prop("checked", true)
}
}
if(admins.indexOf(boxes[i]["value"]) !== -1){
if(boxes[i]["id"].indexOf("chatmembers_admin") !== -1){
$("#" + boxes[i]["id"]).prop("checked", true)
}
}
}
</script>
{% else %}
<h3>Das Module Chat wurde in ihrer Agentur deaktiviert.</h3>
{% endif %}
{% endblock content %}

View File

@ -4,8 +4,11 @@ from . import views
app_name = 'chat' app_name = 'chat'
urlpatterns = [ urlpatterns = [
path('managemenet/', views.chatmanagement, name='chat-management'), path('managemenet/', views.chatmanagement, name='chat-management'),
path('addgc/', views.ChatAddGroupChat, name='chat-addgroup'),
path('addgc/update/<int:pk>', views.ChatUpdateGroupChat.as_view(), name='chat-update'),
path('ajaxchat', views.chatajaxmain, name="chat-ajax"), path('ajaxchat', views.chatajaxmain, name="chat-ajax"),
path('ajaxchat/getloggedusers', views.getloggedusers, name="chtaajax-getloggedusers"), path('ajaxchat/getloggedusers', views.getloggedusers, name="chtaajax-getloggedusers"),
path('ajaxchat/getloggedusersdata', views.getloggedusersdata, name="chtaajax-getloggedusers-data") path('ajaxchat/getloggedusersdata', views.getloggedusersdata, name="chtaajax-getloggedusers-data")
] ]

View File

@ -1,4 +1,4 @@
from django.shortcuts import render from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from channels_presence.models import Presence from channels_presence.models import Presence
from django.http import HttpResponseRedirect,HttpResponse, JsonResponse from django.http import HttpResponseRedirect,HttpResponse, JsonResponse
@ -8,6 +8,11 @@ from channels_presence.models import Presence
import channels.layers import channels.layers
from django.utils import timezone from django.utils import timezone
from .models import ChatRoom, ChatMessage from .models import ChatRoom, ChatMessage
from .forms import ChatAddChatRoom, ChatUpdateChatRoom
from django.contrib import messages
from django.views.generic import UpdateView
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
# Create your views here. # Create your views here.
@login_required @login_required
@ -18,13 +23,51 @@ def chatmanagement(request):
context = { context = {
'active_link' : 'chat', 'active_link' : 'chat',
"usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).exclude(pk=request.user.pk).order_by("last_name"), "usersofagency" : User.objects.filter(profile__agency=request.user.profile.agency).exclude(pk=request.user.pk).order_by("last_name"),
"onlineusers" : users_online.get_users() "onlineusers" : users_online.get_users(),
"chatrooms" : ChatRoom.objects.all()
} }
return render(request, 'chat/chatmanagement.html', context) return render(request, 'chat/chatmanagement.html', context)
@login_required
def ChatAddGroupChat(request):
if request.method == "POST":
form = ChatAddChatRoom(request.POST, instance=request.user)
if(form.is_valid()):
newchatroom = ChatRoom(creator=request.user, chatroomtype=1, roomname=form.cleaned_data["roomname"], roomname_channel="groupchat", chatroom_createddate=timezone.now(), viewstatus=0)
newchatroom.save()
newchatroom.chatmembers.set(form.cleaned_data["chatmembers"])
newchatroom.chatmembers_admin.set(form.cleaned_data["chatmembers_admin"])
newchatroom.save()
messages.success(request, f'Raum angelegt!')
else:
messages.success(request, f'Raum konnte nicht angelegt werden!')
return redirect('chat:chat-management')
else:
context = {
'active_link' : 'chat',
"form" : ChatAddChatRoom(instance=request.user)
}
return render(request, 'chat/chatmanagement_addgc.html', context)
class ChatUpdateGroupChat(LoginRequiredMixin, UpdateView):
model = ChatRoom
template_name = 'chat/chatmanagement_addgc.html'
success_url = reverse_lazy('chat:chat-management')
form_class = ChatUpdateChatRoom
def form_valid(self, form):
# Send message to the site
messages.success(self.request, f'Chatraum aktualisiert!')
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super(ChatUpdateGroupChat, self).get_context_data(**kwargs)
context['active_link'] = 'chat'
print(context)
return context
@login_required @login_required
def getloggedusers(request): def getloggedusers(request):
@ -81,7 +124,7 @@ def chatajaxmain(request):
singleuser = User.objects.get(pk=singleuserid) singleuser = User.objects.get(pk=singleuserid)
# NO PRIVATE CHAT THERE, CREATE ONE! # NO PRIVATE CHAT THERE, CREATE ONE!
if(len(getroom) == 0): if(len(getroom) == 0):
newchatroom = ChatRoom(creator=request.user, chatroomtype=0, roomname="Gespräch mit " + singleuser.first_name + " " + singleuser.last_name, roomname_channel="privatechat_" + str(request.user.pk) + "_" + singleuserid, chatmember_single=singleuser, chatroom_createddate=timezone.now(), viewstatus=0) newchatroom = ChatRoom(creator=request.user, chatroomtype=0, roomname=singleuser.first_name + " " + singleuser.last_name, roomname_channel="privatechat_" + str(request.user.pk) + "_" + singleuserid, chatmember_single=singleuser, chatroom_createddate=timezone.now(), viewstatus=0)
newchatroom.save() newchatroom.save()
context = { context = {
"roomdata" : newchatroom "roomdata" : newchatroom
@ -94,9 +137,39 @@ def chatajaxmain(request):
return render(request, "chat/chat_content_basechat.html", context) return render(request, "chat/chat_content_basechat.html", context)
else: else:
return render(request, "chat/chat_content.html", context) return render(request, "chat/chat_content.html", context)
# NACHRICHT LÖSCHEN
elif request.GET["action"] == "delmessage":
message_to_del = ChatMessage.objects.get(pk=request.GET["messageid"])
if(message_to_del.author == request.user):
message_to_del.delete()
return JsonResponse({"status" : "OK"})
else:
return JsonResponse({"status" : "FORBIDDEN"})
# GRUPPENCHAT LÖSCHEN
elif request.GET["action"] == "remove_chatroom":
chatroom = ChatRoom.objects.get(pk=request.GET["groupchatid"])
if(request.user == chatroom.creator or request.user in chatroom.chatmembers_admin.all()):
chatroom.delete()
messages.success(request, f'Raum gelöscht!')
return JsonResponse({"status" : "RELOAD"})
else:
messages.success(request, f'Das dürfen Sie nicht!')
return JsonResponse({"status" : "RELOAD"})
# GRUPPENCHAT ÖFFNEN
elif request.GET["action"] == "startnewchat_groupchat":
chatroom = ChatRoom.objects.get(pk=request.GET["groupchatid"])
if(request.user == chatroom.creator or request.user in chatroom.chatmembers.all() or request.user in chatroom.chatmembers_admin.all()):
context = {
"roomdata" : chatroom
}
return render(request, "chat/chat_content_groupchat.html", context)
else:
JsonResponse({"status" : "Error on CHATAJAXMAIN"})
elif request.GET["action"] == "addnewmessage": elif request.GET["action"] == "addnewmessage":
room = ChatRoom.objects.get(pk=request.GET["room"]) room = ChatRoom.objects.get(pk=request.GET["room"])
if(request.user == room.creator or request.user == room.chatmember_single): if(request.user == room.creator or request.user == room.chatmember_single or request.user in room.chatmembers.all() or request.user in room.chatmembers_admin.all()):
newmessage = ChatMessage(room=room, author=request.user, content=request.GET["message"]) newmessage = ChatMessage(room=room, author=request.user, content=request.GET["message"])
newmessage.save() newmessage.save()
@ -118,12 +191,3 @@ def chatajaxmain(request):
return JsonResponse({"status" : "Error on CHATAJAXMAIN"}) return JsonResponse({"status" : "Error on CHATAJAXMAIN"})
'''
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.CharField(max_length=5000, blank=False, default="")
sendtime = models.DateField(default=timezone.now, blank=True)
room = models.ForeignKey("ChatRoom", on_delete=models.CASCADE)
'''

View File

@ -7,6 +7,7 @@ from message.models import Message
from cloud.models import DataFile from cloud.models import DataFile
from organizer.models import AGContacts from organizer.models import AGContacts
from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence
from chat.models import ChatRoom
admin.site.register(StandardComments) admin.site.register(StandardComments)
admin.site.register(StandardCommentRate) admin.site.register(StandardCommentRate)
@ -28,3 +29,4 @@ admin.site.register(AbsenceReason)
admin.site.register(Absence) admin.site.register(Absence)
admin.site.register(FreeDays) admin.site.register(FreeDays)
admin.site.register(UserYearAbsenceInfo) admin.site.register(UserYearAbsenceInfo)
admin.site.register(ChatRoom)

View File

@ -8,7 +8,6 @@ import channels
from django.contrib.auth.models import User from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
class UsersConsumer(WebsocketConsumer): class UsersConsumer(WebsocketConsumer):
appconnect = False appconnect = False
@ -103,11 +102,7 @@ class UsersChat(WebsocketConsumer):
loggeduser = self.scope["user"] loggeduser = self.scope["user"]
roomname = "privatechat_" + str(self.scope["url_route"]["kwargs"]["creator"]) + "_" + str(self.scope["url_route"]["kwargs"]["single"]) roomname = "privatechat_" + str(self.scope["url_route"]["kwargs"]["creator"]) + "_" + str(self.scope["url_route"]["kwargs"]["single"])
# TODO: Hier das doppelte Problem lösen mit den Channels...Datenbank dazuziehen!!!
print(roomname)
print(loggeduser.pk)
channel_layer = channels.layers.get_channel_layer() channel_layer = channels.layers.get_channel_layer()
print(channel_layer)
Room.objects.add(roomname, self.channel_name, loggeduser) Room.objects.add(roomname, self.channel_name, loggeduser)
def disconnect(self, close_code): def disconnect(self, close_code):
@ -129,7 +124,9 @@ class UsersChat(WebsocketConsumer):
elif datainfo[0] == 'load': elif datainfo[0] == 'load':
channel_layer = channels.layers.get_channel_layer() channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(datainfo[2], {'type' : 'reloadmessages'}) async_to_sync(channel_layer.group_send)(datainfo[2], {'type' : 'reloadmessages'})
elif datainfo[0] == 'delmessage':
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(datainfo[2], {'type' : 'delmessage', 'messageid' : datainfo[1] })
def start_typing(self, event): def start_typing(self, event):
useristyping = User.objects.get(pk=event["typingname"]) useristyping = User.objects.get(pk=event["typingname"])
@ -152,3 +149,75 @@ class UsersChat(WebsocketConsumer):
# SOMETHING IN PRESENCE CHANGED # SOMETHING IN PRESENCE CHANGED
def update_presence_live(self, event): def update_presence_live(self, event):
self.send("presence_update") self.send("presence_update")
def delmessage(self, event):
self.send("delete_message__" + event["messageid"])
class GroupChat(WebsocketConsumer):
def connect(self):
super().connect()
pathcheck = self.scope["path"].split("/")
loggeduser = ""
# CHECK IF SOCKET COMES FROM APP OR FROM WEB
#APP
if(len(pathcheck) == 7 and len(pathcheck[5]) > 0):
loggeduser = User.objects.get(pk=Token.objects.get(key=pathcheck[5]).user_id)
self.appconnect = True
else:
loggeduser = self.scope["user"]
roomname = "groupchat_" + str(self.scope["url_route"]["kwargs"]["chatid"])
channel_layer = channels.layers.get_channel_layer()
Room.objects.add(roomname, self.channel_name, loggeduser)
def disconnect(self, close_code):
Presence.objects.touch(self.channel_name)
Room.objects.remove("", self.channel_name)
# WEBSOCKET-DATA-CONTENT
def receive(self, text_data=None, bytes_data=None):
datainfo = text_data.split("__")
typinguserid = datainfo[1]
print(datainfo[2])
if datainfo[0] == 'starttyping':
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(datainfo[2], {'type' : 'start_typing', 'typingname' : typinguserid})
elif datainfo[0] == 'stoptyping':
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(datainfo[2], {'type' : 'stop_typing'})
elif datainfo[0] == 'load':
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(datainfo[2], {'type' : 'reloadmessages'})
elif datainfo[0] == 'delmessage':
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(datainfo[2], {'type' : 'delmessage', 'messageid' : datainfo[1] })
def start_typing(self, event):
useristyping = User.objects.get(pk=event["typingname"])
self.send("starttyping__" + str(useristyping.pk) + "_" + useristyping.first_name + " " + useristyping.last_name + " tippt...")
def stop_typing(self, event):
self.send("stoptyping")
def reloadmessages(self, event):
self.send("reloadmessages")
# UPDATET STANDARD
def update_standard(self, event):
self.send("standard_update")
# NEW AGENCY NEWS
def agency_newnews(self, event):
self.send("Neue Agenturnews!")
# SOMETHING IN PRESENCE CHANGED
def update_presence_live(self, event):
self.send("presence_update")
def delmessage(self, event):
self.send("delete_message__" + event["messageid"])

View File

@ -4,6 +4,7 @@ from . import mainwebsocket
websocket_urlpatterns = [ websocket_urlpatterns = [
re_path(r'ws/chat/(?P<creator>\w+)/(?P<single>\w+)/$', mainwebsocket.UsersChat, name="ws-chat"), re_path(r'ws/chat/(?P<creator>\w+)/(?P<single>\w+)/$', mainwebsocket.UsersChat, name="ws-chat"),
re_path(r'ws/groupchat/(?P<chatid>\w+)/$', mainwebsocket.GroupChat, name="ws-groupchat"),
re_path(r'ws/appchat/(?P<creator>\w+)/(?P<single>\w+)/(?P<token>\w+)/$', mainwebsocket.UsersChat, name="ws-appchat"), re_path(r'ws/appchat/(?P<creator>\w+)/(?P<single>\w+)/(?P<token>\w+)/$', mainwebsocket.UsersChat, name="ws-appchat"),
re_path(r'ws/', mainwebsocket.UsersConsumer, name="ws-default"), re_path(r'ws/', mainwebsocket.UsersConsumer, name="ws-default"),
] ]

View File

@ -154,6 +154,7 @@
{% endif %} {% endif %}
{% if request.user.profile.agency.module_chat %} {% if request.user.profile.agency.module_chat %}
<script type="text/javascript">preventUpdatePresLive = false;</script>
{% if active_link == 'chat' %} {% if active_link == 'chat' %}
<li class="nav-item active"> <li class="nav-item active">
{% else%} {% else%}
@ -436,7 +437,7 @@
<button id="chatButton" class="btn btn-primary" style="position: fixed; right: 36px; bottom: 30px;"><i class="far fa-comments"></i></button> <button id="chatButton" class="btn btn-primary" style="position: fixed; right: 36px; bottom: 30px;"><i class="far fa-comments"></i></button>
<!-- CHATAREA --> <!-- CHATAREA -->
<div id="dynamicchatwindow" class="col-4" style="position: absolute; bottom: 30px; right: 23px; display: none;z-index: 999;"> <div id="dynamicchatwindow" class="col-4" style="position: fixed; bottom: 30px; right: 23px; display: none;z-index: 999;">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
@ -444,7 +445,9 @@
</div> </div>
</div> </div>
</div> </div>
<script type="text/javascript">
</script>
<!-- CHATAREA END --> <!-- CHATAREA END -->
{% endif %} {% endif %}
</div> </div>
@ -739,7 +742,9 @@ $(document).ready(function(){
else{ else{
{% if active_link == "chat" %} {% if active_link == "chat" %}
if(preventUpdatePresLive == false){
updatePresenceLive(); updatePresenceLive();
}
{% endif %} {% endif %}
} }
}; };

View File

@ -36,7 +36,8 @@ urlpatterns = [
path('setuserparent/', views.setuserparent, name="users-setuserparent"), path('setuserparent/', views.setuserparent, name="users-setuserparent"),
path('sendpassmail/', views.sendpassmail, name="users-sendpassmail"), path('sendpassmail/', views.sendpassmail, name="users-sendpassmail"),
path('changeonlinestat/', views.changeonlinestat, name="users-updateonlinestat"), path('changeonlinestat/', views.changeonlinestat, name="users-updateonlinestat"),
path('dacron/<slug:code>', views.cronactions, name="cronmain") path('dacron/<slug:code>', views.cronactions, name="cronmain"),
path('dacrondaily/<slug:code>', views.cronactionsdaily, name="cronmaindaily")
] ]

View File

@ -41,6 +41,7 @@ from channels_presence.models import Room
from channels_presence.models import Presence from channels_presence.models import Presence
import channels.layers import channels.layers
from datetime import date from datetime import date
from timemanagement.models import Workday
def randomString(stringLength=10): def randomString(stringLength=10):
"""Generate a random string of fixed length """ """Generate a random string of fixed length """
@ -826,6 +827,7 @@ def handler500(request):
CRONJOB FUNCTION CRONJOB FUNCTION
''' '''
# CRONJOBS ALLE 5 MINUTEN
def cronactions(request, code): def cronactions(request, code):
data = {} data = {}
if(code == settings.CRONAPIKEY): if(code == settings.CRONAPIKEY):
@ -856,15 +858,21 @@ def cronactions(request, code):
newnotification = UserNotification(touser=user, notificationtext="Neue Agenturnews: " + news.name, notificationtype="agencynews", elementid=news.pk) newnotification = UserNotification(touser=user, notificationtext="Neue Agenturnews: " + news.name, notificationtype="agencynews", elementid=news.pk)
newnotification.save() newnotification.save()
# TODO: CronJob für REST-Urlaub implementieren
# CRONJOBS UM 00:01!
def cronactionsdaily(request, code):
data = {}
if(code == settings.CRONAPIKEY):
allusers = User.objects.all()
''' '''
Pro User gibt es das Feld loose_holiday in der UserTime-Info. Ist dieser Tag vorbei, muss die Differenz der days_inuse des VORJHARES in den Rest das AKTUELLEN JAHRES gespeichert werden! Pro User gibt es das Feld loose_holiday in der UserTime-Info. Ist dieser Tag vorbei, muss die Differenz der days_inuse des VORJHARES in den Rest das AKTUELLEN JAHRES gespeichert werden!
''' '''
today = date.today() today = date.today()
for user in allusers: for user in allusers:
# REST URLAUB BERECHNUNG
usertimedata = UserTime.objects.get(user=user) usertimedata = UserTime.objects.get(user=user)
day_tocheck = usertimedata.loose_holidedate.split(".")[0] day_tocheck = usertimedata.loose_holidedate.split(".")[0]
@ -887,31 +895,17 @@ def cronactions(request, code):
next_year.restdays = this_year.days - this_year.days_inuse next_year.restdays = this_year.days - this_year.days_inuse
next_year.save() next_year.save()
data.update({"status" : "ok"}) # ARBEITSTAGE BEENDEN
elif(code == settings.MAILINFOKEY): # Benutzer hat Zeiterfassung aktiv
pass if(user.usertime.usetime):
''' workdays = Workday.objects.filter(user=user, end=None)
# GET ALL USERS for wd in workdays:
users = User.objects.all().exclude(username="root") wd.end = datetime(wd.start.year, wd.start.month, wd.start.day, 23, 59)
wd.save()
data.update({"status" : "ok"})
for u in users:
u.username = u.email
try:
u.save()
notificationtext = "ab sofort können Sie sich nur noch mit Ihrer E-Mailadresse anmelden. Diese lautet " + u.email + "!"
msg_html = render_to_string('users/password_to_username_mail.html', {'user': u, 'notificationtext' : notificationtext})
send_mail(
'Agentur-Benachrichtigung',
'Hallo ' + u.first_name + ' ' + u.last_name + '! ' + notificationtext,
'noreply@digitale-agentur.com',
[u.email],
html_message=msg_html,
fail_silently=True
)
data.update({"user_" + str(u.pk) : u.email})
except:
data.update({"ERROR_user_" + str(u.pk) : u.email})
'''
else: else:
print("API CODE FAILED") print("API CODE FAILED")
data.update({"status" : "failed"}) data.update({"status" : "failed"})