Browse Source

fix #589: forms cleanup

Rafał Pitoń 8 years ago
parent
commit
906e9f1707

+ 2 - 23
docs/Forms.md

@@ -11,38 +11,17 @@ Misago's admin uses [Crispy Forms](http://django-crispy-forms.readthedocs.org/en
 
 
 Finally, Misago defines few custom field types:
 Finally, Misago defines few custom field types:
 
 
+
 ### `misago.core.forms.YesNoSwitch`
 ### `misago.core.forms.YesNoSwitch`
 
 
 Thin wrapper around Django's `TypedChoiceField`. In admin this field renders nice yes/no switch as its input.
 Thin wrapper around Django's `TypedChoiceField`. In admin this field renders nice yes/no switch as its input.
 
 
+
 ##### Warning!
 ##### Warning!
 
 
 `YesNoSwitch` coerces its value to `int` (eg. `0` or `1`)! Remember about this when writing code dealing with forms containing this field!
 `YesNoSwitch` coerces its value to `int` (eg. `0` or `1`)! Remember about this when writing code dealing with forms containing this field!
 
 
 
 
-## `misago.forums.forms`
-
-This module defines two fields you may use for making forum selections in your forms:
-
-* `ForumChoiceField` that extends `django.core.forms.ModelChoiceField`
-* `ModelMultipleChoiceField` that extends `django.core.forms.ModelMultipleChoiceField`
-
-Because those fields need to know ACL, you are required to call their `set_acl` method from your form's `__init__`:
-
-```python
-class MoveThreadsForm(forms.Form):
-    new_forum = ForumChoiceField(label=_("Move threads to forum"))
-
-    def __init__(self, *args, **kwargs):
-        self.forum = kwargs.pop('forum')
-        acl = kwargs.pop('acl')
-
-        super(MoveThreadsForm, self).__init__(*args, **kwargs)
-
-        self.fields['new_forum'].set_acl(acl)
-```
-
-
 ## Template tags
 ## Template tags
 
 
 Misago defines custom templates extension named `misago_forms`. This extension contains two template tags for rendering form fields:
 Misago defines custom templates extension named `misago_forms`. This extension contains two template tags for rendering form fields:

+ 2 - 2
frontend/src/components/yes-no-switch.js

