Skip to content

Commit

Permalink
Add chat to game-event page
Browse files Browse the repository at this point in the history
modify game-event html for adding the chat html
adding tests for the chat
adding new view function that handle the chat
adding urls for the new view function
  • Loading branch information
MaayanMashhadi committed Jun 5, 2023
1 parent 57e7242 commit 7a5c51a
Show file tree
Hide file tree
Showing 7 changed files with 440 additions and 61 deletions.
184 changes: 127 additions & 57 deletions game_event/templates/game_event/game-event.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,70 +4,140 @@
<!DOCTYPE html>
<html>
<head>
<link href="/static/css/chat.css" rel="stylesheet" />

<title>Game Event</title>
<link rel="stylesheet" type="text/css" href="{% static 'css/game-event.css' %}">
<script>
setTimeout(function() {
location.reload();
}, 5000);
</script>

</head>
<body>
{% if time %}
<h1>Event Details</h1>
<p>Time: {{ time }}</p>
<p>Level: {{ level_of_game }}</p>
<p>Min Players: {{ min_number_of_players }}</p>
<p>Max Players: {{ max_number_of_players }}</p>
<p>Court: {{ court }} {{ neighborhood }}</p>
<p>Game: {{ ball_game }}</p>
<h2>Players:</h2>
<table class="nice-table">
<thead>
<tr>
<th> </th>
<th>Name</th>
<th>Brings Ball</th>
</tr>
</thead>
<tbody>
{% for player in event_players %}
<tr>
<td>
<img src="{% static 'images/favicon.ico' %}" alt="Ball Image" class="ball-image">
</td>
<td>{{ player.first_name }} {{ player.last_name }}</td>
<td>
{% if player.brings_ball == True %}
Yes
{% if time %}
<h1>Event Details</h1>
<p>Time: {{ time }}</p>
<p>Level: {{ level_of_game }}</p>
<p>Min Players: {{ min_number_of_players }}</p>
<p>Max Players: {{ max_number_of_players }}</p>
<p>Court: {{ court }} {{ neighborhood }}</p>
<p>Game: {{ ball_game }}</p>
<h2>Players:</h2>
<table class="nice-table">
<thead>
<tr>
<th> </th>
<th>Name</th>
<th>Brings Ball</th>
</tr>
</thead>
<tbody>
{% for player in event_players %}
<tr>
<td>
<img src="{% static 'images/favicon.ico' %}" alt="Ball Image" class="ball-image">
</td>
<td>{{ player.first_name }} {{ player.last_name }}</td>
<td>
{% if player.brings_ball == True %}
Yes
{% else %}
No
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div>
{% if in_event %}
<a href="/game-events/remove-from-event/{{ id }}/"
class="round-button"
onclick="window.open(this.href, 'Remove Event', 'width=400,height=250,left='+((screen.width-400)/2)+',top='+((screen.height-515)/2)); return false;">
Remove Event
</a>
<div class="top-right">
<h1>Chat With Players!</h1>
<body>

{% if all_messages %}
<div id="savedText">
<div class="message-box">
{% for message in all_messages %}

{% if message.user_id.user.username == request.user.username %}
<div class="message-container">
<span class="message-time">{{ message.time_sent|date:"F d, H:i" }}</span>
<span class="name">{{ message.user_id.user.username }}</span><br>
<p><span class="message">{{ message.text }}</span></p>
</div>

{% else %}
<div class="message-other-user-container">
<span class="message-other-time">{{ message.time_sent|date:"F d, H:i" }}</span>
<span class="name-other">{{ message.user_id.user.username }}</span><br>
<p><span class="message-other">{{ message.text }}</span></p>
</div>
{% endif %}
{% endfor %}


</div>
</div>

{% else %}
No
<div id="savedText" style="display: none;">
<textarea id="savedTextbox" rows="12" cols="50" readonly></textarea>
</div>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>

