Merge pull request #2017 from bookwyrm-social/forms

Moves forms into separate files
This commit is contained in:
Mouse Reeve 2022-03-14 12:21:42 -07:00 committed by GitHub
commit d848b950dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 650 additions and 584 deletions

View file

@ -1,584 +0,0 @@
""" using django model forms """
import datetime
from collections import defaultdict
from urllib.parse import urlparse
from django import forms
from django.forms import ModelForm, PasswordInput, widgets, ChoiceField
from django.forms.widgets import Textarea
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from bookwyrm import models
from bookwyrm.models.fields import ClearableFileInputWithWarning
from bookwyrm.models.user import FeedFilterChoices
class CustomForm(ModelForm):
"""add css classes to the forms"""
def __init__(self, *args, **kwargs):
css_classes = defaultdict(lambda: "")
css_classes["text"] = "input"
css_classes["password"] = "input"
css_classes["email"] = "input"
css_classes["number"] = "input"
css_classes["checkbox"] = "checkbox"
css_classes["textarea"] = "textarea"
# pylint: disable=super-with-arguments
super(CustomForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
if hasattr(visible.field.widget, "input_type"):
input_type = visible.field.widget.input_type
if isinstance(visible.field.widget, Textarea):
input_type = "textarea"
visible.field.widget.attrs["rows"] = 5
visible.field.widget.attrs["class"] = css_classes[input_type]
# pylint: disable=missing-class-docstring
class LoginForm(CustomForm):
class Meta:
model = models.User
fields = ["localname", "password"]
help_texts = {f: None for f in fields}
widgets = {
"password": PasswordInput(),
}
class RegisterForm(CustomForm):
class Meta:
model = models.User
fields = ["localname", "email", "password"]
help_texts = {f: None for f in fields}
widgets = {"password": PasswordInput()}
def clean(self):
"""Check if the username is taken"""
cleaned_data = super().clean()
localname = cleaned_data.get("localname").strip()
if models.User.objects.filter(localname=localname).first():
self.add_error("localname", _("User with this username already exists"))
class RatingForm(CustomForm):
class Meta:
model = models.ReviewRating
fields = ["user", "book", "rating", "privacy"]
class ReviewForm(CustomForm):
class Meta:
model = models.Review
fields = [
"user",
"book",
"name",
"content",
"rating",
"content_warning",
"sensitive",
"privacy",
]
class CommentForm(CustomForm):
class Meta:
model = models.Comment
fields = [
"user",
"book",
"content",
"content_warning",
"sensitive",
"privacy",
"progress",
"progress_mode",
"reading_status",
]
class QuotationForm(CustomForm):
class Meta:
model = models.Quotation
fields = [
"user",
"book",
"quote",
"content",
"content_warning",
"sensitive",
"privacy",
"position",
"position_mode",
]
class ReplyForm(CustomForm):
class Meta:
model = models.Status
fields = [
"user",
"content",
"content_warning",
"sensitive",
"reply_parent",
"privacy",
]
class StatusForm(CustomForm):
class Meta:
model = models.Status
fields = ["user", "content", "content_warning", "sensitive", "privacy"]
class DirectForm(CustomForm):
class Meta:
model = models.Status
fields = ["user", "content", "content_warning", "sensitive", "privacy"]
class EditUserForm(CustomForm):
class Meta:
model = models.User
fields = [
"avatar",
"name",
"email",
"summary",
"show_goal",
"show_suggested_users",
"manually_approves_followers",
"default_post_privacy",
"discoverable",
"hide_follows",
"preferred_timezone",
"preferred_language",
"theme",
]
help_texts = {f: None for f in fields}
widgets = {
"avatar": ClearableFileInputWithWarning(
attrs={"aria-describedby": "desc_avatar"}
),
"name": forms.TextInput(attrs={"aria-describedby": "desc_name"}),
"summary": forms.Textarea(attrs={"aria-describedby": "desc_summary"}),
"email": forms.EmailInput(attrs={"aria-describedby": "desc_email"}),
"discoverable": forms.CheckboxInput(
attrs={"aria-describedby": "desc_discoverable"}
),
}
class LimitedEditUserForm(CustomForm):
class Meta:
model = models.User
fields = [
"avatar",
"name",
"summary",
"manually_approves_followers",
"discoverable",
]
help_texts = {f: None for f in fields}
widgets = {
"avatar": ClearableFileInputWithWarning(
attrs={"aria-describedby": "desc_avatar"}
),
"name": forms.TextInput(attrs={"aria-describedby": "desc_name"}),
"summary": forms.Textarea(attrs={"aria-describedby": "desc_summary"}),
"discoverable": forms.CheckboxInput(
attrs={"aria-describedby": "desc_discoverable"}
),
}
class DeleteUserForm(CustomForm):
class Meta:
model = models.User
fields = ["password"]
class UserGroupForm(CustomForm):
class Meta:
model = models.User
fields = ["groups"]
class FeedStatusTypesForm(CustomForm):
class Meta:
model = models.User
fields = ["feed_status_types"]
help_texts = {f: None for f in fields}
widgets = {
"feed_status_types": widgets.CheckboxSelectMultiple(
choices=FeedFilterChoices,
),
}
class CoverForm(CustomForm):
class Meta:
model = models.Book
fields = ["cover"]
help_texts = {f: None for f in fields}
class LinkDomainForm(CustomForm):
class Meta:
model = models.LinkDomain
fields = ["name"]
class FileLinkForm(CustomForm):
class Meta:
model = models.FileLink
fields = ["url", "filetype", "availability", "book", "added_by"]
def clean(self):
"""make sure the domain isn't blocked or pending"""
cleaned_data = super().clean()
url = cleaned_data.get("url")
filetype = cleaned_data.get("filetype")
book = cleaned_data.get("book")
domain = urlparse(url).netloc
if models.LinkDomain.objects.filter(domain=domain).exists():
status = models.LinkDomain.objects.get(domain=domain).status
if status == "blocked":
# pylint: disable=line-too-long
self.add_error(
"url",
_(
"This domain is blocked. Please contact your administrator if you think this is an error."
),
)
elif models.FileLink.objects.filter(
url=url, book=book, filetype=filetype
).exists():
# pylint: disable=line-too-long
self.add_error(
"url",
_(
"This link with file type has already been added for this book. If it is not visible, the domain is still pending."
),
)
class EditionForm(CustomForm):
class Meta:
model = models.Edition
exclude = [
"remote_id",
"origin_id",
"created_date",
"updated_date",
"edition_rank",
"authors",
"parent_work",
"shelves",
"connector",
"search_vector",
"links",
"file_links",
]
widgets = {
"title": forms.TextInput(attrs={"aria-describedby": "desc_title"}),
"subtitle": forms.TextInput(attrs={"aria-describedby": "desc_subtitle"}),
"description": forms.Textarea(
attrs={"aria-describedby": "desc_description"}
),
"series": forms.TextInput(attrs={"aria-describedby": "desc_series"}),
"series_number": forms.TextInput(
attrs={"aria-describedby": "desc_series_number"}
),
"languages": forms.TextInput(
attrs={"aria-describedby": "desc_languages_help desc_languages"}
),
"subjects": forms.TextInput(
attrs={"aria-describedby": "desc_subjects_help desc_subjects"}
),
"publishers": forms.TextInput(
attrs={"aria-describedby": "desc_publishers_help desc_publishers"}
),
"first_published_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_first_published_date"}
),
"published_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_published_date"}
),
"cover": ClearableFileInputWithWarning(
attrs={"aria-describedby": "desc_cover"}
),
"physical_format": forms.Select(
attrs={"aria-describedby": "desc_physical_format"}
),
"physical_format_detail": forms.TextInput(
attrs={"aria-describedby": "desc_physical_format_detail"}
),
"pages": forms.NumberInput(attrs={"aria-describedby": "desc_pages"}),
"isbn_13": forms.TextInput(attrs={"aria-describedby": "desc_isbn_13"}),
"isbn_10": forms.TextInput(attrs={"aria-describedby": "desc_isbn_10"}),
"openlibrary_key": forms.TextInput(
attrs={"aria-describedby": "desc_openlibrary_key"}
),
"inventaire_id": forms.TextInput(
attrs={"aria-describedby": "desc_inventaire_id"}
),
"oclc_number": forms.TextInput(
attrs={"aria-describedby": "desc_oclc_number"}
),
"ASIN": forms.TextInput(attrs={"aria-describedby": "desc_ASIN"}),
}
class AuthorForm(CustomForm):
class Meta:
model = models.Author
fields = [
"last_edited_by",
"name",
"aliases",
"bio",
"wikipedia_link",
"born",
"died",
"openlibrary_key",
"inventaire_id",
"librarything_key",
"goodreads_key",
"isni",
]
widgets = {
"name": forms.TextInput(attrs={"aria-describedby": "desc_name"}),
"aliases": forms.TextInput(attrs={"aria-describedby": "desc_aliases"}),
"bio": forms.Textarea(attrs={"aria-describedby": "desc_bio"}),
"wikipedia_link": forms.TextInput(
attrs={"aria-describedby": "desc_wikipedia_link"}
),
"born": forms.SelectDateWidget(attrs={"aria-describedby": "desc_born"}),
"died": forms.SelectDateWidget(attrs={"aria-describedby": "desc_died"}),
"oepnlibrary_key": forms.TextInput(
attrs={"aria-describedby": "desc_oepnlibrary_key"}
),
"inventaire_id": forms.TextInput(
attrs={"aria-describedby": "desc_inventaire_id"}
),
"librarything_key": forms.TextInput(
attrs={"aria-describedby": "desc_librarything_key"}
),
"goodreads_key": forms.TextInput(
attrs={"aria-describedby": "desc_goodreads_key"}
),
}
class ImportForm(forms.Form):
csv_file = forms.FileField()
class ExpiryWidget(widgets.Select):
def value_from_datadict(self, data, files, name):
"""human-readable exiration time buckets"""
selected_string = super().value_from_datadict(data, files, name)
if selected_string == "day":
interval = datetime.timedelta(days=1)
elif selected_string == "week":
interval = datetime.timedelta(days=7)
elif selected_string == "month":
interval = datetime.timedelta(days=31) # Close enough?
elif selected_string == "forever":
return None
else:
return selected_string # This will raise
return timezone.now() + interval
class InviteRequestForm(CustomForm):
def clean(self):
"""make sure the email isn't in use by a registered user"""
cleaned_data = super().clean()
email = cleaned_data.get("email")
if email and models.User.objects.filter(email=email).exists():
self.add_error("email", _("A user with this email already exists."))
class Meta:
model = models.InviteRequest
fields = ["email"]
class CreateInviteForm(CustomForm):
class Meta:
model = models.SiteInvite
exclude = ["code", "user", "times_used", "invitees"]
widgets = {
"expiry": ExpiryWidget(
choices=[
("day", _("One Day")),
("week", _("One Week")),
("month", _("One Month")),
("forever", _("Does Not Expire")),
]
),
"use_limit": widgets.Select(
choices=[(i, _(f"{i} uses")) for i in [1, 5, 10, 25, 50, 100]]
+ [(None, _("Unlimited"))]
),
}
class ShelfForm(CustomForm):
class Meta:
model = models.Shelf
fields = ["user", "name", "privacy", "description"]
class GoalForm(CustomForm):
class Meta:
model = models.AnnualGoal
fields = ["user", "year", "goal", "privacy"]
class SiteForm(CustomForm):
class Meta:
model = models.SiteSettings
exclude = ["admin_code", "install_mode"]
widgets = {
"instance_short_description": forms.TextInput(
attrs={"aria-describedby": "desc_instance_short_description"}
),
"require_confirm_email": forms.CheckboxInput(
attrs={"aria-describedby": "desc_require_confirm_email"}
),
"invite_request_text": forms.Textarea(
attrs={"aria-describedby": "desc_invite_request_text"}
),
}
class SiteThemeForm(CustomForm):
class Meta:
model = models.SiteSettings
fields = ["default_theme"]
class ThemeForm(CustomForm):
class Meta:
model = models.Theme
fields = ["name", "path"]
widgets = {
"name": forms.TextInput(attrs={"aria-describedby": "desc_name"}),
"path": forms.TextInput(
attrs={
"aria-describedby": "desc_path",
"placeholder": "css/themes/theme-name.scss",
}
),
}
class AnnouncementForm(CustomForm):
class Meta:
model = models.Announcement
exclude = ["remote_id"]
widgets = {
"preview": forms.TextInput(attrs={"aria-describedby": "desc_preview"}),
"content": forms.Textarea(attrs={"aria-describedby": "desc_content"}),
"event_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_event_date"}
),
"start_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_start_date"}
),
"end_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_end_date"}
),
"active": forms.CheckboxInput(attrs={"aria-describedby": "desc_active"}),
}
class ListForm(CustomForm):
class Meta:
model = models.List
fields = ["user", "name", "description", "curation", "privacy", "group"]
class ListItemForm(CustomForm):
class Meta:
model = models.ListItem
fields = ["user", "book", "book_list", "notes"]
class GroupForm(CustomForm):
class Meta:
model = models.Group
fields = ["user", "privacy", "name", "description"]
class ReportForm(CustomForm):
class Meta:
model = models.Report
fields = ["user", "reporter", "status", "links", "note"]
class EmailBlocklistForm(CustomForm):
class Meta:
model = models.EmailBlocklist
fields = ["domain"]
widgets = {
"avatar": forms.TextInput(attrs={"aria-describedby": "desc_domain"}),
}
class IPBlocklistForm(CustomForm):
class Meta:
model = models.IPBlocklist
fields = ["address"]
class ServerForm(CustomForm):
class Meta:
model = models.FederatedServer
exclude = ["remote_id"]
class SortListForm(forms.Form):
sort_by = ChoiceField(
choices=(
("order", _("List Order")),
("title", _("Book Title")),
("rating", _("Rating")),
),
label=_("Sort By"),
)
direction = ChoiceField(
choices=(
("ascending", _("Ascending")),
("descending", _("Descending")),
),
)
class ReadThroughForm(CustomForm):
def clean(self):
"""make sure the email isn't in use by a registered user"""
cleaned_data = super().clean()
start_date = cleaned_data.get("start_date")
finish_date = cleaned_data.get("finish_date")
if start_date and finish_date and start_date > finish_date:
self.add_error(
"finish_date", _("Reading finish date cannot be before start date.")
)
class Meta:
model = models.ReadThrough
fields = ["user", "book", "start_date", "finish_date"]
class AutoModRuleForm(CustomForm):
class Meta:
model = models.AutoMod
fields = ["string_match", "flag_users", "flag_statuses", "created_by"]

