Skip to content

Commit

Permalink
added Peer Recognition feature (OWASP-BLT#3175)
Browse files Browse the repository at this point in the history
* added Peer Recognition feature

* second commit

* third commit

* third commit

* added link, optional comment

* changed migrations

* resolving conflicts

* resolved conflicts

* fixing pre

* fixed pre

* kudos migration file added again
  • Loading branch information
tsu-ki authored Feb 2, 2025
1 parent b4be25a commit 123277f
Show file tree
Hide file tree
Showing 7 changed files with 389 additions and 11 deletions.
2 changes: 2 additions & 0 deletions blt/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
add_member,
create_team,
delete_team,
give_kudos,
join_requests,
kick_member,
leave_team,
Expand Down Expand Up @@ -835,6 +836,7 @@
path("teams/delete-team/", delete_team, name="delete_team"),
path("teams/leave-team/", leave_team, name="leave_team"),
path("teams/kick-member/", kick_member, name="kick_member"),
path("teams/give-kudos/", give_kudos, name="give_kudos"),
path(
"similarity-scan",
TemplateView.as_view(template_name="similarity.html"),
Expand Down
52 changes: 52 additions & 0 deletions website/migrations/0188_kudos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Generated by Django 5.1.3 on 2025-02-02 10:55

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("website", "0187_githubreview"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="Kudos",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("timestamp", models.DateTimeField(auto_now_add=True)),
("link", models.URLField(blank=True, null=True)),
("comment", models.TextField(blank=True, null=True)),
(
"receiver",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="kudos_received",
to=settings.AUTH_USER_MODEL,
),
),
(
"sender",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="kudos_sent",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"verbose_name_plural": "Kudos",
"ordering": ["-timestamp"],
},
),
]
19 changes: 19 additions & 0 deletions website/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1463,3 +1463,22 @@ class GitHubReview(models.Model):

def __str__(self):
return f"Review #{self.review_id} by {self.reviewer.user.username} on PR #{self.pull_request.issue_id}"


class Kudos(models.Model):
"""
Model to send kudos to team members.
"""

sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="kudos_sent")
receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name="kudos_received")
timestamp = models.DateTimeField(auto_now_add=True)
link = models.URLField(blank=True, null=True)
comment = models.TextField(blank=True, null=True)

class Meta:
ordering = ["-timestamp"]
verbose_name_plural = "Kudos"

def __str__(self):
return f"Kudos from {self.sender.username} to {self.receiver.username}"
Binary file added website/static/img/kudos_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
85 changes: 85 additions & 0 deletions website/templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,9 @@ <h4 class="text-[16px] font-semibold uppercase tracking-wide mb-2">
<button class="mr-3" onclick="openBookmarkModal();">
<div class="bg-[#f4f4f4] rounded-2xl p-3 m-2">📑 {% trans "Bookmarks" %} {{ bookmarks|length }}</div>
</button>
<button class="mr-3" onclick="openKudosModal();">
<div class="bg-[#f4f4f4] rounded-2xl p-3 m-2">🌟 Kudos {{ user.kudos_received.count }}</div>
</button>
<button class="mr-3">
<div class="bg-[#f4f4f4] rounded-2xl p-3 m-2">👁️ {% trans "Profile Views" %} {{ user.userprofile.visit_count }}</div>
</button>
Expand Down Expand Up @@ -1062,6 +1065,88 @@ <h3 class="text-lg font-semibold mb-4">Assign a Badge</h3>
</form>
</div>
</div>
<!-- Kudos modal -->
<div id="Kudos"
class="hidden relative z-10"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true">
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"
aria-hidden="true"></div>
<div class="fixed inset-0 z-10 w-screen overflow-y-auto">
<div class="flex min-h-full items-center justify-center p-4 text-center sm:items-center sm:p-0">
<div class="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 max-sm:w-full lg:w-[30vw] ">
<div class="bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start lg:w-full">
<div class="mt-3 sm:ml-4 sm:mt-0 sm:text-left lg:w-full">
<div class="mt-2">
<h3>Kudos Received:</h3>
<br>
<p class="text-xl">
<table class="table-auto w-full border-spacing-52">
<tbody>
{% for k in user.kudos_received.all %}
<tr class="shadow-lg m-3 w-full rounded">
<td>
{% if k.sender.userprofile.avatar %}
<img src="{{ k.sender.userprofile.avatar }}"
height="50"
width="50"
alt="{{ k.sender.username }}">
{% else %}
<img src="{% gravatar_url k.sender.email 50 %}"
height="50"
width="50"
alt="{{ k.sender.username }}">
{% endif %}
</td>
<td>
<a href="{% url 'profile' slug=k.sender.username %}">{{ k.sender.username }}</a>
</td>
<td>{{ k.timestamp }}</td>
{% if k.link %}
<td>
<a href="{{ k.link }}" target="_blank" rel="noopener noreferrer">Link</a>
</td>
{% endif %}
{% if k.comment %}
<td>
<button type="button"
class="toggle-comment"
onclick="this.nextElementSibling.classList.toggle('hidden')">
<i class="fas fa-comment-dots"></i> View Comment
</button>
<div class="hidden mt-2 text-sm text-gray-600">{{ k.comment }}</div>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</p>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6">
<button type="button"
class="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-xl font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto"
id="close-kudos">Close</button>
</div>
</div>
</div>
</div>
</div>
<script defer>
var closeKudos = document.getElementById("close-kudos");
var openKudos = document.getElementById("Kudos");
closeKudos.addEventListener("click", ()=>{
openKudos.style.display="none";
});
function openKudosModal(){
openKudos.style.cssText = "display:block !important;";
}
</script>
<script>
// Assign Badge Modal Logic
const addBadgeButton = document.getElementById("add-badge-button");
Expand Down
Loading

0 comments on commit 123277f

Please sign in to comment.