extract album creation form into its own fragment

This commit is contained in:
imperosol 2025-03-29 18:19:05 +01:00
parent d821dfa180
commit 41d33f3e9e
6 changed files with 111 additions and 122 deletions

View File

@ -1,6 +1,7 @@
from typing import Any from typing import Any
from django import forms from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from core.models import User from core.models import User
@ -11,55 +12,28 @@ from sas.models import Album, Picture, PictureModerationRequest
from sas.widgets.ajax_select import AutoCompleteSelectAlbum from sas.widgets.ajax_select import AutoCompleteSelectAlbum
class SASForm(forms.Form): class AlbumCreateForm(forms.ModelForm):
album_name = forms.CharField( class Meta:
label=_("Add a new album"), max_length=Album.NAME_MAX_LENGTH, required=False model = Album
) fields = ["name", "parent"]
images = MultipleImageField( labels = {"name": _("Add a new album")}
label=_("Upload images"), widgets = {"parent": forms.HiddenInput}
required=False,
)
def process(self, parent, owner, files, *, automodere=False): def __init__(self, *args, owner: User, **kwargs):
try: super().__init__(*args, **kwargs)
if self.cleaned_data["album_name"] != "": self.instance.owner = owner
album = Album( if owner.has_perm("sas.moderate_sasfile"):
parent=parent, self.instance.is_moderated = True
name=self.cleaned_data["album_name"], self.instance.moderator = owner
owner=owner,
is_moderated=automodere, def clean(self):
) if not self.instance.owner.can_edit(self.instance.parent):
album.clean() raise ValidationError(_("You do not have the permission to do that"))
album.save() return super().clean()
except Exception as e:
self.add_error(
None, class PictureUploadForm(forms.Form):
_("Error creating album %(album)s: %(msg)s") images = MultipleImageField(label=_("Upload images"), required=False)
% {"album": self.cleaned_data["album_name"], "msg": repr(e)},
)
for f in files:
new_file = Picture(
parent=parent,
name=f.name,
file=f,
owner=owner,
mime_type=f.content_type,
size=f.size,
is_folder=False,
is_moderated=automodere,
)
if automodere:
new_file.moderator = owner
try:
new_file.clean()
new_file.generate_thumbnails()
new_file.save()
except Exception as e:
self.add_error(
None,
_("Error uploading file %(file_name)s: %(msg)s")
% {"file_name": f, "msg": repr(e)},
)
class PictureEditForm(forms.ModelForm): class PictureEditForm(forms.ModelForm):

View File

@ -110,13 +110,28 @@
{% if is_sas_admin %} {% if is_sas_admin %}
</form> </form>
<form class="add-files" id="upload_form" action="" method="post" enctype="multipart/form-data"> {{ album_create_fragment }}
<form
class="add-files"
id="upload_form"
x-data="pictureUpload({{ album.id }})"
@submit.prevent="sendPictures()"
>
{% csrf_token %} {% csrf_token %}
<div class="inputs"> <div class="inputs">
{{ form.as_p() }} <p>
<label for="{{ upload_form.images.id_for_label }}">{{ upload_form.images.label }} :</label>
{{ upload_form.images|add_attr("x-ref=pictures") }}
<span class="helptext">{{ upload_form.images.help_text }}</span>
</p>
<input type="submit" value="{% trans %}Upload{% endtrans %}" /> <input type="submit" value="{% trans %}Upload{% endtrans %}" />
<progress x-ref="progress" x-show="sending"></progress>
</div> </div>
<ul class="errorlist">
<template x-for="error in errors">
<li class="error" x-text="error"></li>
</template>
</ul>
</form> </form>
{% endif %} {% endif %}

View File

@ -0,0 +1,18 @@
<form
class="add-files"
hx-post="{{ url("sas:album_create") }}"
hx-disabled-elt="find input[type='submit']"
hx-swap="outerHTML"
>
{% csrf_token %}
<div class="inputs">
<div>
<label for="{{ form.name.id_for_label }}">{{ form.name.label }}</label>
{{ form.name }}
</div>
{{ form.parent }}
<input type="submit" value="{% trans %}Create{% endtrans %}" />
</div>
{{ form.non_field_errors() }}
{{ form.name.errors }}
</form>

View File

@ -61,23 +61,8 @@
{% if is_sas_admin %} {% if is_sas_admin %}
</form> </form>
<br> <br>
{{ album_create_fragment }}
<form class="add-files" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="inputs">
<div>
<label for="{{ form.album_name.name }}">{{ form.album_name.label }}</label>
{{ form.album_name }}
</div>
<input type="submit" value="{% trans %}Create{% endtrans %}" />
</div>
{{ form.non_field_errors() }}
{{ form.album_name.errors }}
</form>
{% endif %} {% endif %}
{% endif %} {% endif %}
</main> </main>

View File

