parent
182d7b85ce
commit
5783b5caa0
@ -16,6 +16,7 @@ from .models import (
|
|||||||
ReferenceLocation,
|
ReferenceLocation,
|
||||||
StaticContent,
|
StaticContent,
|
||||||
Tag,
|
Tag,
|
||||||
|
UserProfile,
|
||||||
)
|
)
|
||||||
|
|
||||||
admin.site.register(Category)
|
admin.site.register(Category)
|
||||||
@ -28,6 +29,7 @@ admin.site.register(Place)
|
|||||||
admin.site.register(Message)
|
admin.site.register(Message)
|
||||||
admin.site.register(ReferenceLocation)
|
admin.site.register(ReferenceLocation)
|
||||||
admin.site.register(Organisation)
|
admin.site.register(Organisation)
|
||||||
|
admin.site.register(UserProfile)
|
||||||
|
|
||||||
|
|
||||||
class URLWidget(DynamicArrayWidget):
|
class URLWidget(DynamicArrayWidget):
|
||||||
|
@ -261,9 +261,24 @@ class CategorisationRuleImportForm(ModelForm):
|
|||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class MultipleChoiceFieldAcceptAll(MultipleChoiceField):
|
||||||
|
def validate(self, value):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class EventForm(GroupFormMixin, ModelForm):
|
class EventForm(GroupFormMixin, ModelForm):
|
||||||
required_css_class = "required"
|
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)
|
old_local_image = CharField(widget=HiddenInput(), required=False)
|
||||||
simple_cloning = CharField(widget=HiddenInput(), required=False)
|
simple_cloning = CharField(widget=HiddenInput(), required=False)
|
||||||
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)
|
is_authenticated = kwargs.pop("is_authenticated", False)
|
||||||
self.cloning = kwargs.pop("is_cloning", False)
|
self.cloning = kwargs.pop("is_cloning", False)
|
||||||
self.simple_cloning = kwargs.pop("is_simple_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)
|
super().__init__(*args, **kwargs)
|
||||||
if not is_authenticated:
|
if not is_authenticated:
|
||||||
del self.fields["status"]
|
del self.fields["status"]
|
||||||
del self.fields["organisers"]
|
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(
|
self.fields["category"].queryset = self.fields["category"].queryset.order_by(
|
||||||
"name"
|
"name"
|
||||||
)
|
)
|
||||||
@ -370,10 +388,14 @@ class EventForm(GroupFormMixin, ModelForm):
|
|||||||
self.fields["category"].group_id = "meta-admin"
|
self.fields["category"].group_id = "meta-admin"
|
||||||
self.fields["tags"].group_id = "meta-admin"
|
self.fields["tags"].group_id = "meta-admin"
|
||||||
self.fields["status"].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:
|
else:
|
||||||
self.add_group("meta", _("Meta information"))
|
self.add_group("meta", _("Meta information"))
|
||||||
self.fields["category"].group_id = "meta"
|
self.fields["category"].group_id = "meta"
|
||||||
self.fields["tags"].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):
|
def is_clone_from_url(self):
|
||||||
return self.cloning
|
return self.cloning
|
||||||
@ -407,9 +429,15 @@ class EventForm(GroupFormMixin, ModelForm):
|
|||||||
|
|
||||||
return end_time
|
return end_time
|
||||||
|
|
||||||
|
def clean_new_tags(self):
|
||||||
|
return list(set(self.cleaned_data.get("new_tags")))
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super().clean()
|
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
|
# when cloning an existing event, we need to copy the local image
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
@ -431,11 +459,6 @@ class EventFormWithContact(SimpleContactForm, EventForm):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MultipleChoiceFieldAcceptAll(MultipleChoiceField):
|
|
||||||
def validate(self, value):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class EventModerateForm(ModelForm):
|
class EventModerateForm(ModelForm):
|
||||||
required_css_class = "required"
|
required_css_class = "required"
|
||||||
|
|
||||||
@ -468,10 +491,13 @@ class EventModerateForm(ModelForm):
|
|||||||
widgets = {"status": RadioSelect}
|
widgets = {"status": RadioSelect}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.is_moderation_expert = kwargs.pop("is_moderation_expert", False)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields["category"].queryset = self.fields["category"].queryset.order_by(
|
self.fields["category"].queryset = self.fields["category"].queryset.order_by(
|
||||||
"name"
|
"name"
|
||||||
)
|
)
|
||||||
|
if not self.is_moderation_expert:
|
||||||
|
del self.fields["new_tags"]
|
||||||
self.fields["category"].empty_label = None
|
self.fields["category"].empty_label = None
|
||||||
self.fields["category"].initial = Category.get_default_category()
|
self.fields["category"].initial = Category.get_default_category()
|
||||||
self.fields["tags"].choices = Tag.get_tag_groups(all=True)
|
self.fields["tags"].choices = Tag.get_tag_groups(all=True)
|
||||||
@ -485,7 +511,7 @@ class EventModerateForm(ModelForm):
|
|||||||
if self.cleaned_data["tags"] is None:
|
if self.cleaned_data["tags"] is None:
|
||||||
self.cleaned_data["tags"] = []
|
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"] += self.cleaned_data.get("new_tags")
|
||||||
|
|
||||||
self.cleaned_data["tags"] = list(set(self.cleaned_data["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 Calendar as icalCal
|
||||||
from icalendar import Event as icalEvent
|
from icalendar import Event as icalEvent
|
||||||
from location_field.models.spatial import LocationField
|
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 .calendar import CalendarDay
|
||||||
from .import_tasks.extractor import Extractor
|
from .import_tasks.extractor import Extractor
|
||||||
@ -50,6 +52,37 @@ from .import_tasks.generic_extractors.fbevent import (
|
|||||||
logger = logging.getLogger(__name__)
|
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):
|
def remove_accents(input_str):
|
||||||
if input_str is None:
|
if input_str is None:
|
||||||
return None
|
return None
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
{% if local %}
|
{% if local %}
|
||||||
<a href="{{ local.get_absolute_url }}" role="button">Voir la version locale {% picto_from_name "eye" %}</a>
|
<a href="{{ local.get_absolute_url }}" role="button">Voir la version locale {% picto_from_name "eye" %}</a>
|
||||||
{% else %}
|
{% 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 %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -472,6 +472,9 @@ class EventUpdateView(
|
|||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs["is_authenticated"] = self.request.user.is_authenticated
|
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_cloning"] = self.is_cloning
|
||||||
kwargs["is_simple_cloning"] = self.is_simple_cloning
|
kwargs["is_simple_cloning"] = self.is_simple_cloning
|
||||||
return kwargs
|
return kwargs
|
||||||
@ -548,6 +551,13 @@ class EventModerateView(
|
|||||||
template_name = "agenda_culturel/event_form_moderate.html"
|
template_name = "agenda_culturel/event_form_moderate.html"
|
||||||
form_class = EventModerateForm
|
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):
|
def get_success_message(self, cleaned_data):
|
||||||
txt = (
|
txt = (
|
||||||
_(" A message has been sent to the person who proposed the event.")
|
_(" A message has been sent to the person who proposed the event.")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user