Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add public profile, badges and replace icons #26

Merged
merged 3 commits into from
Oct 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
## O projekte

Trojsten ID vznikol ako náhrada predchádzajúceho `login.trojsten.sk` riešenia. Jeho snahou je vytvoriť jednotný
prihlasovací systém pre všetky Trojsten stránky a služby. Taktiež poskytuje informácie o používateľoch a (čoskoro)
prihlasovací systém pre všetky Trojsten stránky a služby. Taktiež poskytuje informácie o používateľoch a
verejné profily.

## Inštalácia a quick-start
Expand Down
Empty file added trojstenid/badges/__init__.py
Empty file.
18 changes: 18 additions & 0 deletions trojstenid/badges/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django.contrib import admin

from trojstenid.badges.models import Badge, BadgeAssignment, BadgeGroup


class BadgeAssignmentInline(admin.TabularInline):
model = BadgeAssignment


@admin.register(Badge)
class BadgeAdmin(admin.ModelAdmin):
list_filter = ["group", "title"]
inlines = [BadgeAssignmentInline]


@admin.register(BadgeGroup)
class BadgeGroupAdmin(admin.ModelAdmin):
list_filter = ["title"]
6 changes: 6 additions & 0 deletions trojstenid/badges/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class BadgesConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "trojstenid.badges"
97 changes: 97 additions & 0 deletions trojstenid/badges/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Generated by Django 4.2.4 on 2023-09-10 19:09

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


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="Badge",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("image", models.ImageField(upload_to="")),
("title", models.CharField(max_length=100)),
("description", models.CharField(max_length=300)),
("order", models.IntegerField(default=0)),
],
options={
"ordering": ["group", "order", "title"],
},
),
migrations.CreateModel(
name="BadgeGroup",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=100)),
],
options={
"ordering": ["title"],
},
),
migrations.CreateModel(
name="BadgeAssignment",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
(
"badge",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="badges.badge"
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
),
migrations.AddField(
model_name="badge",
name="group",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="badges.badgegroup"
),
),
migrations.AddConstraint(
model_name="badgeassignment",
constraint=models.UniqueConstraint(
models.F("badge"), models.F("user"), name="badge_assignment__unique"
),
),
]
Empty file.
38 changes: 38 additions & 0 deletions trojstenid/badges/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from django.conf import settings
from django.db import models
from django.db.models import UniqueConstraint


class BadgeGroup(models.Model):
title = models.CharField(max_length=100)

class Meta:
ordering = ["title"]

def __str__(self):
return self.title


class Badge(models.Model):
image = models.ImageField()
title = models.CharField(max_length=100)
description = models.CharField(max_length=300)
group = models.ForeignKey(BadgeGroup, on_delete=models.CASCADE)
order = models.IntegerField(default=0)

class Meta:
ordering = ["group", "order", "title"]

def __str__(self):
return self.title