<div class="input">
<form method="POST" action="{% url 'save_text_message' id=id %}">
{% csrf_token %}
<input type="text" id="mytextbox" name="mytextbox" placeholder="Type your message here!">
<button onclick="saveText(); showSaveBox();">Send</button>
</div>
</form>
<script>
function saveText() {
var textbox = document.getElementById('mytextbox');
var savedTextbox = document.getElementById('savedTextbox');

}
function showSaveBox() {
var savedTextDiv = document.getElementById('savedText');
savedTextDiv.style.display = 'block';
}

</script>
{% if messages %}
<div class="row my-4">
<div class="col">
<div class="alert alert-danger" role="alert">
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}

</body>


</div>
{% else %}
<a href="/game-events/join-event/{{ id }}/"
class="round-button"
onclick="window.open(this.href, 'Join Event', 'width=400,height=250,left='+((screen.width-400)/2)+',top='+((screen.height-515)/2)); return false;">
Join Event
</a>
{% endif %}
</div>
{% else %}
<div>
{% if in_event %}
<a href="/game-events/remove-from-event/{{ id }}/"
class="round-button"
onclick="window.open(this.href, 'Remove Event', 'width=400,height=250,left='+((screen.width-400)/2)+',top='+((screen.height-515)/2)); return false;">
Remove Event
</a>
{% else %}
<a href="/game-events/join-event/{{ id }}/"
class="round-button"
onclick="window.open(this.href, 'Join Event', 'width=400,height=250,left='+((screen.width-400)/2)+',top='+((screen.height-515)/2)); return false;">
Join Event
</a>
{% endif %}
<h1> Event Does not exist. </h1>
</div>
{% else %}
<div>
<h1> Event Does not exist. </h1>
</div>
{% endif %}
</body>
{% endif %}
</body>
</html>
{%endblock%}
4 changes: 3 additions & 1 deletion game_event/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.urls import path
from . import views
from message.views import save_text_message


urlpatterns = [
Expand All @@ -9,4 +10,5 @@
path('<id>/', views.game_event, name='game_event'),
path('join-event/<id>/', views.join_event, name='join_event'),
path('process-answer-game-event/<id>/', views.process_answer_game_event, name='process_answer_game_event'),
path('remove-from-event/<id>/', views.remove_from_event, name='remove_from_event')]
path('remove-from-event/<id>/', views.remove_from_event, name='remove_from_event'),
path('save-text-message/<id>/', save_text_message, name='save_text_message')]
5 changes: 4 additions & 1 deletion game_event/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.utils import timezone
from django.core.exceptions import ValidationError
from django.contrib import messages
from message.models import Message
from datetime import date


Expand Down Expand Up @@ -96,6 +97,7 @@ def game_event(request, id):
for entry in GameEventPlayer.objects.filter(game_event=event)
]
in_event = GameEventPlayer.objects.filter(game_event=event, player=player).exists()
all_messages = Message.objects.filter(game_event_id=event)
context = {
'id': event.id,
'time': event.time,
Expand All @@ -106,7 +108,8 @@ def game_event(request, id):
'neighborhood': event.court.neighborhood,
'ball_game': event.ball_game,
'in_event': in_event,
'event_players': event_players
'event_players': event_players,
'all_messages': all_messages
}
return render(request, 'game_event/game-event.html', context)

Expand Down
25 changes: 25 additions & 0 deletions message/models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
from django.db import models
from player.models import Player
from game_event.models import GameEvent
from game_event_player.models import GameEventPlayer
from django.core.validators import MinLengthValidator
from django.core.exceptions import ValidationError


class Message(models.Model):
user_id = models.ForeignKey(Player, on_delete=models.CASCADE)
game_event_id = models.ForeignKey(GameEvent, on_delete=models.CASCADE)
time_sent = models.DateTimeField(auto_now_add=True)
text = models.CharField(max_length=255, validators=[MinLengthValidator(1)])

@staticmethod
def create(player, game_event, text):
Message.validate_message(player, game_event, text)
message = Message(user_id=player,
game_event_id=game_event,
text=text)

message.save()
return message

@staticmethod
def validate_message(player, game_event, text):
game_event = GameEvent.objects.get(pk=game_event.pk)
player_participates = GameEventPlayer.objects.filter(player=player, game_event=game_event).exists()
errors = []
if player_participates is False:
errors.append("Just players from this event can send messages on chat")
if text.strip() == '':
errors.append("Message can't be empty")