View file

@ -0,0 +1,12 @@
""" make forms available to the app """
# site admin
from .admin import *
from .author import *
from .books import *
from .edit_user import *
from .forms import *
from .groups import *
from .landing import *
from .links import *
from .lists import *
from .status import *

129
bookwyrm/forms/admin.py Normal file
View file

@ -0,0 +1,129 @@
""" using django model forms """
import datetime
from django import forms
from django.forms import widgets
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from bookwyrm import models
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class ExpiryWidget(widgets.Select):
def value_from_datadict(self, data, files, name):
"""human-readable exiration time buckets"""
selected_string = super().value_from_datadict(data, files, name)
if selected_string == "day":
interval = datetime.timedelta(days=1)
elif selected_string == "week":
interval = datetime.timedelta(days=7)
elif selected_string == "month":
interval = datetime.timedelta(days=31) # Close enough?
elif selected_string == "forever":
return None
else:
return selected_string # This will raise
return timezone.now() + interval
class CreateInviteForm(CustomForm):
class Meta:
model = models.SiteInvite
exclude = ["code", "user", "times_used", "invitees"]
widgets = {
"expiry": ExpiryWidget(
choices=[
("day", _("One Day")),
("week", _("One Week")),
("month", _("One Month")),
("forever", _("Does Not Expire")),
]
),
"use_limit": widgets.Select(
choices=[(i, _(f"{i} uses")) for i in [1, 5, 10, 25, 50, 100]]
+ [(None, _("Unlimited"))]
),
}
class SiteForm(CustomForm):
class Meta:
model = models.SiteSettings
exclude = ["admin_code", "install_mode"]
widgets = {
"instance_short_description": forms.TextInput(
attrs={"aria-describedby": "desc_instance_short_description"}
),
"require_confirm_email": forms.CheckboxInput(
attrs={"aria-describedby": "desc_require_confirm_email"}
),
"invite_request_text": forms.Textarea(
attrs={"aria-describedby": "desc_invite_request_text"}
),
}
class ThemeForm(CustomForm):
class Meta:
model = models.Theme
fields = ["name", "path"]
widgets = {
"name": forms.TextInput(attrs={"aria-describedby": "desc_name"}),
"path": forms.TextInput(
attrs={
"aria-describedby": "desc_path",
"placeholder": "css/themes/theme-name.scss",
}
),
}
class AnnouncementForm(CustomForm):
class Meta:
model = models.Announcement
exclude = ["remote_id"]
widgets = {
"preview": forms.TextInput(attrs={"aria-describedby": "desc_preview"}),
"content": forms.Textarea(attrs={"aria-describedby": "desc_content"}),
"event_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_event_date"}
),
"start_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_start_date"}
),
"end_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_end_date"}
),
"active": forms.CheckboxInput(attrs={"aria-describedby": "desc_active"}),
}
class EmailBlocklistForm(CustomForm):
class Meta:
model = models.EmailBlocklist
fields = ["domain"]
widgets = {
"avatar": forms.TextInput(attrs={"aria-describedby": "desc_domain"}),
}
class IPBlocklistForm(CustomForm):
class Meta:
model = models.IPBlocklist
fields = ["address"]
class ServerForm(CustomForm):
class Meta:
model = models.FederatedServer
exclude = ["remote_id"]
class AutoModRuleForm(CustomForm):
class Meta:
model = models.AutoMod
fields = ["string_match", "flag_users", "flag_statuses", "created_by"]