@@ -10,7 +10,7 @@ export default class extends React.Component {
   }
   }
 
 
   getIcon() {
   getIcon() {
-    if (this.props.value) {
+    if (!!this.props.value) {
       return this.props.iconOn || 'check_box';
       return this.props.iconOn || 'check_box';
     } else {
     } else {
       return this.props.iconOff || 'check_box_outline_blank';
       return this.props.iconOff || 'check_box_outline_blank';
@@ -18,7 +18,7 @@ export default class extends React.Component {
   }
   }
 
 
   getLabel() {
   getLabel() {
-    if (this.props.value) {
+    if (!!this.props.value) {
       return this.props.labelOn || gettext("yes");
       return this.props.labelOn || gettext("yes");
     } else {
     } else {
       return this.props.labelOff || gettext("no");
       return this.props.labelOff || gettext("no");

+ 1 - 2
misago/acl/forms.py

@@ -1,7 +1,6 @@
+from django import forms
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
-from misago.core import forms
-
 from .models import Role
 from .models import Role
 from .providers import providers
 from .providers import providers
 
 

+ 3 - 43
misago/categories/forms.py

@@ -1,10 +1,11 @@
 from mptt.forms import *  # noqa
 from mptt.forms import *  # noqa
 
 
+from django import forms
 from django.db import models
 from django.db import models
 from django.utils.html import conditional_escape, mark_safe
 from django.utils.html import conditional_escape, mark_safe
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 from misago.core.validators import validate_sluggable
 from misago.core.validators import validate_sluggable
 from misago.threads.threadtypes import trees_map
 from misago.threads.threadtypes import trees_map
 
 
@@ -45,47 +46,6 @@ class AdminCategoryMultipleChoiceField(
     pass
     pass
 
 
 
 
-class MisagoCategoryMixin(object):
-    def __init__(self, *args, **kwargs):
-        self.parent = None
-        if not 'queryset' in kwargs:
-            kwargs['queryset'] = Category.objects.order_by('lft')
-
-        if kwargs.get('error_messages', {}):
-            kwargs['error_messages'].update({
-                'invalid_choice': self.INVALID_CHOICE_ERROR
-            })
-        else:
-            kwargs['error_messages'] = {
-                'invalid_choice': self.INVALID_CHOICE_ERROR
-            }
-
-        super(MisagoCategoryMixin, self).__init__(*args, **kwargs)
-
-    def set_acl(self, acl=None):
-        queryset = Category.objects.root_category().get_descendants()
-        if acl:
-            allowed_ids = [0]
-            for category_id, perms in acl.get('categories', {}).items():
-                if perms.get('can_see') and perms.get('can_browse'):
-                    allowed_ids.append(category_id)
-            queryset = queryset.filter(id__in=allowed_ids)
-        self.queryset = queryset
-
-    def _get_level_indicator(self, obj):
-        level = obj.level - 1
-        return mark_safe(conditional_escape('- - ') * level)
-
-
-class CategoryChoiceField(MisagoCategoryMixin, TreeNodeChoiceField):
-    INVALID_CHOICE_ERROR = _("Select valid category.")
-
-
-class CategorysMultipleChoiceField(
-        MisagoCategoryMixin, TreeNodeMultipleChoiceField):
-    INVALID_CHOICE_ERROR = _("Select valid categories.")
-
-
 """
 """
 Forms
 Forms
 """
 """
@@ -107,7 +67,7 @@ class CategoryFormBase(forms.ModelForm):
         help_text=_("Optional CSS class used to customize this category "
         help_text=_("Optional CSS class used to customize this category "
                     "appearance from templates.")
                     "appearance from templates.")
     )
     )
-    is_closed = forms.YesNoSwitch(
+    is_closed = YesNoSwitch(
         label=_("Closed category"),
         label=_("Closed category"),
         required=False,
         required=False,
         help_text=_("Only members with valid permissions can post in "
         help_text=_("Only members with valid permissions can post in "

+ 4 - 3
misago/categories/permissions.py

@@ -1,3 +1,4 @@
+from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.core.exceptions import PermissionDenied
 from django.http import Http404
 from django.http import Http404
@@ -5,7 +6,7 @@ from django.utils.translation import ugettext_lazy as _
 
 
 from misago.acl import algebra
 from misago.acl import algebra
 from misago.acl.decorators import return_boolean
 from misago.acl.decorators import return_boolean
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
 
 
 from .models import Category, CategoryRole, RoleCategoryACL
 from .models import Category, CategoryRole, RoleCategoryACL
@@ -17,8 +18,8 @@ Admin Permissions Form
 class PermissionsForm(forms.Form):
 class PermissionsForm(forms.Form):
     legend = _("Category access")
     legend = _("Category access")
 
 
-    can_see = forms.YesNoSwitch(label=_("Can see category"))
-    can_browse = forms.YesNoSwitch(label=_("Can see category contents"))
+    can_see = YesNoSwitch(label=_("Can see category"))
+    can_browse = YesNoSwitch(label=_("Can see category contents"))
 
 
 
 
 def change_permissions_form(role):
 def change_permissions_form(role):

+ 4 - 4
misago/conf/forms.py

@@ -1,7 +1,7 @@
-from django.utils.translation import ugettext as _
-from django.utils.translation import ungettext
+from django import forms
+from django.utils.translation import ugettext as _, ungettext
 
 
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 
 
 __ALL__ = ['ChangeSettingsForm']
 __ALL__ = ['ChangeSettingsForm']
@@ -112,7 +112,7 @@ def create_textarea(setting, kwargs, extra):
 
 
 
 
 def create_yesno(setting, kwargs, extra):
 def create_yesno(setting, kwargs, extra):
-    return forms.YesNoSwitch(**kwargs)
+    return YesNoSwitch(**kwargs)
 
 
 
 
 FIELD_STYPES = {
 FIELD_STYPES = {

+ 2 - 7
misago/core/forms.py

@@ -1,10 +1,5 @@
-from datetime import datetime, timedelta
-
-from mptt.forms import *  # noqa
-
-from django.forms import *  # noqa
-from django.utils import timezone
-from django.utils.encoding import force_text
+from django.forms import (
+    DateTimeField, RadioSelect, TypedChoiceField, ValidationError)
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
 from .utils import parse_iso8601_string
 from .utils import parse_iso8601_string

+ 3 - 2
misago/core/tests/test_forms.py

@@ -1,10 +1,11 @@
+from django import forms
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import forms
+from misago.core.forms import YesNoSwitch
 
 
 
 
 class YesNoForm(forms.Form):
 class YesNoForm(forms.Form):
-    test_field = forms.YesNoSwitch(label='Hello!')
+    test_field = YesNoSwitch(label='Hello!')
 
 
 
 
 class YesNoSwitchTests(TestCase):
 class YesNoSwitchTests(TestCase):

+ 4 - 4
misago/core/tests/test_templatetags.py

@@ -1,10 +1,10 @@
+from django import forms
 from django.template import Context, Template, TemplateSyntaxError
 from django.template import Context, Template, TemplateSyntaxError
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import forms
-from ..shortcuts import paginate
-from ..templatetags import misago_batch
-from ..utils import encode_json_html
+from misago.core.shortcuts import paginate
+from misago.core.templatetags import misago_batch
+from misago.core.utils import encode_json_html
 
 
 
 
 class CaptureTests(TestCase):
 class CaptureTests(TestCase):

+ 3 - 3
misago/search/permissions.py

@@ -1,9 +1,9 @@
+from django import forms
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
-from django.utils.translation import ungettext
 
 
 from misago.acl import algebra
 from misago.acl import algebra
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 
 
 """
 """
@@ -12,7 +12,7 @@ Admin Permissions Form
 class PermissionsForm(forms.Form):
 class PermissionsForm(forms.Form):
     legend = _("Search")
     legend = _("Search")
 
 
-    can_search = forms.YesNoSwitch(
+    can_search = YesNoSwitch(
         label=_("Can search site"),
         label=_("Can search site"),
         initial=1
         initial=1
     )
     )

File diff suppressed because it is too large
+ 0 - 0
misago/static/misago/js/misago.js.map


+ 5 - 4
misago/threads/permissions/attachments.py

@@ -1,8 +1,9 @@
+from django import forms
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
 from misago.acl import algebra
 from misago.acl import algebra
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 from ..models import Attachment
 from ..models import Attachment
 
 
@@ -20,14 +21,14 @@ class PermissionsForm(forms.Form):
         min_value=0
         min_value=0
     )
     )
 
 
-    can_download_other_users_attachments = forms.YesNoSwitch(label=_("Can download other users attachments"))
-    can_delete_other_users_attachments = forms.YesNoSwitch(label=_("Can delete other users attachments"))
+    can_download_other_users_attachments = YesNoSwitch(label=_("Can download other users attachments"))
+    can_delete_other_users_attachments = YesNoSwitch(label=_("Can delete other users attachments"))
 
 
 
 
 class AnonymousPermissionsForm(forms.Form):
 class AnonymousPermissionsForm(forms.Form):
     legend = _("Attachments")
     legend = _("Attachments")
 
 
-    can_download_other_users_attachments = forms.YesNoSwitch(label=_("Can download attachments"))
+    can_download_other_users_attachments = YesNoSwitch(label=_("Can download attachments"))
 
 
 
 
 def change_permissions_form(role):
 def change_permissions_form(role):

+ 3 - 2
misago/threads/permissions/polls.py

@@ -1,3 +1,4 @@
+from django import forms
 from django.core.exceptions import PermissionDenied
 from django.core.exceptions import PermissionDenied
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
@@ -6,7 +7,7 @@ from django.utils.translation import ungettext
 from misago.acl import algebra
 from misago.acl import algebra
 from misago.acl.decorators import return_boolean
 from misago.acl.decorators import return_boolean
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 from ..models import Poll, Thread
 from ..models import Poll, Thread
 
 
@@ -53,7 +54,7 @@ class RolePermissionsForm(forms.Form):
         initial=0,
         initial=0,
         min_value=0
         min_value=0
     )
     )
-    can_always_see_poll_voters = forms.YesNoSwitch(
+    can_always_see_poll_voters = YesNoSwitch(
         label=_("Can always see polls voters"),
         label=_("Can always see polls voters"),
         help_text=_("Allows users to see who voted in poll even if poll votes are secret.")
         help_text=_("Allows users to see who voted in poll even if poll votes are secret.")
     )
     )

+ 7 - 6
misago/threads/permissions/privatethreads.py

@@ -1,3 +1,4 @@
+from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q
 from django.db.models import Q
@@ -8,7 +9,7 @@ from misago.acl import add_acl, algebra
 from misago.acl.decorators import return_boolean
 from misago.acl.decorators import return_boolean
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.categories.models import PRIVATE_THREADS_ROOT_NAME, Category
 from misago.categories.models import PRIVATE_THREADS_ROOT_NAME, Category
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 from ..models import Thread
 from ..models import Thread
 
 
@@ -37,24 +38,24 @@ Admin Permissions Form
 class PermissionsForm(forms.Form):
 class PermissionsForm(forms.Form):
     legend = _("Private threads")
     legend = _("Private threads")
 
 
-    can_use_private_threads = forms.YesNoSwitch(label=_("Can use private threads"))
-    can_start_private_threads = forms.YesNoSwitch(label=_("Can start private threads"))
+    can_use_private_threads = YesNoSwitch(label=_("Can use private threads"))
+    can_start_private_threads = YesNoSwitch(label=_("Can start private threads"))
     max_private_thread_participants = forms.IntegerField(
     max_private_thread_participants = forms.IntegerField(
         label=_("Max number of users invited to private thread"),
         label=_("Max number of users invited to private thread"),
         help_text=_("Enter 0 to don't limit number of participants."),
         help_text=_("Enter 0 to don't limit number of participants."),
         initial=3,
         initial=3,
         min_value=0
         min_value=0
     )
     )
-    can_add_everyone_to_private_threads = forms.YesNoSwitch(
+    can_add_everyone_to_private_threads = YesNoSwitch(
         label=_("Can add everyone to threads"),
         label=_("Can add everyone to threads"),
         help_text=_("Allows user to add users that are blocking him to private threads.")
         help_text=_("Allows user to add users that are blocking him to private threads.")
     )
     )
-    can_report_private_threads = forms.YesNoSwitch(
+    can_report_private_threads = YesNoSwitch(
         label=_("Can report private threads"),
         label=_("Can report private threads"),
         help_text=_("Allows user to report private threads they are "
         help_text=_("Allows user to report private threads they are "
                     "participating in, making them accessible to moderators.")
                     "participating in, making them accessible to moderators.")
     )
     )
-    can_moderate_private_threads = forms.YesNoSwitch(
+    can_moderate_private_threads = YesNoSwitch(
         label=_("Can moderate private threads"),
         label=_("Can moderate private threads"),
         help_text=_("Allows user to read, reply, edit and delete content "
         help_text=_("Allows user to read, reply, edit and delete content "
                     "in reported private threads.")
                     "in reported private threads.")

+ 17 - 16
misago/threads/permissions/threads.py

@@ -1,3 +1,4 @@
+from django import forms
 from django.core.exceptions import PermissionDenied
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q
 from django.db.models import Q
 from django.http import Http404
 from django.http import Http404
@@ -10,7 +11,7 @@ from misago.acl.decorators import return_boolean
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.categories.models import Category, CategoryRole, RoleCategoryACL
 from misago.categories.models import Category, CategoryRole, RoleCategoryACL
 from misago.categories.permissions import get_categories_roles
 from misago.categories.permissions import get_categories_roles
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 from ..models import Post, Thread
 from ..models import Post, Thread
 
 
@@ -21,7 +22,7 @@ Admin Permissions Forms
 class RolePermissionsForm(forms.Form):
 class RolePermissionsForm(forms.Form):
     legend = _("Threads")
     legend = _("Threads")
 
 
-    can_see_unapproved_content_lists = forms.YesNoSwitch(
+    can_see_unapproved_content_lists = YesNoSwitch(
         label=_("Can see unapproved content list"),
         label=_("Can see unapproved content list"),
         help_text=_('Allows access to "unapproved" tab on threads lists for '
         help_text=_('Allows access to "unapproved" tab on threads lists for '
                     "easy listing of threads that are unapproved or contain "
                     "easy listing of threads that are unapproved or contain "
@@ -30,7 +31,7 @@ class RolePermissionsForm(forms.Form):
                     "categories in which the user has permission to approve "
                     "categories in which the user has permission to approve "
                     "content.")
                     "content.")
     )
     )
-    can_see_reported_content_lists = forms.YesNoSwitch(
+    can_see_reported_content_lists = YesNoSwitch(
         label=_("Can see reported content list"),
         label=_("Can see reported content list"),
         help_text=_('Allows access to "reported" tab on threads lists for '
         help_text=_('Allows access to "reported" tab on threads lists for '
                     "easy listing of threads that contain reported posts. "
                     "easy listing of threads that contain reported posts. "
@@ -39,7 +40,7 @@ class RolePermissionsForm(forms.Form):
                     "categories in which the user has permission to see posts "
                     "categories in which the user has permission to see posts "
                     "reports.")
                     "reports.")
     )
     )
-    can_omit_flood_protection = forms.YesNoSwitch(
+    can_omit_flood_protection = YesNoSwitch(
         label=_("Can omit flood protection"),
         label=_("Can omit flood protection"),
         help_text=_("Allows posting more frequently than flood protection would.")
         help_text=_("Allows posting more frequently than flood protection would.")
     )
     )
@@ -55,8 +56,8 @@ class CategoryPermissionsForm(forms.Form):
         choices=((0, _("Started threads")), (1, _("All threads")))
         choices=((0, _("Started threads")), (1, _("All threads")))
     )
     )
 
 
-    can_start_threads = forms.YesNoSwitch(label=_("Can start threads"))
-    can_reply_threads = forms.YesNoSwitch(label=_("Can reply to threads"))
+    can_start_threads = YesNoSwitch(label=_("Can start threads"))
+    can_reply_threads = YesNoSwitch(label=_("Can reply to threads"))
 
 
     can_edit_threads = forms.TypedChoiceField(
     can_edit_threads = forms.TypedChoiceField(
         label=_("Can edit threads"),
         label=_("Can edit threads"),
@@ -103,9 +104,9 @@ class CategoryPermissionsForm(forms.Form):
             (2, _("Globally"))
             (2, _("Globally"))
         )
         )
     )
     )
-    can_close_threads = forms.YesNoSwitch(label=_("Can close threads"))
-    can_move_threads = forms.YesNoSwitch(label=_("Can move threads"))
-    can_merge_threads = forms.YesNoSwitch(label=_("Can merge threads"))
+    can_close_threads = YesNoSwitch(label=_("Can close threads"))
+    can_move_threads = YesNoSwitch(label=_("Can move threads"))
+    can_merge_threads = YesNoSwitch(label=_("Can merge threads"))
 
 
     can_edit_posts = forms.TypedChoiceField(
     can_edit_posts = forms.TypedChoiceField(
         label=_("Can edit posts"),
         label=_("Can edit posts"),
@@ -151,26 +152,26 @@ class CategoryPermissionsForm(forms.Form):
             (2, _("Number and list of likers"))
             (2, _("Number and list of likers"))
         )
         )
     )
     )
-    can_like_posts = forms.YesNoSwitch(
+    can_like_posts = YesNoSwitch(
         label=_("Can like posts"),
         label=_("Can like posts"),
         help_text=_("Only users with this permission to see likes can like posts.")
         help_text=_("Only users with this permission to see likes can like posts.")
     )
     )
 
 
-    can_protect_posts = forms.YesNoSwitch(
+    can_protect_posts = YesNoSwitch(
         label=_("Can protect posts"),
         label=_("Can protect posts"),
         help_text=_("Only users with this permission can edit protected posts.")
         help_text=_("Only users with this permission can edit protected posts.")
     )
     )
-    can_move_posts = forms.YesNoSwitch(
+    can_move_posts = YesNoSwitch(
         label=_("Can move posts"),
         label=_("Can move posts"),
         help_text=_("Will be able to move posts to other threads.")
         help_text=_("Will be able to move posts to other threads.")
     )
     )
-    can_merge_posts = forms.YesNoSwitch(label=_("Can merge posts"))
-    can_approve_content = forms.YesNoSwitch(
+    can_merge_posts = YesNoSwitch(label=_("Can merge posts"))
+    can_approve_content = YesNoSwitch(
         label=_("Can approve content"),
         label=_("Can approve content"),
         help_text=_("Will be able to see and approve unapproved content.")
         help_text=_("Will be able to see and approve unapproved content.")
     )
     )
-    can_report_content = forms.YesNoSwitch(label=_("Can report posts"))
-    can_see_reports = forms.YesNoSwitch(label=_("Can see reports"))
+    can_report_content = YesNoSwitch(label=_("Can report posts"))
+    can_see_reports = YesNoSwitch(label=_("Can see reports"))
 
 
     can_hide_events = forms.TypedChoiceField(
     can_hide_events = forms.TypedChoiceField(
         label=_("Can hide events"),
         label=_("Can hide events"),

+ 2 - 3
misago/users/api/userendpoints/create.py

@@ -1,5 +1,5 @@
 from django.contrib.auth import authenticate, get_user_model, login
 from django.contrib.auth import authenticate, get_user_model, login
-from django.core.exceptions import PermissionDenied
+from django.core.exceptions import PermissionDenied, ValidationError
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 from django.views.decorators.csrf import csrf_protect
 from django.views.decorators.csrf import csrf_protect
 
 
@@ -7,7 +7,6 @@ from rest_framework import status
 from rest_framework.response import Response
 from rest_framework.response import Response
 
 
 from misago.conf import settings
 from misago.conf import settings
-from misago.core import forms
 from misago.core.mail import mail_user
 from misago.core.mail import mail_user
 
 
 from ... import captcha
 from ... import captcha
@@ -26,7 +25,7 @@ def create_endpoint(request):
 
 
     try:
     try:
         captcha.test_request(request)
         captcha.test_request(request)
-    except forms.ValidationError as e:
+    except ValidationError as e:
         form.add_error('captcha', e)
         form.add_error('captcha', e)
 
 
     if not form.is_valid():
     if not form.is_valid():

+ 1 - 2
misago/users/djangoadmin.py

@@ -9,14 +9,13 @@ Registration call is placed in :mod:`misago.users.admin`.
 
 
 Test for the model is placed in :mod:`misago.users.tests.test_djangoadmin_user`.
 Test for the model is placed in :mod:`misago.users.tests.test_djangoadmin_user`.
 """
 """
+from django import forms
 from django.contrib import admin
 from django.contrib import admin
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.urls import reverse
 from django.utils.html import format_html
 from django.utils.html import format_html
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 
 
-from misago.core import forms
-
 
 
 # Misago user model
 # Misago user model
 User = get_user_model()
 User = get_user_model()

+ 14 - 12
misago/users/forms/admin.py

@@ -1,10 +1,12 @@
+from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ungettext
 from django.utils.translation import ungettext
 
 
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.conf import settings
 from misago.conf import settings
-from misago.core import forms, threadstore
+from misago.core import threadstore
+from misago.core.forms import IsoDateTimeField, YesNoSwitch
 from misago.core.validators import validate_sluggable
 from misago.core.validators import validate_sluggable
 
 
 from ..models import (
 from ..models import (
@@ -100,7 +102,7 @@ class EditUserForm(UserBaseForm):
         required=False
         required=False
     )
     )
 
 
-    is_avatar_locked = forms.YesNoSwitch(
+    is_avatar_locked = YesNoSwitch(
         label=_("Lock avatar"),
         label=_("Lock avatar"),
         help_text=_(
         help_text=_(
             "Setting this to yes will stop user from changing "
             "Setting this to yes will stop user from changing "
@@ -132,7 +134,7 @@ class EditUserForm(UserBaseForm):
         widget=forms.Textarea(attrs={'rows': 3}),
         widget=forms.Textarea(attrs={'rows': 3}),
         required=False
         required=False
     )
     )
-    is_signature_locked = forms.YesNoSwitch(
+    is_signature_locked = YesNoSwitch(
         label=_("Lock signature"),
         label=_("Lock signature"),
         help_text=_(
         help_text=_(
             "Setting this to yes will stop user from "
             "Setting this to yes will stop user from "
@@ -156,7 +158,7 @@ class EditUserForm(UserBaseForm):
         required=False
         required=False
     )
     )
 
 
-    is_hiding_presence = forms.YesNoSwitch(label=_("Hides presence"))
+    is_hiding_presence = YesNoSwitch(label=_("Hides presence"))
 
 
     limits_private_thread_invites_to = forms.TypedChoiceField(
     limits_private_thread_invites_to = forms.TypedChoiceField(
         label=_("Who can add user to private threads"),
         label=_("Who can add user to private threads"),
@@ -238,12 +240,12 @@ def UserFormFactory(FormType, instance):
 
 
 def StaffFlagUserFormFactory(FormType, instance):
 def StaffFlagUserFormFactory(FormType, instance):
     staff_fields = {
     staff_fields = {
-        'is_staff': forms.YesNoSwitch(
+        'is_staff': YesNoSwitch(
             label=EditUserForm.IS_STAFF_LABEL,
             label=EditUserForm.IS_STAFF_LABEL,
             help_text=EditUserForm.IS_STAFF_HELP_TEXT,
             help_text=EditUserForm.IS_STAFF_HELP_TEXT,
             initial=instance.is_staff
             initial=instance.is_staff
         ),
         ),
-        'is_superuser': forms.YesNoSwitch(
+        'is_superuser': YesNoSwitch(
             label=EditUserForm.IS_SUPERUSER_LABEL,
             label=EditUserForm.IS_SUPERUSER_LABEL,
             help_text=EditUserForm.IS_SUPERUSER_HELP_TEXT,
             help_text=EditUserForm.IS_SUPERUSER_HELP_TEXT,
             initial=instance.is_superuser
             initial=instance.is_superuser
@@ -255,7 +257,7 @@ def StaffFlagUserFormFactory(FormType, instance):
 
 
 def UserIsActiveFormFactory(FormType, instance):
 def UserIsActiveFormFactory(FormType, instance):
     is_active_fields = {
     is_active_fields = {
-        'is_active': forms.YesNoSwitch(
+        'is_active': YesNoSwitch(
             label=EditUserForm.IS_ACTIVE_LABEL,
             label=EditUserForm.IS_ACTIVE_LABEL,
             help_text=EditUserForm.IS_ACTIVE_HELP_TEXT,
             help_text=EditUserForm.IS_ACTIVE_HELP_TEXT,
             initial=instance.is_active
             initial=instance.is_active
@@ -288,9 +290,9 @@ def EditUserFormFactory(FormType, instance,
 class SearchUsersFormBase(forms.Form):
 class SearchUsersFormBase(forms.Form):
     username = forms.CharField(label=_("Username starts with"), required=False)
     username = forms.CharField(label=_("Username starts with"), required=False)
     email = forms.CharField(label=_("E-mail starts with"), required=False)
     email = forms.CharField(label=_("E-mail starts with"), required=False)
-    inactive = forms.YesNoSwitch(label=_("Inactive only"))
-    disabled = forms.YesNoSwitch(label=_("Disabled only"))
-    is_staff = forms.YesNoSwitch(label=_("Admins only"))
+    inactive = YesNoSwitch(label=_("Inactive only"))
+    disabled = YesNoSwitch(label=_("Disabled only"))
+    is_staff = YesNoSwitch(label=_("Admins only"))
 
 
     def filter_queryset(self, criteria, queryset):
     def filter_queryset(self, criteria, queryset):
         if criteria.get('username'):
         if criteria.get('username'):
@@ -475,7 +477,7 @@ class BanUsersForm(forms.Form):
             'max_length': _("Message can't be longer than 1000 characters.")
             'max_length': _("Message can't be longer than 1000 characters.")
         }
         }
     )
     )
-    expires_on = forms.IsoDateTimeField(
+    expires_on = IsoDateTimeField(
         label=_("Expires on"),
         label=_("Expires on"),
         required=False,
         required=False,
         help_text=_("Leave this field empty for set bans to never expire.")
         help_text=_("Leave this field empty for set bans to never expire.")
@@ -521,7 +523,7 @@ class BanForm(forms.ModelForm):
             'max_length': _("Message can't be longer than 1000 characters.")
             'max_length': _("Message can't be longer than 1000 characters.")
         }
         }
     )
     )
-    expires_on = forms.IsoDateTimeField(
+    expires_on = IsoDateTimeField(
         label=_("Expires on"),
         label=_("Expires on"),
         required=False,
         required=False,
         help_text=_("Leave this field empty for this ban to never expire.")
         help_text=_("Leave this field empty for this ban to never expire.")

+ 1 - 2
misago/users/forms/auth.py

@@ -1,11 +1,10 @@
+from django import forms
 from django.contrib.auth import authenticate, get_user_model
 from django.contrib.auth import authenticate, get_user_model
 from django.contrib.auth.forms import AuthenticationForm as BaseAuthenticationForm
 from django.contrib.auth.forms import AuthenticationForm as BaseAuthenticationForm
 from django.core.exceptions import ValidationError
 from django.core.exceptions import ValidationError
 from django.core.validators import validate_email
 from django.core.validators import validate_email
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
-from misago.core import forms
-
 from ..bans import get_user_ban
 from ..bans import get_user_ban
 from ..validators import validate_password
 from ..validators import validate_password
 
 

+ 4 - 3
misago/users/forms/moderation.py

@@ -1,18 +1,19 @@
 from datetime import timedelta
 from datetime import timedelta
 
 
+from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ungettext
 from django.utils.translation import ungettext
 
 
 from misago.conf import settings
 from misago.conf import settings
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 from ..bans import ban_user
 from ..bans import ban_user
 
 
 
 
 class ModerateAvatarForm(forms.ModelForm):
 class ModerateAvatarForm(forms.ModelForm):
-    is_avatar_locked = forms.YesNoSwitch()
+    is_avatar_locked = YesNoSwitch()
     avatar_lock_user_message = forms.CharField(required=False)
     avatar_lock_user_message = forms.CharField(required=False)
     avatar_lock_staff_message = forms.CharField(required=False)
     avatar_lock_staff_message = forms.CharField(required=False)
 
 
@@ -30,7 +31,7 @@ class ModerateSignatureForm(forms.ModelForm):
         label=_("Signature contents"),
         label=_("Signature contents"),
         widget=forms.Textarea(attrs={'rows': 3}),
         widget=forms.Textarea(attrs={'rows': 3}),
         required=False)
         required=False)
-    is_signature_locked = forms.YesNoSwitch(
+    is_signature_locked = YesNoSwitch(
         label=_("Lock signature"),
         label=_("Lock signature"),
         help_text=_("Setting this to yes will stop user from "
         help_text=_("Setting this to yes will stop user from "
                     "making changes to his/her signature."))
                     "making changes to his/her signature."))

+ 3 - 2
misago/users/forms/options.py

@@ -1,16 +1,17 @@
+from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ungettext
 from django.utils.translation import ungettext
 
 
 from misago.conf import settings
 from misago.conf import settings
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 from ..models import AUTO_SUBSCRIBE_CHOICES, PRIVATE_THREAD_INVITES_LIMITS_CHOICES
 from ..models import AUTO_SUBSCRIBE_CHOICES, PRIVATE_THREAD_INVITES_LIMITS_CHOICES
 from ..validators import validate_email, validate_password
 from ..validators import validate_email, validate_password
 
 
 
 
 class ForumOptionsForm(forms.ModelForm):
 class ForumOptionsForm(forms.ModelForm):
-    is_hiding_presence = forms.YesNoSwitch()
+    is_hiding_presence = YesNoSwitch()
 
 
     limits_private_thread_invites_to = forms.TypedChoiceField(
     limits_private_thread_invites_to = forms.TypedChoiceField(
         coerce=int, choices=PRIVATE_THREAD_INVITES_LIMITS_CHOICES)
         coerce=int, choices=PRIVATE_THREAD_INVITES_LIMITS_CHOICES)

+ 1 - 1
misago/users/forms/register.py

@@ -1,4 +1,4 @@
-from misago.core import forms
+from django import forms
 
 
 from .. import validators
 from .. import validators
 
 

+ 1 - 2
misago/users/forms/rename.py

@@ -1,7 +1,6 @@
+from django import forms
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
-from misago.core import forms
-
 from ..validators import validate_username
 from ..validators import validate_username
 
 
 
 

+ 6 - 5
misago/users/permissions/account.py

@@ -1,8 +1,9 @@
+from django import forms
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
 from misago.acl import algebra
 from misago.acl import algebra
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 
 
 """
 """
@@ -24,10 +25,10 @@ class PermissionsForm(forms.Form):
         min_value=0,
         min_value=0,
         initial=0
         initial=0
     )
     )
-    can_have_signature = forms.YesNoSwitch(label=_("Can have signature"))
-    allow_signature_links = forms.YesNoSwitch(label=_("Can put links in signature"))
-    allow_signature_images = forms.YesNoSwitch(label=_("Can put images in signature"))
-    allow_signature_blocks = forms.YesNoSwitch(
+    can_have_signature = YesNoSwitch(label=_("Can have signature"))
+    allow_signature_links = YesNoSwitch(label=_("Can put links in signature"))
+    allow_signature_images = YesNoSwitch(label=_("Can put images in signature"))
+    allow_signature_blocks = YesNoSwitch(
         label=_("Can use text blocks in signature"),
         label=_("Can use text blocks in signature"),
         help_text=_("Controls whether or not users can put quote, code, "
         help_text=_("Controls whether or not users can put quote, code, "
                     "spoiler blocks and horizontal lines in signatures.")
                     "spoiler blocks and horizontal lines in signatures.")

+ 1 - 1
misago/users/permissions/delete.py

@@ -1,5 +1,6 @@
 from datetime import timedelta
 from datetime import timedelta
 
 
+from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.core.exceptions import PermissionDenied
 from django.utils import timezone
 from django.utils import timezone
@@ -9,7 +10,6 @@ from django.utils.translation import ungettext
 from misago.acl import algebra
 from misago.acl import algebra
 from misago.acl.decorators import return_boolean
 from misago.acl.decorators import return_boolean
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.core import forms
 
 
 
 
 """
 """

+ 7 - 6
misago/users/permissions/moderation.py

@@ -1,5 +1,6 @@
 from datetime import timedelta
 from datetime import timedelta
 
 
+from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.core.exceptions import PermissionDenied
 from django.template.defaultfilters import date as format_date
 from django.template.defaultfilters import date as format_date
@@ -9,7 +10,7 @@ from django.utils.translation import ugettext_lazy as _
 from misago.acl import algebra
 from misago.acl import algebra
 from misago.acl.decorators import return_boolean
 from misago.acl.decorators import return_boolean
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 from ..bans import get_user_ban
 from ..bans import get_user_ban
 
 
@@ -20,17 +21,17 @@ Admin Permissions Form
 class PermissionsForm(forms.Form):
 class PermissionsForm(forms.Form):
     legend = _("Users moderation")
     legend = _("Users moderation")
 
 
-    can_rename_users = forms.YesNoSwitch(label=_("Can rename users"))
-    can_moderate_avatars = forms.YesNoSwitch(label=_("Can moderate avatars"))
-    can_moderate_signatures = forms.YesNoSwitch(label=_("Can moderate signatures"))
-    can_ban_users = forms.YesNoSwitch(label=_("Can ban users"))
+    can_rename_users = YesNoSwitch(label=_("Can rename users"))
+    can_moderate_avatars = YesNoSwitch(label=_("Can moderate avatars"))
+    can_moderate_signatures = YesNoSwitch(label=_("Can moderate signatures"))
+    can_ban_users = YesNoSwitch(label=_("Can ban users"))
     max_ban_length = forms.IntegerField(
     max_ban_length = forms.IntegerField(
         label=_("Max length, in days, of imposed ban"),
         label=_("Max length, in days, of imposed ban"),
         help_text=_("Enter zero to let moderators impose permanent bans."),
         help_text=_("Enter zero to let moderators impose permanent bans."),
         min_value=0,
         min_value=0,
         initial=0
         initial=0
     )
     )
-    can_lift_bans = forms.YesNoSwitch(label=_("Can lift bans"))
+    can_lift_bans = YesNoSwitch(label=_("Can lift bans"))
     max_lifted_ban_length = forms.IntegerField(
     max_lifted_ban_length = forms.IntegerField(
         label=_("Max length, in days, of lifted ban"),
         label=_("Max length, in days, of lifted ban"),
         help_text=_("Enter zero to let moderators lift permanent bans."),
         help_text=_("Enter zero to let moderators lift permanent bans."),

+ 11 - 10
misago/users/permissions/profiles.py

@@ -1,3 +1,4 @@
+from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
@@ -5,7 +6,7 @@ from django.utils.translation import ugettext_lazy as _
 from misago.acl import algebra
 from misago.acl import algebra
 from misago.acl.decorators import return_boolean
 from misago.acl.decorators import return_boolean
 from misago.acl.models import Role
 from misago.acl.models import Role
-from misago.core import forms
+from misago.core.forms import YesNoSwitch
 
 
 from .decorators import authenticated_only
 from .decorators import authenticated_only
 
 
@@ -13,18 +14,18 @@ from .decorators import authenticated_only
 """
 """
 Admin Permissions Form
 Admin Permissions Form
 """
 """
-CAN_BROWSE_USERS_LIST = forms.YesNoSwitch(
+CAN_BROWSE_USERS_LIST = YesNoSwitch(
     label=_("Can browse users list"),
     label=_("Can browse users list"),
     initial=1
     initial=1
 )
 )
-CAN_SEARCH_USERS = forms.YesNoSwitch(
+CAN_SEARCH_USERS = YesNoSwitch(
     label=_("Can search user profiles"),
     label=_("Can search user profiles"),
     initial=1
     initial=1
 )
 )
-CAN_SEE_USER_NAME_HISTORY = forms.YesNoSwitch(
+CAN_SEE_USER_NAME_HISTORY = YesNoSwitch(
     label=_("Can see other members name history")
     label=_("Can see other members name history")
 )
 )
-CAN_SEE_BAN_DETAILS = forms.YesNoSwitch(
+CAN_SEE_BAN_DETAILS = YesNoSwitch(
     label=_("Can see members bans details"),
     label=_("Can see members bans details"),
     help_text=_("Allows users with this permission to see user and staff ban messages.")
     help_text=_("Allows users with this permission to see user and staff ban messages.")
 )
 )
@@ -42,23 +43,23 @@ class LimitedPermissionsForm(forms.Form):
 class PermissionsForm(LimitedPermissionsForm):
 class PermissionsForm(LimitedPermissionsForm):
     can_browse_users_list = CAN_BROWSE_USERS_LIST
     can_browse_users_list = CAN_BROWSE_USERS_LIST
     can_search_users = CAN_SEARCH_USERS
     can_search_users = CAN_SEARCH_USERS
-    can_follow_users = forms.YesNoSwitch(
+    can_follow_users = YesNoSwitch(
         label=_("Can follow other users"),
         label=_("Can follow other users"),
         initial=1
         initial=1
     )
     )
-    can_be_blocked = forms.YesNoSwitch(
+    can_be_blocked = YesNoSwitch(
         label=_("Can be blocked by other users"),
         label=_("Can be blocked by other users"),
         initial=0
         initial=0
     )
     )
     can_see_users_name_history = CAN_SEE_USER_NAME_HISTORY
     can_see_users_name_history = CAN_SEE_USER_NAME_HISTORY
     can_see_ban_details = CAN_SEE_BAN_DETAILS
     can_see_ban_details = CAN_SEE_BAN_DETAILS
-    can_see_users_emails = forms.YesNoSwitch(
+    can_see_users_emails = YesNoSwitch(
         label=_("Can see members e-mails")
         label=_("Can see members e-mails")
     )
     )
-    can_see_users_ips = forms.YesNoSwitch(
+    can_see_users_ips = YesNoSwitch(
         label=_("Can see members IPs")
         label=_("Can see members IPs")
     )
     )
-    can_see_hidden_users = forms.YesNoSwitch(
+    can_see_hidden_users = YesNoSwitch(
         label=_("Can see members that hide their presence")
         label=_("Can see members that hide their presence")
     )
     )
 
 

+ 29 - 0
misago/users/tests/test_users_api.py

@@ -302,6 +302,35 @@ class UserCategoriesOptionsTests(AuthenticatedUserTestCase):
         self.assertEqual(self.user.subscribe_to_started_threads, 2)
         self.assertEqual(self.user.subscribe_to_started_threads, 2)
         self.assertEqual(self.user.subscribe_to_replied_threads, 1)
         self.assertEqual(self.user.subscribe_to_replied_threads, 1)
 
 
+        response = self.client.post(self.link, data={
+            'is_hiding_presence': 'true',
+            'limits_private_thread_invites_to': 1,
+            'subscribe_to_started_threads': 2,
+            'subscribe_to_replied_threads': 1
+        })
+        self.assertEqual(response.status_code, 200)
+
+        self.reload_user();
+
+        self.assertTrue(self.user.is_hiding_presence)
+        self.assertEqual(self.user.limits_private_thread_invites_to, 1)
+        self.assertEqual(self.user.subscribe_to_started_threads, 2)
+        self.assertEqual(self.user.subscribe_to_replied_threads, 1)
+
+        response = self.client.post(self.link, data={
+            'is_hiding_presence': 'false',
+            'limits_private_thread_invites_to': 1,
+            'subscribe_to_started_threads': 2,
+            'subscribe_to_replied_threads': 1
+        })
+        self.assertEqual(response.status_code, 200)
+
+        self.reload_user();
+
+        self.assertFalse(self.user.is_hiding_presence)
+        self.assertEqual(self.user.limits_private_thread_invites_to, 1)
+        self.assertEqual(self.user.subscribe_to_started_threads, 2)
+        self.assertEqual(self.user.subscribe_to_replied_threads, 1)
 
 
 class UserFollowTests(AuthenticatedUserTestCase):
 class UserFollowTests(AuthenticatedUserTestCase):
     """
     """

Some files were not shown because too many files changed in this diff