if errors:
raise ValidationError("\n".join(errors))
92 changes: 92 additions & 0 deletions message/tests.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from player.models import Player
from game_event.models import GameEvent
from game_event_player.models import GameEventPlayer
from message.models import Message
from django.core.exceptions import ValidationError
from django.utils import timezone
from django.urls import reverse
import pytest


TEST_ID = 2
TEST_TIME = timezone.now()
TEST_LEVEL = 3
Expand Down Expand Up @@ -81,3 +84,92 @@ def test_create_message_with_empty_text(self, player, game_event):
time_sent=TEST_TIME,
text=""
).full_clean()


@pytest.mark.django_db
class TestMessageViews:

def test_success_send_message(self, client, game_event, player):
client.force_login(player.user)
game_event_id = game_event.id
url = reverse('process_answer_game_event', args=[game_event_id])
client.post(url, {'answer': 'yes'})
count_before = Message.objects.count()
url = reverse('save_text_message', args=[game_event_id])
response = client.post(url, {'mytextbox': 'Test message'})

assert response.status_code == 302
assert Message.objects.count() == count_before + 1
message = Message.objects.last()
assert message.user_id == player
assert message.game_event_id == game_event
assert message.text == 'Test message'

def test_messages_persist_after_join_and_remove(self, client, game_event, player):
client.force_login(player.user)
game_event_id = game_event.id
url = reverse('process_answer_game_event', args=[game_event_id])
response = client.post(url, {'answer': 'yes'})
assert response.status_code == 200
url = reverse('save_text_message', args=[game_event_id])
client.post(url, {'mytextbox': 'hi from user'})
reverse('remove_from_event', args=[game_event_id])
player_messages = [entry.text for entry in Message.objects.filter(game_event_id=game_event)]
assert 'hi from user' in player_messages

def test_success_create_message_function(self, game_event, player):
text = 'test message'
GameEventPlayer.objects.create(game_event=game_event, player=player)
count_before = Message.objects.count()
message = Message.create(player, game_event, text)
assert Message.objects.count() == count_before + 1
assert message.text == 'test message'

def test_fail_create_message_function(self, game_event, player):
text = 'test message'
count_before = Message.objects.count()
with pytest.raises(ValidationError):
Message.create(player, game_event, text)
assert Message.objects.count() == count_before

def test_success_validate_message(self, game_event, player):
GameEventPlayer.objects.create(game_event=game_event, player=player)
text = 'test message'
e = Message.validate_message(player, game_event, text)
assert e is None

@pytest.mark.parametrize(
"text, expected_errors",
[
('test message', ["Just players from this event can send messages on chat"]),
('', ["Message can't be empty", "Just players from this event can send messages on chat"]),
(' ', ["Message can't be empty", "Just players from this event can send messages on chat"]),
]
)
def test_fail_validate_message(self, game_event, player, text, expected_errors):
with pytest.raises(ValidationError) as current_errors:
Message.validate_message(player, game_event, text)
errors = current_errors.value.messages[0].split("\n")
assert set(errors) == set(expected_errors)

def test_failed_send_empty_message(self, client, game_event, player):
client.force_login(player.user)
game_event_id = game_event.id
url = reverse('process_answer_game_event', args=[game_event_id])
response = client.post(url, {'answer': 'yes'})
count_before = Message.objects.count()
url = reverse('save_text_message', args=[game_event_id])
response = client.post(url, {'mytextbox': ''})
assert response.status_code == 302
assert Message.objects.count() == count_before

def test_failed_send_message_invalid_player(self, client, game_event, player):
client.force_login(player.user)
game_event_id = game_event.id
count_before = Message.objects.count()
reverse('remove_from_event', args=[game_event_id])
url = reverse('save_text_message', args=[game_event_id])
response = client.post(url, {'mytextbox': 'Test message'})

assert response.status_code == 302
assert Message.objects.count() == count_before
Loading

0 comments on commit 7a5c51a

Please sign in to comment.