Add script to create channels per tournament, pools and teams. Put channels in categories

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello 2024-04-28 13:50:04 +02:00
parent 784002c085
commit a5c210e9b6
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
10 changed files with 273 additions and 35 deletions

View File

@ -8,8 +8,8 @@ from .models import Channel, Message
@admin.register(Channel) @admin.register(Channel)
class ChannelAdmin(admin.ModelAdmin): class ChannelAdmin(admin.ModelAdmin):
list_display = ('name', 'read_access', 'write_access', 'tournament', 'pool', 'team', 'private',) list_display = ('name', 'category', 'read_access', 'write_access', 'tournament', 'private',)
list_filter = ('read_access', 'write_access', 'tournament', 'private',) list_filter = ('category', 'read_access', 'write_access', 'tournament', 'private',)
search_fields = ('name', 'tournament__name', 'team__name', 'team__trigram',) search_fields = ('name', 'tournament__name', 'team__name', 'team__trigram',)
autocomplete_fields = ('tournament', 'pool', 'team', 'invited', ) autocomplete_fields = ('tournament', 'pool', 'team', 'invited', )

View File

@ -3,7 +3,6 @@
from channels.generic.websocket import AsyncJsonWebsocketConsumer from channels.generic.websocket import AsyncJsonWebsocketConsumer
from django.contrib.auth.models import User from django.contrib.auth.models import User
from participation.models import Team, Pool, Tournament
from registration.models import Registration from registration.models import Registration
from .models import Channel, Message from .models import Channel, Message
@ -78,6 +77,7 @@ class ChatConsumer(AsyncJsonWebsocketConsumer):
{ {
'id': channel.id, 'id': channel.id,
'name': channel.name, 'name': channel.name,
'category': channel.category,
'read_access': True, 'read_access': True,
'write_access': await write_channels.acontains(channel), 'write_access': await write_channels.acontains(channel),
} }

View File

View File

View File

