parent
182d7b85ce
commit
5783b5caa0
@ -16,6 +16,7 @@ from .models import (
|
||||
ReferenceLocation,
|
||||
StaticContent,
|
||||
Tag,
|
||||
UserProfile,
|
||||
)
|
||||
|
||||
admin.site.register(Category)
|
||||
@ -28,6 +29,7 @@ admin.site.register(Place)
|
||||
admin.site.register(Message)
|
||||
admin.site.register(ReferenceLocation)
|
||||
admin.site.register(Organisation)
|
||||
admin.site.register(UserProfile)
|
||||
|
||||
|
||||
class URLWidget(DynamicArrayWidget):
|
||||
|
@ -261,9 +261,24 @@ class CategorisationRuleImportForm(ModelForm):
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class MultipleChoiceFieldAcceptAll(MultipleChoiceField):
|
||||
def validate(self, value):
|
||||
pass
|
||||
|
||||
|
||||
class EventForm(GroupFormMixin, ModelForm):
|
||||
required_css_class = "required"
|
||||
|
||||
new_tags = MultipleChoiceFieldAcceptAll(
|
||||
label=_("New tags"),
|
||||
help_text=_(
|
||||
"Create new labels (sparingly). Note: by starting your tag with the characters “TW:”, you"
|
||||
"ll create a “trigger warning” tag, and the associated events will be announced as such."
|
||||
),
|
||||
widget=DynamicArrayWidget(),
|
||||
required=False,
|
||||
)
|
||||
|
||||
old_local_image = CharField(widget=HiddenInput(), required=False)
|
||||
simple_cloning = CharField(widget=HiddenInput(), required=False)
|
||||
cloning = CharField(widget=HiddenInput(), required=False)
|
||||
@ -311,10 +326,13 @@ class EventForm(GroupFormMixin, ModelForm):
|
||||
is_authenticated = kwargs.pop("is_authenticated", False)
|
||||
self.cloning = kwargs.pop("is_cloning", False)
|
||||
self.simple_cloning = kwargs.pop("is_simple_cloning", False)
|
||||
self.is_moderation_expert = kwargs.pop("is_moderation_expert", False)
|
||||
super().__init__(*args, **kwargs)
|
||||
if not is_authenticated:
|
||||
del self.fields["status"]
|
||||
del self.fields["organisers"]
|
||||
if not self.is_moderation_expert:
|
||||
del self.fields["new_tags"]
|
||||
self.fields["category"].queryset = self.fields["category"].queryset.order_by(
|
||||
"name"
|
||||
)
|
||||
@ -370,10 +388,14 @@ class EventForm(GroupFormMixin, ModelForm):
|
||||
self.fields["category"].group_id = "meta-admin"
|
||||
self.fields["tags"].group_id = "meta-admin"
|
||||
self.fields["status"].group_id = "meta-admin"
|
||||
if self.is_moderation_expert:
|
||||
self.fields["new_tags"].group_id = "meta-admin"
|
||||
else:
|
||||
self.add_group("meta", _("Meta information"))
|
||||
self.fields["category"].group_id = "meta"
|
||||
self.fields["tags"].group_id = "meta"
|
||||
if self.is_moderation_expert:
|
||||
self.fields["new_tags"].group_id = "meta"
|
||||
|
||||
def is_clone_from_url(self):
|
||||
return self.cloning
|
||||
@ -407,9 +429,15 @@ class EventForm(GroupFormMixin, ModelForm):
|
||||
|
||||
return end_time
|
||||
|
||||
def clean_new_tags(self):
|
||||
return list(set(self.cleaned_data.get("new_tags")))
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
if self.is_moderation_expert and self.cleaned_data.get("new_tags") is not None:
|
||||
self.cleaned_data["tags"] += self.cleaned_data.get("new_tags")
|
||||
|
||||
# when cloning an existing event, we need to copy the local image
|
||||
if (
|
||||
(
|
||||
@ -431,11 +459,6 @@ class EventFormWithContact(SimpleContactForm, EventForm):
|
||||
pass
|
||||
|
||||
|
||||
class MultipleChoiceFieldAcceptAll(MultipleChoiceField):
|
||||
def validate(self, value):
|
||||
pass
|
||||
|
||||
|
||||
class EventModerateForm(ModelForm):
|
||||
required_css_class = "required"
|
||||
|
||||
@ -468,10 +491,13 @@ class EventModerateForm(ModelForm):
|
||||
widgets = {"status": RadioSelect}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.is_moderation_expert = kwargs.pop("is_moderation_expert", False)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["category"].queryset = self.fields["category"].queryset.order_by(
|
||||
"name"
|
||||
)
|
||||
if not self.is_moderation_expert:
|
||||
del self.fields["new_tags"]
|
||||
self.fields["category"].empty_label = None
|
||||
self.fields["category"].initial = Category.get_default_category()
|
||||
self.fields["tags"].choices = Tag.get_tag_groups(all=True)
|
||||
@ -485,7 +511,7 @@ class EventModerateForm(ModelForm):
|
||||
if self.cleaned_data["tags"] is None:
|
||||
self.cleaned_data["tags"] = []
|
||||
|
||||
if self.cleaned_data.get("new_tags") is not None:
|
||||
if self.is_moderation_expert and self.cleaned_data.get("new_tags") is not None:
|
||||
self.cleaned_data["tags"] += self.cleaned_data.get("new_tags")
|
||||
|
||||
self.cleaned_data["tags"] = list(set(self.cleaned_data["tags"]))
|
||||
|
38
src/agenda_culturel/migrations/0155_userprofile.py
Normal file
38
src/agenda_culturel/migrations/0155_userprofile.py
Normal file
@ -0,0 +1,38 @@
|
||||
# Generated by Django 4.2.19 on 2025-03-14 16:35
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("auth", "0012_alter_user_first_name_max_length"),
|
||||
("agenda_culturel", "0154_tag_message"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="UserProfile",
|
||||
fields=[
|
||||
(
|
||||
"user",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_moderation_expert",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
help_text="This user is an expert in moderation, and the interface features additional functionalities.",
|
||||
verbose_name="Expert moderation user",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.2.19 on 2025-03-14 16:42
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("agenda_culturel", "0155_userprofile"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="userprofile",
|
||||
options={
|
||||
"verbose_name": "User profile",
|
||||
"verbose_name_plural": "User profiles",
|
||||
},
|
||||
),
|
||||
]
|
33
src/agenda_culturel/migrations/0157_auto_20250314_1645.py
Normal file
33
src/agenda_culturel/migrations/0157_auto_20250314_1645.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Generated by Django 4.2.19 on 2025-03-14 16:45
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def create_profiles(apps, schema_editor):
|
||||
User = apps.get_model("auth", "User")
|
||||
UserProfile = apps.get_model("agenda_culturel", "UserProfile")
|
||||
|
||||
for instance in User.objects.all():
|
||||
if not hasattr(instance, "userprofile"):
|
||||
UserProfile.objects.create(user=instance)
|
||||
instance.userprofile.is_moderation_expert = True
|
||||
|
||||
instance.userprofile.save()
|
||||
|
||||
|
||||
def create_profiles_backward(apps, schema_editor):
|
||||
pass
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("agenda_culturel", "0156_alter_userprofile_options"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=create_profiles,
|
||||
reverse_code=create_profiles_backward,
|
||||
),
|
||||
]
|
@ -40,6 +40,8 @@ from django_resized import ResizedImageField
|
||||
from icalendar import Calendar as icalCal
|
||||
from icalendar import Event as icalEvent
|
||||
from location_field.models.spatial import LocationField
|
||||
from django.dispatch import receiver
|
||||
from django.db.models.signals import post_save
|
||||
|
||||
from .calendar import CalendarDay
|
||||
from .import_tasks.extractor import Extractor
|
||||
@ -50,6 +52,37 @@ from .import_tasks.generic_extractors.fbevent import (
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserProfile(models.Model):
|
||||
user = models.OneToOneField(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
primary_key=True,
|
||||
)
|
||||
|
||||
is_moderation_expert = models.BooleanField(
|
||||
verbose_name=_("Expert moderation user"),
|
||||
help_text=_(
|
||||
"This user is an expert in moderation, and the interface features additional functionalities."
|
||||
),
|
||||
default=False,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("User profile")
|
||||
verbose_name_plural = _("User profiles")
|
||||
|
||||
def __str__(self):
|
||||
return _("User profile") + " (" + self.user.username + ")"
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def update_profile_signal(sender, instance, created, **kwargs):
|
||||
if not hasattr(instance, "userprofile"):
|
||||
UserProfile.objects.create(user=instance)
|
||||
|
||||
instance.userprofile.save()
|
||||
|
||||
|
||||
def remove_accents(input_str):
|
||||
if input_str is None:
|
||||
return None
|
||||
|
@ -9,7 +9,9 @@
|
||||
{% if local %}
|
||||
<a href="{{ local.get_absolute_url }}" role="button">Voir la version locale {% picto_from_name "eye" %}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'clone_edit' event.id %}" role="button">modifier & modérer {% picto_from_name "edit-3" %}</a>
|
||||
{% if user.userprofile.is_moderation_expert %}
|
||||
<a href="{% url 'clone_edit' event.id %}" role="button">modifier & modérer {% picto_from_name "edit-3" %}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
|
@ -472,6 +472,9 @@ class EventUpdateView(
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs["is_authenticated"] = self.request.user.is_authenticated
|
||||
kwargs["is_moderation_expert"] = (
|
||||
self.request.user.userprofile.is_moderation_expert
|
||||
)
|
||||
kwargs["is_cloning"] = self.is_cloning
|
||||
kwargs["is_simple_cloning"] = self.is_simple_cloning
|
||||
return kwargs
|
||||
@ -548,6 +551,13 @@ class EventModerateView(
|
||||
template_name = "agenda_culturel/event_form_moderate.html"
|
||||
form_class = EventModerateForm
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs["is_moderation_expert"] = (
|
||||
self.request.user.userprofile.is_moderation_expert
|
||||
)
|
||||
return kwargs
|
||||
|
||||
def get_success_message(self, cleaned_data):
|
||||
txt = (
|
||||
_(" A message has been sent to the person who proposed the event.")
|
||||
|
Loading…
x
Reference in New Issue
Block a user