class BadgeAssignment(models.Model):
badge = models.ForeignKey(Badge, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
constraints = [
UniqueConstraint("badge", "user", name="badge_assignment__unique"),
]
1 change: 1 addition & 0 deletions trojstenid/badges/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Create your views here.
53 changes: 53 additions & 0 deletions trojstenid/profiles/templates/profile/profile.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{% extends "base.html" %}

{% block title %}{{ object.get_full_name }} - {{ block.super }}{% endblock %}

{% block body %}

<div class="max-w-4xl mx-auto p-4 sm:p-6">
<div class="w-full bg-blue-500 h-32 rounded-lg"></div>
<div class="-mt-20 text-center">
<img src="{{ object.avatar }}" alt="{{ object.get_full_name }}" class="w-32 h-32 mx-auto outline-white outline-4 outline rounded-full">
<h1 class="font-bold text-2xl mt-3">
{{ object.get_full_name }}
</h1>
<div>
{% if "trojsten:veduci" in groups %}
<span class="bg-red-600 text-white mt-1 font-bold gap-1 text-sm px-1 py-0.5 rounded inline-flex items-center">
<span class="iconify inline h-4 w-4 text-white" data-icon="mdi:account-tie"></span>
Vedúci
</span>
{% endif %}
</div>
</div>

<hr class="my-5">

<h2 class="font-semibold text-3xl mb-4">Odznaky</h2>

{% if badges %}
{% regroup badges by group as groups %}
{% for group, items in groups %}
<h3 class="font-semibold text-2xl mb-2">{{ group.title }}</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-2">
{% for item in items %}
<div class="flex gap-2 items-center">
<img src="{{ item.image.url }}" class="rounded-lg h-24 shrink-0" alt="{{ item.title }}">
<div>
<p class="text-lg font-bold leading-5">{{ item.title }}</p>
<p class="leading-5 text-gray-600">{{ item.description }}</p>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
{% else %}
<div class="text-center">
<span class="iconify w-12 h-12 text-gray-400 mx-auto" data-icon="mdi:trophy-broken"></span>
<h3 class="mt-2 text-sm font-semibold text-gray-900">Žiadne odznaky</h3>
<p class="mt-1 text-sm text-gray-500">Tento používateľ zatiaľ nezískal žiadne odznaky.</p>
</div>
{% endif %}
</div>

{% endblock %}
1 change: 1 addition & 0 deletions trojstenid/profiles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

urlpatterns = [
path("<user>/avatar/", views.AvatarView.as_view(), name="profile_avatar"),
path("<user>/", views.ProfileView.as_view(), name="profile"),
]
18 changes: 17 additions & 1 deletion trojstenid/profiles/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import random

from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.views.generic import TemplateView
from django.views.generic import DetailView, TemplateView
from PIL import ImageColor

from trojstenid.badges.models import Badge
from trojstenid.users.models import User


Expand Down Expand Up @@ -34,3 +36,17 @@ def get_context_data(self, **kwargs):
ctx["color"] = self.get_text_color(background)
ctx["text"] = initials
return ctx


class ProfileView(LoginRequiredMixin, DetailView):
template_name = "profile/profile.html"

def get_object(self, queryset=None):
return get_object_or_404(User, username=self.kwargs["user"])

def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
user = ctx["object"]
ctx["groups"] = user.groups.values_list("name", flat=True)
ctx["badges"] = Badge.objects.filter(badgeassignment__user=user)
return ctx
1 change: 1 addition & 0 deletions trojstenid/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"debug_toolbar",
"trojstenid.users",
"trojstenid.profiles",
"trojstenid.badges",
"widget_tweaks",
"captcha",
"allauth",
Expand Down
2 changes: 1 addition & 1 deletion trojstenid/users/templates/_partials/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<form action="{% url "account_logout" %}" method="post" class="ml-auto">
{% csrf_token %}
<button type="submit" class="text-red-600 p-1.5 hover:bg-red-700 hover:text-white inline-flex rounded">
<iconify-icon icon="mdi:logout" height="24"></iconify-icon>
<span data-icon="mdi:logout" class="iconify h-6 w-6"></span>
</button>
</form>
</a>
Expand Down
2 changes: 1 addition & 1 deletion trojstenid/users/templates/_partials/navbar_items.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<li>
<a href="{% url item.2 %}"
class="{% if request.resolver_match.view_name == item.2 %}text-white bg-gray-800{% else %}text-gray-400 hover:text-white hover:bg-gray-800 group{% endif %} flex gap-x-2 rounded-md p-2 text-sm leading-6 font-bold">
<iconify-icon icon="{{ item.0 }}" height="24"></iconify-icon>
<span data-icon="{{ item.0 }}" class="iconify h-6 w-6"></span>
{{ item.1 }}
</a>
</li>
Expand Down
2 changes: 1 addition & 1 deletion trojstenid/users/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{% block body %}{% endblock %}
{% include "_partials/messages.html" %}

<script src="https://cdn.jsdelivr.net/npm/iconify-icon@1.0.7/dist/iconify-icon.min.js"></script>
<script src="https://code.iconify.design/2/2.0.0/iconify.min.js"></script>
<script src="//unpkg.com/alpinejs" defer></script>
</body>
</html>
2 changes: 1 addition & 1 deletion trojstenid/users/templates/landing.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

<a href="{% url "account_login" %}" class="font-bold leading-6 text-gray-900 hover:text-gray-700 flex items-center gap-2">
Prihlásiť sa
<iconify-icon icon="mdi:arrow-right" height="18"></iconify-icon>
<span class="iconify h-5 w-5" data-icon="mdi:arrow-right"></span>
</a>
</nav>

Expand Down
2 changes: 1 addition & 1 deletion trojstenid/users/templates/oauth2_provider/authorize.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h2 class="mb-6 text-center text-2xl font-bold tracking-tight text-gray-900">

{% else %}
<div class="rounded-md bg-red-50 p-4 flex">
<iconify-icon icon="mdi:alert-circle" class="text-red-400" height="20"></iconify-icon>
<span data-icon="mdi:alert-circle" class="text-red-400 iconify h-5 w-5"></span>
<p class="text-sm text-red-800 ml-3">
<b>Chyba:</b> {{ error.error }}<br>
<span class="text-xs">{{ error.description }}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ <h2 class="mb-6 text-center text-2xl font-bold tracking-tight text-gray-900">

{% else %}
<div class="rounded-md bg-red-50 p-4 flex">
<iconify-icon icon="mdi:alert-circle" class="text-red-400" height="20"></iconify-icon>
<span data-icon="mdi:alert-circle" class="text-red-400 iconify h-5 w-5"></span>
<p class="text-sm text-red-800 ml-3">
<b>Chyba:</b> {{ error.error }}<br>
<span class="text-xs">{{ error.description }}</span>
Expand Down
4 changes: 2 additions & 2 deletions trojstenid/users/templates/settings_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
>
<button type="button" class="-m-2.5 p-2.5 text-gray-200">
<span class="sr-only">Zavrieť menu</span>
<iconify-icon icon="mdi:close" height="24"></iconify-icon>
<span data-icon="mdi:close" class="iconify h-6 w-6"></span>
</button>
</div>

Expand All @@ -59,7 +59,7 @@
<div class="sticky top-0 z-40 flex items-center gap-x-6 bg-gray-900 px-4 py-4 shadow-sm sm:px-6 lg:hidden">
<button type="button" class="-m-2.5 p-2.5 text-gray-400 flex items-center justify-center lg:hidden" @click="sidebar = true">
<span class="sr-only">Otvoriť menu</span>
<iconify-icon icon="mdi:menu" height="24"></iconify-icon>
<span data-icon="mdi:menu" class="iconify h-6 w-6"></span>
</button>
</div>

Expand Down
2 changes: 1 addition & 1 deletion trojstenid/users/templates/socialaccount/connections.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ <h2 class="text-xl font-bold text-gray-900">Externé účty</h2>
</form>
{% else %}
<div class="rounded-md bg-red-50 p-4 mt-6 flex">
<iconify-icon icon="mdi:alert-circle" class="text-red-400" height="20"></iconify-icon>
<span data-icon="mdi:alert-circle" class="iconify text-red-400 h-5 w-5"></span>
<p class="text-sm text-red-800 ml-3">Nemáš pripojené žiadne externé účty</p>
</div>
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<button type="submit"
class="btn btn-black">
<iconify-icon icon="devicon-plain:google"></iconify-icon>
<span data-icon="devicon-plain:google" class="iconify h-4 w-4"></span>
Google
</button>
</form>
Expand Down