@ -0,0 +1,144 @@
# Copyright (C) 2024 by Animath
# SPDX-License-Identifier: GPL-3.0-or-later
from django.core.management import BaseCommand
from django.utils.translation import activate
from participation.models import Team, Tournament
from tfjm.permissions import PermissionType
from ...models import Channel
class Command(BaseCommand):
def handle(self, *args, **kwargs):
activate('fr')
Channel.objects.update_or_create(
name="Annonces",
defaults=dict(
category=Channel.ChannelCategory.GENERAL,
read_access=PermissionType.AUTHENTICATED,
write_access=PermissionType.ADMIN,
),
)
Channel.objects.update_or_create(
name="Aide jurys et orgas",
defaults=dict(
category=Channel.ChannelCategory.GENERAL,
read_access=PermissionType.VOLUNTEER,
write_access=PermissionType.VOLUNTEER,
),
)
Channel.objects.update_or_create(
name="Général",
defaults=dict(
category=Channel.ChannelCategory.GENERAL,
read_access=PermissionType.AUTHENTICATED,
write_access=PermissionType.AUTHENTICATED,
),
)
Channel.objects.update_or_create(
name="Je cherche une équipe",
defaults=dict(
category=Channel.ChannelCategory.GENERAL,
read_access=PermissionType.AUTHENTICATED,
write_access=PermissionType.AUTHENTICATED,
),
)
Channel.objects.update_or_create(
name="Détente",
defaults=dict(
category=Channel.ChannelCategory.GENERAL,
read_access=PermissionType.AUTHENTICATED,
write_access=PermissionType.AUTHENTICATED,
),
)
for tournament in Tournament.objects.all():
Channel.objects.update_or_create(
name=f"{tournament.name} - Annonces",
defaults=dict(
category=Channel.ChannelCategory.TOURNAMENT,
read_access=PermissionType.TOURNAMENT_MEMBER,
write_access=PermissionType.TOURNAMENT_ORGANIZER,
tournament=tournament,
),
)
Channel.objects.update_or_create(
name=f"{tournament.name} - Général",
defaults=dict(
category=Channel.ChannelCategory.TOURNAMENT,
read_access=PermissionType.TOURNAMENT_MEMBER,
write_access=PermissionType.TOURNAMENT_MEMBER,
tournament=tournament,
),
)
Channel.objects.update_or_create(
name=f"{tournament.name} - Détente",
defaults=dict(
category=Channel.ChannelCategory.TOURNAMENT,
read_access=PermissionType.TOURNAMENT_MEMBER,
write_access=PermissionType.TOURNAMENT_MEMBER,
tournament=tournament,
),
)
Channel.objects.update_or_create(
name=f"{tournament.name} - Juré⋅es",
defaults=dict(
category=Channel.ChannelCategory.TOURNAMENT,
read_access=PermissionType.JURY_MEMBER,
write_access=PermissionType.JURY_MEMBER,
tournament=tournament,
),
)
if tournament.remote:
Channel.objects.update_or_create(
name=f"{tournament.name} - Président⋅es de jury",
defaults=dict(
category=Channel.ChannelCategory.TOURNAMENT,
read_access=PermissionType.TOURNAMENT_JURY_PRESIDENT,
write_access=PermissionType.TOURNAMENT_JURY_PRESIDENT,
tournament=tournament,
),
)
for pool in tournament.pools.all():
Channel.objects.update_or_create(
name=f"{tournament.name} - Poule {pool.short_name}",
defaults=dict(
category=Channel.ChannelCategory.TOURNAMENT,
read_access=PermissionType.POOL_MEMBER,
write_access=PermissionType.POOL_MEMBER,
pool=pool,
),
)
Channel.objects.update_or_create(
name=f"{tournament.name} - Poule {pool.short_name} - Jury",
defaults=dict(
category=Channel.ChannelCategory.TOURNAMENT,
read_access=PermissionType.JURY_MEMBER,
write_access=PermissionType.JURY_MEMBER,
pool=pool,
),
)
for team in Team.objects.filter(participation__valid=True).all():
Channel.objects.update_or_create(
name=f"Équipe {team.trigram}",
defaults=dict(
category=Channel.ChannelCategory.TEAM,
read_access=PermissionType.TEAM_MEMBER,
write_access=PermissionType.TEAM_MEMBER,
team=team,
),
)

View File

@ -0,0 +1,36 @@
# Generated by Django 5.0.3 on 2024-04-28 11:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("chat", "0001_initial"),
]
operations = [
migrations.AlterModelOptions(
name="channel",
options={
"ordering": ("category", "name"),
"verbose_name": "channel",
"verbose_name_plural": "channels",
},
),
migrations.AddField(
model_name="channel",
name="category",
field=models.CharField(
choices=[
("general", "General channels"),
("tournament", "Tournament channels"),
("team", "Team channels"),
("private", "Private channels"),
],
default="general",
max_length=255,
verbose_name="category",
),
),
]

View File