47
bookwyrm/forms/author.py Normal file
View file

@ -0,0 +1,47 @@
""" using django model forms """
from django import forms
from bookwyrm import models
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class AuthorForm(CustomForm):
class Meta:
model = models.Author
fields = [
"last_edited_by",
"name",
"aliases",
"bio",
"wikipedia_link",
"born",
"died",
"openlibrary_key",
"inventaire_id",
"librarything_key",
"goodreads_key",
"isni",
]
widgets = {
"name": forms.TextInput(attrs={"aria-describedby": "desc_name"}),
"aliases": forms.TextInput(attrs={"aria-describedby": "desc_aliases"}),
"bio": forms.Textarea(attrs={"aria-describedby": "desc_bio"}),
"wikipedia_link": forms.TextInput(
attrs={"aria-describedby": "desc_wikipedia_link"}
),
"born": forms.SelectDateWidget(attrs={"aria-describedby": "desc_born"}),
"died": forms.SelectDateWidget(attrs={"aria-describedby": "desc_died"}),
"oepnlibrary_key": forms.TextInput(
attrs={"aria-describedby": "desc_oepnlibrary_key"}
),
"inventaire_id": forms.TextInput(
attrs={"aria-describedby": "desc_inventaire_id"}
),
"librarything_key": forms.TextInput(
attrs={"aria-describedby": "desc_librarything_key"}
),
"goodreads_key": forms.TextInput(
attrs={"aria-describedby": "desc_goodreads_key"}
),
}

