Fix Gravatar profiles showing on hover and add gravatar explanation and profile page for users

This commit is contained in:
badblocks 2025-03-18 14:21:50 -07:00
parent 2451a6c630
commit 4c0db9f842
7 changed files with 79 additions and 10 deletions

View file

@ -47,6 +47,17 @@ def gravatar(email, size=20):
html = f'<img src="{url}" width="{size}" height="{size}" alt="Gravatar">' html = f'<img src="{url}" width="{size}" height="{size}" alt="Gravatar">'
return mark_safe(html) return mark_safe(html)
@register.filter
def gravatar_no_hover(email, size=20):
"""
Returns an HTML image tag for the Gravatar of a given email,
with the specified width and height.
"""
url = gravatar_url(email, size)
# Return a safe HTML snippet with the image element
html = f'<img src="{url}" width="{size}" height="{size}" alt="Gravatar" class="ignore">'
return mark_safe(html)
@register.filter @register.filter
def gravatar_profile_data(email): def gravatar_profile_data(email):
""" """

View file

@ -6,6 +6,7 @@ from .views import (
ChangeDefaultFriendCodeView, ChangeDefaultFriendCodeView,
EditFriendCodeView, EditFriendCodeView,
SettingsView, SettingsView,
ProfileView,
) )
urlpatterns = [ urlpatterns = [
@ -16,4 +17,5 @@ urlpatterns = [
path("friend-codes/delete/<int:pk>/", DeleteFriendCodeView.as_view(), name="delete_friend_code"), path("friend-codes/delete/<int:pk>/", DeleteFriendCodeView.as_view(), name="delete_friend_code"),
path("friend-codes/default/<int:pk>/", ChangeDefaultFriendCodeView.as_view(), name="change_default_friend_code"), path("friend-codes/default/<int:pk>/", ChangeDefaultFriendCodeView.as_view(), name="change_default_friend_code"),
path("settings/", SettingsView.as_view(), name="settings"), path("settings/", SettingsView.as_view(), name="settings"),
path("profile/", ProfileView.as_view(), name="profile"),
] ]

View file

@ -129,6 +129,12 @@ class SettingsView(LoginRequiredMixin, TemplateView):
""" """
template_name = "account/settings.html" template_name = "account/settings.html"
class ProfileView(LoginRequiredMixin, TemplateView):
"""
Display the user's profile.
"""
template_name = "account/profile.html"
class EditFriendCodeView(LoginRequiredMixin, UpdateView): class EditFriendCodeView(LoginRequiredMixin, UpdateView):
""" """
Edit the in-game name for a friend code. Edit the in-game name for a friend code.

View file

@ -2,12 +2,6 @@ const $ = x => Array.from(document.querySelectorAll(x));
const $$ = x => Array.from(document.querySelector(x)); const $$ = x => Array.from(document.querySelector(x));
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Initialize Gravatar if available
if (typeof Gravatar !== 'undefined' && typeof Gravatar.init === 'function') {
Gravatar.init();
}
const themeToggleBtn = document.getElementById('theme-toggle-btn'); const themeToggleBtn = document.getElementById('theme-toggle-btn');
if (themeToggleBtn) { if (themeToggleBtn) {
themeToggleBtn.addEventListener('click', function() { themeToggleBtn.addEventListener('click', function() {

View file

@ -0,0 +1,26 @@
{% extends 'base.html' %}
{% load i18n gravatar%}
{% block head_title %}{% trans "Settings" %}{% endblock %}
{% block content %}
<div class="container mx-auto">
<h1 class="text-3xl font-semibold text-center mb-6">{% trans "Profile" %}</h1>
<div class="card card-border bg-base-100 shadow-lg w-4/5 mx-auto">
<div class="card-body">
<div class="mx-auto mb-4">{{ user.email|gravatar:100 }}</div>
<p class="text-center">All profile information is managed through Gravatar.</p>
<p class="text-center mt-4"><a href="https://gravatar.com/profile/" target="_blank" rel="noopener noreferrer" class="btn btn-secondary">Edit Profile on Gravatar</a></p>
<div class="divider"></div>
<h2 class="text-lg font-semibold pt-0">What is Gravatar?</h2>
<p class="mb-4">Gravatar (Globally Recognized Avatar) is a free service that links your email address to a profile picture and, optionally, a profile. Many websites, including this one, use Gravatar to display your avatar and profile automatically.</p>
<h2 class="text-lg font-semibold">How does it work?</h2>
<p class="mb-4">If youve set up a Gravatar, your profile picture will appear here whenever you use your email on supported sites. When someone hovers over or clicks on your avatar, your Gravatar profile will appear if you have one. If you dont have a Gravatar yet, youll see a default image instead.</p>
<h2 class="text-lg font-semibold">Want to update or add a Gravatar?</h2>
<p class="mb-4">Go to Gravatar.com to set up or change your avatar or profile. Your updates will appear here once saved!</p>
</div>
</div>
</div>
{% endblock %}

View file

@ -8,7 +8,7 @@
<h1 class="text-3xl font-bold text-center mb-6">{% trans "Settings" %}</h1> <h1 class="text-3xl font-bold text-center mb-6">{% trans "Settings" %}</h1>
<div class="card card-border bg-base-100 shadow-lg w-4/5 mx-auto"> <div class="card card-border bg-base-100 shadow-lg w-4/5 mx-auto">
<div class="flex flex-col gap-6 w-full mx-auto p-6"> <div class="flex flex-col gap-6 w-full mx-auto p-6">
<a href="https://gravatar.com/profile/" target="_blank" rel="noopener noreferrer" class="btn btn-secondary"> <a href="{% url 'profile' %}" class="btn btn-secondary">
{% trans "Profile" %} {% trans "Profile" %}
</a> </a>
<a href="{% url 'list_friend_codes' %}" class="btn btn-primary"> <a href="{% url 'list_friend_codes' %}" class="btn btn-primary">

View file

@ -36,6 +36,14 @@
<!-- Floating UI --> <!-- Floating UI -->
<script src="https://cdn.jsdelivr.net/npm/@floating-ui/core@1.6.9"></script> <script src="https://cdn.jsdelivr.net/npm/@floating-ui/core@1.6.9"></script>
<script src="https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.6.13"></script> <script src="https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.6.13"></script>
<!-- Gravatar -->
<!-- Import the hovercard styles -->
<link rel="stylesheet" href="https://unpkg.com/@gravatar-com/hovercards@0.10.8/dist/style.css">
<!-- Import the hovercards library -->
<script src="https://unpkg.com/@gravatar-com/hovercards@0.10.8"></script>
{% block css %}{% endblock %} {% block css %}{% endblock %}
{% block javascript_head %}{% endblock %} {% block javascript_head %}{% endblock %}
@ -97,14 +105,14 @@
<div class="dropdown dropdown-end hidden sm:block"> <div class="dropdown dropdown-end hidden sm:block">
<div tabindex="0" role="button" class="btn btn-ghost btn-circle avatar"> <div tabindex="0" role="button" class="btn btn-ghost btn-circle avatar">
<div class="w-10 rounded-full"> <div class="w-10 rounded-full">
{{ user.email|gravatar:40 }} {{ user.email|gravatar_no_hover:40 }}
</div> </div>
</div> </div>
<ul <ul
tabindex="0" tabindex="0"
class="menu menu-sm dropdown-content bg-base-100 rounded-box z-1 mt-3 w-32 p-2 shadow"> class="menu menu-sm dropdown-content bg-base-100 rounded-box z-1 mt-3 w-32 p-2 shadow">
<li> <li>
<a class="flex items-center justify-between" href="https://www.gravatar.com/profile/" target="_blank" rel="noopener noreferrer"> <a class="flex items-center justify-between" href="{% url 'profile' %}">
<div>Profile</div> <div>Profile</div>
<div> <div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
@ -171,7 +179,29 @@
<script defer src="{% static 'js/tooltip.js' %}"></script> <script defer src="{% static 'js/tooltip.js' %}"></script>
<script defer src="{% static 'js/base.js' %}"></script> <!-- Gravatar -->
<script>
document.addEventListener('DOMContentLoaded', function() {
if (typeof Gravatar !== 'undefined' && typeof Gravatar.Hovercards !== 'undefined') {
const hovercards = new Gravatar.Hovercards({
myHash: '{{ user.email|gravatar_hash }}'
});
hovercards.attach( document.body, { ignoreSelector: 'img[src*="gravatar.com/avatar/"].ignore' } );
}
});
// i18n: {
// 'Edit your profile →': 'Modifier votre profil →',
// 'View profile →': 'Voir le profil →',
// 'Contact': 'Contact',
// 'Send money': 'Envoyer de l\'argent',
// 'Sorry, we are unable to load this Gravatar profile.': 'Désolé, nous ne pouvons pas charger ce profil Gravatar.',
// 'Profile not found.': 'Profil non trouvé.',
// 'Too Many Requests.': 'Trop de demandes.',
// 'Internal Server Error.': 'Erreur interne du serveur.',
// }
</script>
<script defer src="{% static 'js/base.js' %}"></script>
{% block javascript %}{% endblock %} {% block javascript %}{% endblock %}
</body> </body>
</html> </html>