@ -13,11 +13,24 @@ from tfjm.permissions import PermissionType
class Channel(models.Model): class Channel(models.Model):
class ChannelCategory(models.TextChoices):
GENERAL = 'general', _("General channels")
TOURNAMENT = 'tournament', _("Tournament channels")
TEAM = 'team', _("Team channels")
PRIVATE = 'private', _("Private channels")
name = models.CharField( name = models.CharField(
max_length=255, max_length=255,
verbose_name=_("name"), verbose_name=_("name"),
) )
category = models.CharField(
max_length=255,
verbose_name=_("category"),
choices=ChannelCategory,
default=ChannelCategory.GENERAL,
)
read_access = models.CharField( read_access = models.CharField(
max_length=16, max_length=16,
verbose_name=_("read permission"), verbose_name=_("read permission"),
@ -90,7 +103,7 @@ class Channel(models.Model):
return Channel.objects.filter(**{permission_type: PermissionType.ANONYMOUS}) return Channel.objects.filter(**{permission_type: PermissionType.ANONYMOUS})
qs |= Channel.objects.filter(**{permission_type: PermissionType.AUTHENTICATED}) qs |= Channel.objects.filter(**{permission_type: PermissionType.AUTHENTICATED})
registration = await Registration.objects.aget(user_id=user.id) registration = await Registration.objects.prefetch_related('user').aget(user_id=user.id)
if registration.is_admin: if registration.is_admin:
return Channel.objects.all() return Channel.objects.all()
@ -147,7 +160,7 @@ class Channel(models.Model):
class Meta: class Meta:
verbose_name = _("channel") verbose_name = _("channel")
verbose_name_plural = _("channels") verbose_name_plural = _("channels")
ordering = ('name',) ordering = ('category', 'name',)
class Message(models.Model): class Message(models.Model):

View File

@ -6,6 +6,7 @@
const MAX_MESSAGES = 50 const MAX_MESSAGES = 50
const channel_categories = ['general', 'tournament', 'team', 'private']
let channels = {} let channels = {}
let messages = {} let messages = {}
let selected_channel_id = null let selected_channel_id = null
@ -62,20 +63,27 @@ function sendMessage() {
function setChannels(new_channels) { function setChannels(new_channels) {
channels = {} channels = {}
let navTab = document.getElementById('nav-channels-tab') let categoryLists = {}
navTab.innerHTML = '' for (let category of channel_categories) {
categoryLists[category] = document.getElementById(`nav-${category}-channels-tab`)
categoryLists[category].innerHTML = ''
categoryLists[category].parentElement.classList.add('d-none')
}
for (let channel of new_channels) { for (let channel of new_channels) {
channels[channel['id']] = channel channels[channel['id']] = channel
if (!messages[channel['id']]) if (!messages[channel['id']])
messages[channel['id']] = new Map() messages[channel['id']] = new Map()
let categoryList = categoryLists[channel['category']]
categoryList.parentElement.classList.remove('d-none')
let navItem = document.createElement('li') let navItem = document.createElement('li')
navItem.classList.add('list-group-item') navItem.classList.add('list-group-item')
navItem.id = `tab-channel-${channel['id']}` navItem.id = `tab-channel-${channel['id']}`
navItem.setAttribute('data-bs-dismiss', 'offcanvas') navItem.setAttribute('data-bs-dismiss', 'offcanvas')
navItem.onclick = () => selectChannel(channel['id']) navItem.onclick = () => selectChannel(channel['id'])
navTab.appendChild(navItem) categoryList.appendChild(navItem)
let channelButton = document.createElement('button') let channelButton = document.createElement('button')
channelButton.classList.add('nav-link') channelButton.classList.add('nav-link')

View File

@ -3,13 +3,30 @@
<noscript> <noscript>
{% trans "JavaScript must be enabled on your browser to access chat." %} {% trans "JavaScript must be enabled on your browser to access chat." %}
</noscript> </noscript>
<div class="offcanvas offcanvas-start" tabindex="-1" id="channelSelector" aria-labelledby="offcanvasExampleLabel"> <div class="offcanvas offcanvas-start" tabindex="-1" id="channelSelector" aria-labelledby="offcanvasTitle">
<div class="offcanvas-header"> <div class="offcanvas-header">
<h4 class="offcanvas-title" id="offcanvasExampleLabel">{% trans "Chat channels" %}</h4> <h3 class="offcanvas-title" id="offcanvasTitle">{% trans "Chat channels" %}</h3>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div> </div>
<div class="offcanvas-body"> <div class="offcanvas-body">
<ul class="list-group list-group-flush" id="nav-channels-tab"></ul> <ul class="list-group list-group-flush" id="nav-channels-tab">
<li class="list-group-item d-none">
<h4>{% trans "General channels" %}</h4>
<ul class="list-group list-group-flush" id="nav-general-channels-tab"></ul>
</li>
<li class="list-group-item d-none">
<h4>{% trans "Tournament channels" %}</h4>
<ul class="list-group list-group-flush" id="nav-tournament-channels-tab"></ul>
</li>
<li class="list-group-item d-none">
<h4>{% trans "Team channels" %}</h4>
<ul class="list-group list-group-flush" id="nav-team-channels-tab"></ul>
</li>
<li class="list-group-item d-none">
<h4>{% trans "Private channels" %}</h4>
<ul class="list-group list-group-flush" id="nav-private-channels-tab"></ul>
</li>
</ul>
</div> </div>
</div> </div>

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TFJM\n" "Project-Id-Version: TFJM\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-04-28 11:56+0200\n" "POT-Creation-Date: 2024-04-28 13:08+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n" "Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -21,20 +21,40 @@ msgstr ""
msgid "API" msgid "API"
msgstr "API" msgstr "API"
#: chat/models.py:18 participation/models.py:35 participation/models.py:263 #: chat/models.py:17
msgid "General channels"
msgstr "Canaux généraux"
#: chat/models.py:18
msgid "Tournament channels"
msgstr "Canaux de tournois"
#: chat/models.py:19
msgid "Team channels"
msgstr "Canaux d'équipes"
#: chat/models.py:20
msgid "Private channels"
msgstr "Messages privés"
#: chat/models.py:24 participation/models.py:35 participation/models.py:263
#: participation/tables.py:18 participation/tables.py:34 #: participation/tables.py:18 participation/tables.py:34
msgid "name" msgid "name"
msgstr "nom" msgstr "nom"
#: chat/models.py:23 #: chat/models.py:29
msgid "category"
msgstr "catégorie"
#: chat/models.py:36
msgid "read permission" msgid "read permission"
msgstr "permission de lecture" msgstr "permission de lecture"
#: chat/models.py:29 #: chat/models.py:42
msgid "write permission" msgid "write permission"
msgstr "permission d'écriture" msgstr "permission d'écriture"
#: chat/models.py:39 draw/admin.py:53 draw/admin.py:71 draw/admin.py:88 #: chat/models.py:52 draw/admin.py:53 draw/admin.py:71 draw/admin.py:88
#: draw/models.py:26 participation/admin.py:79 participation/admin.py:140 #: draw/models.py:26 participation/admin.py:79 participation/admin.py:140
#: participation/admin.py:171 participation/models.py:693 #: participation/admin.py:171 participation/models.py:693
#: participation/models.py:717 participation/models.py:935 #: participation/models.py:717 participation/models.py:935
@ -43,7 +63,7 @@ msgstr "permission d'écriture"
msgid "tournament" msgid "tournament"
msgstr "tournoi" msgstr "tournoi"
#: chat/models.py:41 #: chat/models.py:54
msgid "" msgid ""
"For a permission that concerns a tournament, indicates what is the concerned " "For a permission that concerns a tournament, indicates what is the concerned "
"tournament." "tournament."
@ -51,21 +71,21 @@ msgstr ""
"Pour une permission qui concerne un tournoi, indique quel est le tournoi " "Pour une permission qui concerne un tournoi, indique quel est le tournoi "
"concerné." "concerné."
#: chat/models.py:50 draw/models.py:429 draw/models.py:456 #: chat/models.py:63 draw/models.py:429 draw/models.py:456
#: participation/admin.py:136 participation/admin.py:155 #: participation/admin.py:136 participation/admin.py:155
#: participation/models.py:1434 participation/models.py:1443 #: participation/models.py:1434 participation/models.py:1443
#: participation/tables.py:84 #: participation/tables.py:84
msgid "pool" msgid "pool"
msgstr "poule" msgstr "poule"
#: chat/models.py:52 #: chat/models.py:65
msgid "" msgid ""
"For a permission that concerns a pool, indicates what is the concerned pool." "For a permission that concerns a pool, indicates what is the concerned pool."
msgstr "" msgstr ""
"Pour une permission qui concerne une poule, indique quelle est la poule " "Pour une permission qui concerne une poule, indique quelle est la poule "
"concernée." "concernée."
#: chat/models.py:61 draw/templates/draw/tournament_content.html:277 #: chat/models.py:74 draw/templates/draw/tournament_content.html:277
#: participation/admin.py:167 participation/models.py:252 #: participation/admin.py:167 participation/models.py:252
#: participation/models.py:708 #: participation/models.py:708
#: participation/templates/participation/tournament_harmonize.html:15 #: participation/templates/participation/tournament_harmonize.html:15
@ -75,18 +95,18 @@ msgstr ""
msgid "team" msgid "team"
msgstr "équipe" msgstr "équipe"
#: chat/models.py:63 #: chat/models.py:76
msgid "" msgid ""
"For a permission that concerns a team, indicates what is the concerned team." "For a permission that concerns a team, indicates what is the concerned team."
msgstr "" msgstr ""
"Pour une permission qui concerne une équipe, indique quelle est l'équipe " "Pour une permission qui concerne une équipe, indique quelle est l'équipe "
"concernée." "concernée."
#: chat/models.py:67 #: chat/models.py:80
msgid "private" msgid "private"
msgstr "privé" msgstr "privé"
#: chat/models.py:69 #: chat/models.py:82
msgid "" msgid ""
"If checked, only users who have been explicitly added to the channel will be " "If checked, only users who have been explicitly added to the channel will be "
"able to access it." "able to access it."
@ -94,11 +114,11 @@ msgstr ""
"Si sélectionné, seul⋅es les utilisateur⋅rices qui ont été explicitement " "Si sélectionné, seul⋅es les utilisateur⋅rices qui ont été explicitement "
"ajouté⋅es au canal pourront y accéder." "ajouté⋅es au canal pourront y accéder."
#: chat/models.py:74 #: chat/models.py:87
msgid "invited users" msgid "invited users"
msgstr "Utilisateur⋅rices invité" msgstr "Utilisateur⋅rices invité"
#: chat/models.py:77 #: chat/models.py:90
msgid "" msgid ""
"Extra users who have been invited to the channel, in addition to the " "Extra users who have been invited to the channel, in addition to the "
"permitted group of the channel." "permitted group of the channel."
@ -106,40 +126,40 @@ msgstr ""
"Utilisateur⋅rices supplémentaires qui ont été invité⋅es au canal, en plus du " "Utilisateur⋅rices supplémentaires qui ont été invité⋅es au canal, en plus du "
"groupe autorisé du canal." "groupe autorisé du canal."
#: chat/models.py:82 #: chat/models.py:95
#, python-brace-format #, python-brace-format
msgid "Channel {name}" msgid "Channel {name}"
msgstr "Canal {name}" msgstr "Canal {name}"
#: chat/models.py:148 chat/models.py:157 #: chat/models.py:161 chat/models.py:170
msgid "channel" msgid "channel"
msgstr "canal" msgstr "canal"
#: chat/models.py:149 #: chat/models.py:162
msgid "channels" msgid "channels"
msgstr "canaux" msgstr "canaux"
#: chat/models.py:163 #: chat/models.py:176
msgid "author" msgid "author"
msgstr "auteur⋅rice" msgstr "auteur⋅rice"
#: chat/models.py:170 #: chat/models.py:183
msgid "created at" msgid "created at"
msgstr "créé le" msgstr "créé le"
#: chat/models.py:175 #: chat/models.py:188
msgid "updated at" msgid "updated at"
msgstr "modifié le" msgstr "modifié le"
#: chat/models.py:180 #: chat/models.py:193
msgid "content" msgid "content"
msgstr "contenu" msgstr "contenu"
#: chat/models.py:243 #: chat/models.py:256
msgid "message" msgid "message"
msgstr "message" msgstr "message"
#: chat/models.py:244 #: chat/models.py:257
msgid "messages" msgid "messages"
msgstr "messages" msgstr "messages"
@ -171,7 +191,7 @@ msgstr "Déconnexion"
msgid "Install app on home screen" msgid "Install app on home screen"
msgstr "Installer l'application sur l'écran d'accueil" msgstr "Installer l'application sur l'écran d'accueil"
#: chat/templates/chat/content.html:54 #: chat/templates/chat/content.html:55
msgid "Fetch previous messages…" msgid "Fetch previous messages…"
msgstr "Récupérer les messages précédents…" msgstr "Récupérer les messages précédents…"