81
bookwyrm/forms/books.py Normal file
View file

@ -0,0 +1,81 @@
""" using django model forms """
from django import forms
from bookwyrm import models
from bookwyrm.models.fields import ClearableFileInputWithWarning
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class CoverForm(CustomForm):
class Meta:
model = models.Book
fields = ["cover"]
help_texts = {f: None for f in fields}
class EditionForm(CustomForm):
class Meta:
model = models.Edition
exclude = [
"remote_id",
"origin_id",
"created_date",
"updated_date",
"edition_rank",
"authors",
"parent_work",
"shelves",
"connector",
"search_vector",
"links",
"file_links",
]
widgets = {
"title": forms.TextInput(attrs={"aria-describedby": "desc_title"}),
"subtitle": forms.TextInput(attrs={"aria-describedby": "desc_subtitle"}),
"description": forms.Textarea(
attrs={"aria-describedby": "desc_description"}
),
"series": forms.TextInput(attrs={"aria-describedby": "desc_series"}),
"series_number": forms.TextInput(
attrs={"aria-describedby": "desc_series_number"}
),
"languages": forms.TextInput(
attrs={"aria-describedby": "desc_languages_help desc_languages"}
),
"subjects": forms.TextInput(
attrs={"aria-describedby": "desc_subjects_help desc_subjects"}
),
"publishers": forms.TextInput(
attrs={"aria-describedby": "desc_publishers_help desc_publishers"}
),
"first_published_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_first_published_date"}
),
"published_date": forms.SelectDateWidget(
attrs={"aria-describedby": "desc_published_date"}
),
"cover": ClearableFileInputWithWarning(
attrs={"aria-describedby": "desc_cover"}
),
"physical_format": forms.Select(
attrs={"aria-describedby": "desc_physical_format"}
),
"physical_format_detail": forms.TextInput(
attrs={"aria-describedby": "desc_physical_format_detail"}
),
"pages": forms.NumberInput(attrs={"aria-describedby": "desc_pages"}),
"isbn_13": forms.TextInput(attrs={"aria-describedby": "desc_isbn_13"}),
"isbn_10": forms.TextInput(attrs={"aria-describedby": "desc_isbn_10"}),
"openlibrary_key": forms.TextInput(
attrs={"aria-describedby": "desc_openlibrary_key"}
),
"inventaire_id": forms.TextInput(
attrs={"aria-describedby": "desc_inventaire_id"}
),
"oclc_number": forms.TextInput(
attrs={"aria-describedby": "desc_oclc_number"}
),
"ASIN": forms.TextInput(attrs={"aria-describedby": "desc_ASIN"}),
}

