Files
WYGIWYH/app/apps/common/forms.py
2025-11-09 15:31:50 -03:00

109 lines
3.6 KiB
Python

from apps.common.models import SharedObject
from apps.common.widgets.crispy.submit import NoClassSubmit
from apps.common.widgets.tom_select import TomSelect, TomSelectMultiple
from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Div, Field, Layout, Submit
from django import forms
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
User = get_user_model()
class SharedObjectForm(forms.Form):
"""
Generic form for editing visibility and sharing settings
for models inheriting from SharedObject.
"""
owner = forms.ModelChoiceField(
queryset=User.objects.all(),
required=False,
label=_("Owner"),
widget=TomSelect(clear_button=False),
help_text=_(
"The owner of this object, if empty all users can see, edit and take ownership."
),
)
shared_with_users = forms.ModelMultipleChoiceField(
queryset=User.objects.all(),
required=False,
widget=TomSelectMultiple(clear_button=True),
label=_("Shared with users"),
help_text=_("Select users to share this object with"),
)
visibility = forms.ChoiceField(
choices=SharedObject.Visibility.choices,
required=True,
label=_("Visibility"),
widget=TomSelect(clear_button=False),
help_text=_(
"Private: Only shown for the owner and shared users. Only editable by the owner."
"<br/>"
"Public: Shown for all users. Only editable by the owner."
),
)
class Meta:
fields = ["visibility", "shared_with_users"]
def __init__(self, *args, **kwargs):
# Get the current user to filter available sharing options
self.user = kwargs.pop("user", None)
self.instance = kwargs.pop("instance", None)
super().__init__(*args, **kwargs)
# Pre-populate shared users if instance exists
if self.instance:
self.fields["shared_with_users"].initial = self.instance.shared_with.all()
self.fields["visibility"].initial = self.instance.visibility
self.fields["owner"].initial = self.instance.owner
# Set up crispy form helper
self.helper = FormHelper()
self.helper.form_method = "post"
self.helper.form_tag = False
self.helper.layout = Layout(
Field("owner"),
Field("visibility"),
HTML('<hr class="hr my-3">'),
Field("shared_with_users"),
FormActions(
NoClassSubmit("submit", _("Save"), css_class="btn btn-primary"),
),
)
def clean(self):
cleaned_data = super().clean()
owner = cleaned_data.get("owner")
shared_with_users = cleaned_data.get("shared_with_users", [])
# Raise validation error if owner is in shared_with_users
if owner and owner in shared_with_users:
self.add_error(
"shared_with_users",
ValidationError(
_("You cannot share this item with its owner."),
code="invalid_share",
),
)
return cleaned_data
def save(self):
instance = self.instance
instance.visibility = self.cleaned_data["visibility"]
instance.owner = self.cleaned_data["owner"]
instance.save()
# Clear and set shared_with users
instance.shared_with.set(self.cleaned_data.get("shared_with_users", []))
return instance