forked from mirrors/bookwyrm
Request invite flow
This commit is contained in:
parent
4d07cb1eb5
commit
d15396eb26
8 changed files with 81 additions and 16 deletions
|
@ -3,6 +3,7 @@ import datetime
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms import ModelForm, PasswordInput, widgets
|
from django.forms import ModelForm, PasswordInput, widgets
|
||||||
from django.forms.widgets import Textarea
|
from django.forms.widgets import Textarea
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
@ -203,6 +204,13 @@ class ExpiryWidget(widgets.Select):
|
||||||
|
|
||||||
|
|
||||||
class InviteRequestForm(CustomForm):
|
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:
|
class Meta:
|
||||||
model = models.InviteRequest
|
model = models.InviteRequest
|
||||||
fields = ["email"]
|
fields = ["email"]
|
||||||
|
|
|
@ -45,9 +45,33 @@
|
||||||
<form name="register" method="post" action="/register">
|
<form name="register" method="post" action="/register">
|
||||||
{% include 'snippets/register_form.html' %}
|
{% include 'snippets/register_form.html' %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
<h2 class="title">{% trans "This instance is closed" %}</h2>
|
<h2 class="title">{% trans "This instance is closed" %}</h2>
|
||||||
<p>{{ site.registration_closed_text | safe}}</p>
|
<p>{{ site.registration_closed_text | safe}}</p>
|
||||||
|
|
||||||
|
{% if site.allow_invite_requests %}
|
||||||
|
{% if request_received %}
|
||||||
|
<p>
|
||||||
|
{% trans "Thank you! Your request has been received." %}
|
||||||
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<h3>{% trans "Request an Invitation" %}</h3>
|
||||||
|
<form name="invite-request" action="{% url 'invite-request' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="block">
|
||||||
|
<label for="id_request_email" class="label">{% trans "Email address:" %}</label>
|
||||||
|
<input type="email" name="email" maxlength="255" class="input" required="" id="id_request_email">
|
||||||
|
{% for error in request_form.email.errors %}
|
||||||
|
<p class="help is-danger">{{ error | escape }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button is-link">{% trans "Submit" %}</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -79,6 +79,10 @@
|
||||||
<label class="label" for="id_allow_registration">{% trans "Allow registration:" %}
|
<label class="label" for="id_allow_registration">{% trans "Allow registration:" %}
|
||||||
{{ site_form.allow_registration }}
|
{{ site_form.allow_registration }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<label class="label" for="id_allow_invite_requests">{% trans "Allow invite requests:" %}
|
||||||
|
{{ site_form.allow_invite_requests }}
|
||||||
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<label class="label" for="id_registration_closed_text">{% trans "Registration closed text:" %}</label>
|
<label class="label" for="id_registration_closed_text">{% trans "Registration closed text:" %}</label>
|
||||||
{{ site_form.registration_closed_text }}
|
{{ site_form.registration_closed_text }}
|
||||||
|
|
|
@ -54,6 +54,9 @@ urlpatterns = [
|
||||||
re_path(
|
re_path(
|
||||||
r"^settings/invites/?$", views.ManageInvites.as_view(), name="settings-invites"
|
r"^settings/invites/?$", views.ManageInvites.as_view(), name="settings-invites"
|
||||||
),
|
),
|
||||||
|
re_path(
|
||||||
|
r"^invite-request/?$", views.InviteRequest.as_view(), name="invite-request"
|
||||||
|
),
|
||||||
re_path(r"^invite/(?P<code>[A-Za-z0-9]+)/?$", views.Invite.as_view()),
|
re_path(r"^invite/(?P<code>[A-Za-z0-9]+)/?$", views.Invite.as_view()),
|
||||||
# moderation
|
# moderation
|
||||||
re_path(r"^settings/reports/?$", views.Reports.as_view(), name="settings-reports"),
|
re_path(r"^settings/reports/?$", views.Reports.as_view(), name="settings-reports"),
|
||||||
|
|
|
@ -13,7 +13,7 @@ from .goal import Goal, hide_goal
|
||||||
from .import_data import Import, ImportStatus
|
from .import_data import Import, ImportStatus
|
||||||
from .inbox import Inbox
|
from .inbox import Inbox
|
||||||
from .interaction import Favorite, Unfavorite, Boost, Unboost
|
from .interaction import Favorite, Unfavorite, Boost, Unboost
|
||||||
from .invite import ManageInvites, Invite
|
from .invite import ManageInvites, Invite, InviteRequest
|
||||||
from .isbn import Isbn
|
from .isbn import Isbn
|
||||||
from .landing import About, Home, Discover
|
from .landing import About, Home, Discover
|
||||||
from .list import Lists, List, Curate, UserLists
|
from .list import Lists, List, Curate, UserLists
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import re
|
import re
|
||||||
from requests import HTTPError
|
from requests import HTTPError
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
from django.db.models import Q
|
from django.db.models import Max, Q
|
||||||
|
|
||||||
from bookwyrm import activitypub, models
|
from bookwyrm import activitypub, models
|
||||||
from bookwyrm.connectors import ConnectorException, get_data
|
from bookwyrm.connectors import ConnectorException, get_data
|
||||||
|
@ -216,3 +216,20 @@ def is_blocked(viewer, user):
|
||||||
if viewer.is_authenticated and viewer in user.blocks.all():
|
if viewer.is_authenticated and viewer in user.blocks.all():
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_discover_books():
|
||||||
|
""" list of books for the discover page """
|
||||||
|
return list(
|
||||||
|
set(
|
||||||
|
models.Edition.objects.filter(
|
||||||
|
review__published_date__isnull=False,
|
||||||
|
review__deleted=False,
|
||||||
|
review__user__local=True,
|
||||||
|
review__privacy__in=["public", "unlisted"],
|
||||||
|
)
|
||||||
|
.exclude(cover__exact="")
|
||||||
|
.annotate(Max("review__published_date"))
|
||||||
|
.order_by("-review__published_date__max")[:6]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -9,6 +9,7 @@ from django.views import View
|
||||||
|
|
||||||
from bookwyrm import forms, models
|
from bookwyrm import forms, models
|
||||||
from bookwyrm.settings import PAGE_LENGTH
|
from bookwyrm.settings import PAGE_LENGTH
|
||||||
|
from . import helpers
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable= no-self-use
|
# pylint: disable= no-self-use
|
||||||
|
@ -77,3 +78,22 @@ class Invite(View):
|
||||||
return TemplateResponse(request, "invite.html", data)
|
return TemplateResponse(request, "invite.html", data)
|
||||||
|
|
||||||
# post handling is in views.authentication.Register
|
# post handling is in views.authentication.Register
|
||||||
|
|
||||||
|
|
||||||
|
class InviteRequest(View):
|
||||||
|
""" prospective users sign up here """
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
""" create a request """
|
||||||
|
form = forms.InviteRequestForm(request.POST)
|
||||||
|
received = False
|
||||||
|
if form.is_valid():
|
||||||
|
received = True
|
||||||
|
form.save()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"request_form": form,
|
||||||
|
"request_received": received,
|
||||||
|
"books": helpers.get_discover_books(),
|
||||||
|
}
|
||||||
|
return TemplateResponse(request, "discover/discover.html", data)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
""" non-interactive pages """
|
""" non-interactive pages """
|
||||||
from django.db.models import Max
|
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.views import View
|
from django.views import View
|
||||||
|
|
||||||
from bookwyrm import forms, models
|
from bookwyrm import forms, models
|
||||||
from .feed import Feed
|
from .feed import Feed
|
||||||
|
from . import helpers
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable= no-self-use
|
# pylint: disable= no-self-use
|
||||||
|
@ -33,20 +33,9 @@ class Discover(View):
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
""" tiled book activity page """
|
""" tiled book activity page """
|
||||||
books = (
|
|
||||||
models.Edition.objects.filter(
|
|
||||||
review__published_date__isnull=False,
|
|
||||||
review__deleted=False,
|
|
||||||
review__user__local=True,
|
|
||||||
review__privacy__in=["public", "unlisted"],
|
|
||||||
)
|
|
||||||
.exclude(cover__exact="")
|
|
||||||
.annotate(Max("review__published_date"))
|
|
||||||
.order_by("-review__published_date__max")[:6]
|
|
||||||
)
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"register_form": forms.RegisterForm(),
|
"register_form": forms.RegisterForm(),
|
||||||
"books": list(set(books)),
|
"request_form": forms.InviteRequestForm(),
|
||||||
|
"books": helpers.get_discover_books(),
|
||||||
}
|
}
|
||||||
return TemplateResponse(request, "discover/discover.html", data)
|
return TemplateResponse(request, "discover/discover.html", data)
|
||||||
|
|
Loading…
Reference in a new issue