View file

@ -0,0 +1,26 @@
""" Overrides django's default form class """
from collections import defaultdict
from django.forms import ModelForm
from django.forms.widgets import Textarea
class CustomForm(ModelForm):
"""add css classes to the forms"""
def __init__(self, *args, **kwargs):
css_classes = defaultdict(lambda: "")
css_classes["text"] = "input"
css_classes["password"] = "input"
css_classes["email"] = "input"
css_classes["number"] = "input"
css_classes["checkbox"] = "checkbox"
css_classes["textarea"] = "textarea"
# pylint: disable=super-with-arguments
super(CustomForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
if hasattr(visible.field.widget, "input_type"):
input_type = visible.field.widget.input_type
if isinstance(visible.field.widget, Textarea):
input_type = "textarea"
visible.field.widget.attrs["rows"] = 5
visible.field.widget.attrs["class"] = css_classes[input_type]

View file

@ -0,0 +1,68 @@
""" using django model forms """
from django import forms
from bookwyrm import models
from bookwyrm.models.fields import ClearableFileInputWithWarning
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class EditUserForm(CustomForm):
class Meta:
model = models.User
fields = [
"avatar",
"name",
"email",
"summary",
"show_goal",
"show_suggested_users",
"manually_approves_followers",
"default_post_privacy",
"discoverable",
"hide_follows",
"preferred_timezone",
"preferred_language",
"theme",
]
help_texts = {f: None for f in fields}
widgets = {
"avatar": ClearableFileInputWithWarning(
attrs={"aria-describedby": "desc_avatar"}
),
"name": forms.TextInput(attrs={"aria-describedby": "desc_name"}),
"summary": forms.Textarea(attrs={"aria-describedby": "desc_summary"}),
"email": forms.EmailInput(attrs={"aria-describedby": "desc_email"}),
"discoverable": forms.CheckboxInput(
attrs={"aria-describedby": "desc_discoverable"}
),
}
class LimitedEditUserForm(CustomForm):
class Meta:
model = models.User
fields = [
"avatar",
"name",
"summary",
"manually_approves_followers",
"discoverable",
]
help_texts = {f: None for f in fields}
widgets = {
"avatar": ClearableFileInputWithWarning(
attrs={"aria-describedby": "desc_avatar"}
),
"name": forms.TextInput(attrs={"aria-describedby": "desc_name"}),
"summary": forms.Textarea(attrs={"aria-describedby": "desc_summary"}),
"discoverable": forms.CheckboxInput(
attrs={"aria-describedby": "desc_discoverable"}
),
}
class DeleteUserForm(CustomForm):
class Meta:
model = models.User
fields = ["password"]

59
bookwyrm/forms/forms.py Normal file
View file

@ -0,0 +1,59 @@
""" using django model forms """
from django import forms
from django.forms import widgets
from django.utils.translation import gettext_lazy as _
from bookwyrm import models
from bookwyrm.models.user import FeedFilterChoices
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class FeedStatusTypesForm(CustomForm):
class Meta:
model = models.User
fields = ["feed_status_types"]
help_texts = {f: None for f in fields}
widgets = {
"feed_status_types": widgets.CheckboxSelectMultiple(
choices=FeedFilterChoices,
),
}
class ImportForm(forms.Form):
csv_file = forms.FileField()
class ShelfForm(CustomForm):
class Meta:
model = models.Shelf
fields = ["user", "name", "privacy", "description"]
class GoalForm(CustomForm):
class Meta:
model = models.AnnualGoal
fields = ["user", "year", "goal", "privacy"]
class ReportForm(CustomForm):
class Meta:
model = models.Report
fields = ["user", "reporter", "status", "links", "note"]
class ReadThroughForm(CustomForm):
def clean(self):
"""make sure the email isn't in use by a registered user"""
cleaned_data = super().clean()
start_date = cleaned_data.get("start_date")
finish_date = cleaned_data.get("finish_date")
if start_date and finish_date and start_date > finish_date:
self.add_error(
"finish_date", _("Reading finish date cannot be before start date.")
)
class Meta:
model = models.ReadThrough
fields = ["user", "book", "start_date", "finish_date"]

16
bookwyrm/forms/groups.py Normal file
View file

@ -0,0 +1,16 @@
""" using django model forms """
from bookwyrm import models
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class UserGroupForm(CustomForm):
class Meta:
model = models.User
fields = ["groups"]
class GroupForm(CustomForm):
class Meta:
model = models.Group
fields = ["user", "privacy", "name", "description"]

45
bookwyrm/forms/landing.py Normal file
View file

@ -0,0 +1,45 @@
""" Forms for the landing pages """
from django.forms import PasswordInput
from django.utils.translation import gettext_lazy as _
from bookwyrm import models
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class LoginForm(CustomForm):
class Meta:
model = models.User
fields = ["localname", "password"]
help_texts = {f: None for f in fields}
widgets = {
"password": PasswordInput(),
}
class RegisterForm(CustomForm):
class Meta:
model = models.User
fields = ["localname", "email", "password"]
help_texts = {f: None for f in fields}
widgets = {"password": PasswordInput()}
def clean(self):
"""Check if the username is taken"""
cleaned_data = super().clean()
localname = cleaned_data.get("localname").strip()
if models.User.objects.filter(localname=localname).first():
self.add_error("localname", _("User with this username already exists"))
class InviteRequestForm(CustomForm):
def clean(self):
"""make sure the email isn't in use by a registered user"""
cleaned_data = super().clean()
email = cleaned_data.get("email")
if email and models.User.objects.filter(email=email).exists():
self.add_error("email", _("A user with this email already exists."))
class Meta:
model = models.InviteRequest
fields = ["email"]

48
bookwyrm/forms/links.py Normal file
View file

@ -0,0 +1,48 @@
""" using django model forms """
from urllib.parse import urlparse
from django.utils.translation import gettext_lazy as _
from bookwyrm import models
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class LinkDomainForm(CustomForm):
class Meta:
model = models.LinkDomain
fields = ["name"]
class FileLinkForm(CustomForm):
class Meta:
model = models.FileLink
fields = ["url", "filetype", "availability", "book", "added_by"]
def clean(self):
"""make sure the domain isn't blocked or pending"""
cleaned_data = super().clean()
url = cleaned_data.get("url")
filetype = cleaned_data.get("filetype")
book = cleaned_data.get("book")
domain = urlparse(url).netloc
if models.LinkDomain.objects.filter(domain=domain).exists():
status = models.LinkDomain.objects.get(domain=domain).status
if status == "blocked":
# pylint: disable=line-too-long
self.add_error(
"url",
_(
"This domain is blocked. Please contact your administrator if you think this is an error."
),
)
elif models.FileLink.objects.filter(
url=url, book=book, filetype=filetype
).exists():
# pylint: disable=line-too-long
self.add_error(
"url",
_(
"This link with file type has already been added for this book. If it is not visible, the domain is still pending."
),
)

37
bookwyrm/forms/lists.py Normal file
View file

@ -0,0 +1,37 @@
""" using django model forms """
from django import forms
from django.forms import ChoiceField
from django.utils.translation import gettext_lazy as _
from bookwyrm import models
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class ListForm(CustomForm):
class Meta:
model = models.List
fields = ["user", "name", "description", "curation", "privacy", "group"]
class ListItemForm(CustomForm):
class Meta:
model = models.ListItem
fields = ["user", "book", "book_list", "notes"]
class SortListForm(forms.Form):
sort_by = ChoiceField(
choices=(
("order", _("List Order")),
("title", _("Book Title")),
("rating", _("Rating")),
),
label=_("Sort By"),
)
direction = ChoiceField(
choices=(
("ascending", _("Ascending")),
("descending", _("Descending")),
),
)

82
bookwyrm/forms/status.py Normal file
View file

@ -0,0 +1,82 @@
""" using django model forms """
from bookwyrm import models
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class RatingForm(CustomForm):
class Meta:
model = models.ReviewRating
fields = ["user", "book", "rating", "privacy"]
class ReviewForm(CustomForm):
class Meta:
model = models.Review
fields = [
"user",
"book",
"name",
"content",
"rating",
"content_warning",
"sensitive",
"privacy",
]
class CommentForm(CustomForm):
class Meta:
model = models.Comment
fields = [
"user",
"book",
"content",
"content_warning",
"sensitive",
"privacy",
"progress",
"progress_mode",
"reading_status",
]
class QuotationForm(CustomForm):
class Meta:
model = models.Quotation
fields = [
"user",
"book",
"quote",
"content",
"content_warning",
"sensitive",
"privacy",
"position",
"position_mode",
]
class ReplyForm(CustomForm):
class Meta:
model = models.Status
fields = [
"user",
"content",
"content_warning",
"sensitive",
"reply_parent",
"privacy",
]
class StatusForm(CustomForm):
class Meta:
model = models.Status
fields = ["user", "content", "content_warning", "sensitive", "privacy"]
class DirectForm(CustomForm):
class Meta:
model = models.Status
fields = ["user", "content", "content_warning", "sensitive", "privacy"]