@ -16,6 +16,7 @@
from django.urls import path from django.urls import path
from sas.views import ( from sas.views import (
AlbumCreateFragment,
AlbumEditView, AlbumEditView,
AlbumUploadView, AlbumUploadView,
AlbumView, AlbumView,
@ -59,4 +60,5 @@ urlpatterns = [
path( path(
"user/<int:user_id>/pictures/", UserPicturesView.as_view(), name="user_pictures" "user/<int:user_id>/pictures/", UserPicturesView.as_view(), name="user_pictures"
), ),
path("fragment/album-create", AlbumCreateFragment.as_view(), name="album_create"),
] ]

View File

@ -36,28 +36,40 @@ from sas.forms import (
from sas.models import Album, Picture from sas.models import Album, Picture
class SASMainView(FormView): class AlbumCreateFragment(FragmentMixin, CreateView):
form_class = SASForm model = Album
template_name = "sas/main.jinja" form_class = AlbumCreateForm
success_url = reverse_lazy("sas:main") template_name = "sas/fragments/album_create_form.jinja"
reload_on_redirect = True
def post(self, request, *args, **kwargs): def get_form_kwargs(self):
self.form = self.get_form() return super().get_form_kwargs() | {"owner": self.request.user}
parent = SithFile.objects.filter(id=settings.SITH_SAS_ROOT_DIR_ID).first()
files = request.FILES.getlist("images") def render_fragment(
root = User.objects.filter(username="root").first() self, request, owner: User | None = None, **kwargs
if request.user.is_authenticated and request.user.is_in_group( ) -> SafeString:
pk=settings.SITH_GROUP_SAS_ADMIN_ID self.object = None
): self.owner = owner or self.request.user
if self.form.is_valid(): return super().render_fragment(request, **kwargs)
self.form.process(
parent=parent, owner=root, files=files, automodere=True def get_success_url(self):
) parent = self.object.parent
if self.form.is_valid(): parent.__class__ = Album
return super().form_valid(self.form) return parent.get_absolute_url()
else:
self.form.add_error(None, _("You do not have the permission to do that"))
return self.form_invalid(self.form) class SASMainView(UseFragmentsMixin, TemplateView):
template_name = "sas/main.jinja"
def get_fragments(self) -> dict[str, FragmentRenderer]:
form_init = {"parent": SithFile.objects.get(id=settings.SITH_SAS_ROOT_DIR_ID)}
return {
"album_create_fragment": AlbumCreateFragment.as_fragment(initial=form_init)
}
def get_fragment_data(self) -> dict[str, dict[str, Any]]:
root_user = User.objects.get(pk=settings.SITH_ROOT_USER_ID)
return {"album_create_fragment": {"owner": root_user}}
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
@ -130,62 +142,45 @@ class AlbumUploadView(CanViewMixin, DetailView, FormMixin):
return HttpResponse(str(self.form.errors), status=200) return HttpResponse(str(self.form.errors), status=200)
return HttpResponse(str(self.form.errors), status=500) return HttpResponse(str(self.form.errors), status=500)
class AlbumView(CanViewMixin, UseFragmentsMixin, DetailView):
class AlbumView(CanViewMixin, DetailView, FormMixin):
model = Album model = Album
form_class = SASForm
pk_url_kwarg = "album_id" pk_url_kwarg = "album_id"
template_name = "sas/album.jinja" template_name = "sas/album.jinja"
def get_fragments(self) -> dict[str, FragmentRenderer]:
return {
"album_create_fragment": AlbumCreateFragment.as_fragment(
initial={"parent": self.object}
)
}
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
try: try:
self.asked_page = int(request.GET.get("page", 1)) self.asked_page = int(request.GET.get("page", 1))
except ValueError as e: except ValueError as e:
raise Http404 from e raise Http404 from e
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
self.form = self.get_form()
if "clipboard" not in request.session: if "clipboard" not in request.session:
request.session["clipboard"] = [] request.session["clipboard"] = []
return super().get(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
if not self.object.file: if not self.object.file:
self.object.generate_thumbnail() self.object.generate_thumbnail()
self.form = self.get_form()
if "clipboard" not in request.session:
request.session["clipboard"] = []
if request.user.can_edit(self.object): # Handle the copy-paste functions if request.user.can_edit(self.object): # Handle the copy-paste functions
FileView.handle_clipboard(request, self.object) FileView.handle_clipboard(request, self.object)
parent = SithFile.objects.filter(id=self.object.id).first() return HttpResponseRedirect(self.request.path)
files = request.FILES.getlist("images")
if request.user.is_authenticated and request.user.is_subscribed:
if self.form.is_valid():
self.form.process(
parent=parent,
owner=request.user,
files=files,
automodere=request.user.is_in_group(
pk=settings.SITH_GROUP_SAS_ADMIN_ID
),
)
if self.form.is_valid():
return super().form_valid(self.form)
else:
self.form.add_error(None, _("You do not have the permission to do that"))
return self.form_invalid(self.form)
def get_success_url(self): def get_fragment_data(self) -> dict[str, dict[str, Any]]:
return reverse("sas:album", kwargs={"album_id": self.object.id}) return {"album_create_fragment": {"owner": self.request.user}}
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs) kwargs = super().get_context_data(**kwargs)
kwargs["form"] = self.form if ids := self.request.session.get("clipboard", None):
kwargs["clipboard"] = SithFile.objects.filter( kwargs["clipboard"] = SithFile.objects.filter(id__in=ids)
id__in=self.request.session["clipboard"] kwargs["upload_form"] = PictureUploadForm()
) # if True, the albums will be fetched with a request to the API
# if False, the section won't be displayed at all
kwargs["show_albums"] = ( kwargs["show_albums"] = (
Album.objects.viewable_by(self.request.user) Album.objects.viewable_by(self.request.user)
.filter(parent_id=self.object.id) .filter(parent_id=self.object.id)