Browse Source

Added ability to create and remove categories.
Renamed the templates for adding and creating users, groups and forums to a more appropriate name.

sh4nks 11 years ago
parent
commit
183ba9ff42

+ 33 - 31
flaskbb/admin/forms.py

@@ -19,7 +19,7 @@ from wtforms.ext.sqlalchemy.fields import (QuerySelectField,
 
 
 from flaskbb.utils.widgets import SelectDateWidget
 from flaskbb.utils.widgets import SelectDateWidget
 from flaskbb.extensions import db
 from flaskbb.extensions import db
-from flaskbb.forum.models import Forum
+from flaskbb.forum.models import Forum, Category
 from flaskbb.user.models import User, Group
 from flaskbb.user.models import User, Group
 
 
 USERNAME_RE = r'^[\w.+-]+$'
 USERNAME_RE = r'^[\w.+-]+$'
@@ -28,7 +28,11 @@ is_username = regexp(USERNAME_RE,
 
 
 
 
 def selectable_forums():
 def selectable_forums():
-    return Forum.query.order_by(Forum.id)
+    return Forum.query.order_by(Forum.position)
+
+
+def selectable_categories():
+    return Category.query.order_by(Category.position)
 
 
 
 
 def select_primary_group():
 def select_primary_group():
@@ -215,48 +219,34 @@ class AddGroupForm(GroupForm):
 
 
 
 
 class ForumForm(Form):
 class ForumForm(Form):
-    _id = None
     _moderators = set()
     _moderators = set()
 
 
     title = TextField("Forum Title", validators=[
     title = TextField("Forum Title", validators=[
         Required(message="Forum title required")])
         Required(message="Forum title required")])
 
 
     description = TextAreaField("Description", validators=[
     description = TextAreaField("Description", validators=[
-        Optional()])
+        Optional()],
+        description="You can format your description with BBCode.")
 
 
     position = IntegerField("Position", default=1, validators=[
     position = IntegerField("Position", default=1, validators=[
         Required(message="Forum position required")])
         Required(message="Forum position required")])
 
 
-    parent = QuerySelectField("Parent",
-                              query_factory=selectable_forums,
-                              allow_blank=True,
-                              get_label="title",
-                              description="This field is not saved if this \
-                                           forum is a category (see \"Is a \
-                                           category?\" field below).")
+    category = QuerySelectField(
+        "Category",
+        query_factory=selectable_categories,
+        allow_blank=False,
+        get_label="title",
+        description="The category that contains this forum."
+    )
 
 
     moderators = TextField("Moderators",
     moderators = TextField("Moderators",
                            description="Comma seperated usernames. Leave it \
                            description="Comma seperated usernames. Leave it \
                                         blank if you do not want to set any \
                                         blank if you do not want to set any \
                                         moderators.")
                                         moderators.")
 
 
-    is_category = BooleanField("Is a category?",
-                               description="Categories are root-level parents \
-                                            for forums. They can not contain \
-                                            topics.")
-
     locked = BooleanField("Locked?", description="Disable new posts and topics \
     locked = BooleanField("Locked?", description="Disable new posts and topics \
                                                   in this forum.")
                                                   in this forum.")
 
 
-    def validate_parent(self, field):
-        if hasattr(field.data, "id"):
-            if field.data.id == self._id:
-                raise ValidationError("A forum cannot be it's own parent!")
-        else:
-            if not self.is_category.data:
-                raise ValidationError("Please choose a parent or is it a \
-                                      category?")
-
     def validate_moderators(self, field):
     def validate_moderators(self, field):
         if field.data:
         if field.data:
             # Check if the usernames exist
             # Check if the usernames exist
@@ -274,7 +264,7 @@ class ForumForm(Form):
                     raise ValidationError("User not found")
                     raise ValidationError("User not found")
             field.data = self._moderators
             field.data = self._moderators
 
 
-    def save(self, category_id=None):
+    def save(self):
         forum = Forum(title=self.title.data,
         forum = Forum(title=self.title.data,
                       description=self.description.data,
                       description=self.description.data,
                       position=self.position.data)
                       position=self.position.data)
@@ -282,10 +272,22 @@ class ForumForm(Form):
         if self.moderators.data and not self.is_category.data:
         if self.moderators.data and not self.is_category.data:
             forum.moderators = self.moderators.data
             forum.moderators = self.moderators.data
 
 
-        if self.is_category.data:
-            forum.is_category = True
-            forum.parent_id = None
-        else:
-            forum.parent_id = self.parent.data.id
+        forum.category_id = self.category.data.id
 
 
         return forum.save()
         return forum.save()
+
+
+class CategoryForm(Form):
+    title = TextField("Category title", validators=[
+        Required(message="Category title required")])
+
+    description = TextAreaField("Description", validators=[
+        Optional()],
+        description="You can format your description with BBCode.")
+
+    position = IntegerField("Position", default=1, validators=[
+        Required(message="Category position required")])
+
+    def save(self):
+        category = Category(**self.data)
+        return category.save()

+ 53 - 20
flaskbb/admin/views.py

@@ -19,7 +19,7 @@ from flaskbb.extensions import db
 from flaskbb.user.models import User, Group
 from flaskbb.user.models import User, Group
 from flaskbb.forum.models import Post, Topic, Forum, Category
 from flaskbb.forum.models import Post, Topic, Forum, Category
 from flaskbb.admin.forms import (AddUserForm, EditUserForm, AddGroupForm,
 from flaskbb.admin.forms import (AddUserForm, EditUserForm, AddGroupForm,
-                                 EditGroupForm, ForumForm)
+                                 EditGroupForm, ForumForm, CategoryForm)
 
 
 
 
 admin = Blueprint("admin", __name__)
 admin = Blueprint("admin", __name__)
@@ -115,7 +115,8 @@ def edit_user(user_id):
         form.primary_group.data = user.primary_group
         form.primary_group.data = user.primary_group
         form.secondary_groups.data = user.secondary_groups
         form.secondary_groups.data = user.secondary_groups
 
 
-    return render_template("admin/edit_user.html", form=form)
+    return render_template("admin/user_form.html", form=form,
+                           title="Edit User")
 
 
 
 
 @admin.route("/users/<int:user_id>/delete")
 @admin.route("/users/<int:user_id>/delete")
@@ -136,7 +137,8 @@ def add_user():
         flash("User successfully added.", "success")
         flash("User successfully added.", "success")
         return redirect(url_for("admin.users"))
         return redirect(url_for("admin.users"))
 
 
-    return render_template("admin/edit_user.html", form=form)
+    return render_template("admin/user_form.html", form=form,
+                           title="Add User")
 
 
 
 
 @admin.route("/groups/<int:group_id>/edit", methods=["GET", "POST"])
 @admin.route("/groups/<int:group_id>/edit", methods=["GET", "POST"])
@@ -165,7 +167,8 @@ def edit_group(group_id):
         form.posttopic.data = group.posttopic
         form.posttopic.data = group.posttopic
         form.postreply.data = group.postreply
         form.postreply.data = group.postreply
 
 
-    return render_template("admin/edit_group.html", form=form)
+    return render_template("admin/group_form.html", form=form,
+                           title="Edit Group")
 
 
 
 
 @admin.route("/groups/<int:group_id>/delete")
 @admin.route("/groups/<int:group_id>/delete")
@@ -186,7 +189,8 @@ def add_group():
         flash("Group successfully added.", "success")
         flash("Group successfully added.", "success")
         return redirect(url_for("admin.groups"))
         return redirect(url_for("admin.groups"))
 
 
-    return render_template("admin/edit_group.html", form=form)
+    return render_template("admin/group_form.html", form=form,
+                           title="Add Group")
 
 
 
 
 @admin.route("/forums/<int:forum_id>/edit", methods=["GET", "POST"])
 @admin.route("/forums/<int:forum_id>/edit", methods=["GET", "POST"])
@@ -201,17 +205,12 @@ def edit_forum(forum_id):
         forum.title = form.title.data
         forum.title = form.title.data
         forum.description = form.description.data
         forum.description = form.description.data
         forum.position = form.position.data
         forum.position = form.position.data
-        forum.is_category = form.is_category.data
         forum.locked = form.locked.data
         forum.locked = form.locked.data
+        forum.category_id = form.category.data.id
 
 
         if form.moderators.data:
         if form.moderators.data:
             forum.moderators = form.moderators.data
             forum.moderators = form.moderators.data
 
 
-        if hasattr(form.parent.data, 'id'):
-            forum.parent_id = form.parent.data.id
-        else:
-            forum.parent_id = form.parent.data
-
         forum.save()
         forum.save()
 
 
         flash("Forum successfully edited.", "success")
         flash("Forum successfully edited.", "success")
@@ -220,8 +219,7 @@ def edit_forum(forum_id):
         form.title.data = forum.title
         form.title.data = forum.title
         form.description.data = forum.description
         form.description.data = forum.description
         form.position.data = forum.position
         form.position.data = forum.position
-        form.parent.data = forum.parent
-        form.is_category.data = forum.is_category
+        form.category.data = forum.category
         form.locked.data = forum.locked
         form.locked.data = forum.locked
 
 
         if forum.moderators:
         if forum.moderators:
@@ -230,7 +228,8 @@ def edit_forum(forum_id):
         else:
         else:
             form.moderators.data = None
             form.moderators.data = None
 
 
-    return render_template("admin/edit_forum.html", form=form)
+    return render_template("admin/forum_form.html", form=form,
+                           title="Edit Forum")
 
 
 
 
 @admin.route("/forums/<int:forum_id>/delete")
 @admin.route("/forums/<int:forum_id>/delete")
@@ -248,29 +247,63 @@ def delete_forum(forum_id):
 
 
 
 
 @admin.route("/forums/add", methods=["GET", "POST"])
 @admin.route("/forums/add", methods=["GET", "POST"])
-@admin.route("/forums/<int:category_id>/add")
+@admin.route("/forums/<int:category_id>/add", methods=["GET", "POST"])
 @admin_required
 @admin_required
 def add_forum(category_id=None):
 def add_forum(category_id=None):
     form = ForumForm()
     form = ForumForm()
 
 
     if form.validate_on_submit():
     if form.validate_on_submit():
-        form.save(category_id)
+        form.save()
         flash("Forum successfully added.", "success")
         flash("Forum successfully added.", "success")
         return redirect(url_for("admin.forums"))
         return redirect(url_for("admin.forums"))
+    else:
+        if category_id:
+            category = Category.query.filter_by(id=category_id).first()
+            form.category.data = category
 
 
-    return render_template("admin/edit_forum.html", form=form)
+    return render_template("admin/forum_form.html", form=form,
+                           title="Add Forum")
 
 
 
 
 @admin.route("/category/add", methods=["GET", "POST"])
 @admin.route("/category/add", methods=["GET", "POST"])
 def add_category():
 def add_category():
-    pass
+    form = CategoryForm()
+
+    if form.validate_on_submit():
+        form.save()
+        flash("Category successfully created.", "success")
+        return redirect(url_for("admin.forums"))
+
+    return render_template("admin/category_form.html", form=form,
+                           title="Add Category")
 
 
 
 
 @admin.route("/category/<int:category_id>/edit", methods=["GET", "POST"])
 @admin.route("/category/<int:category_id>/edit", methods=["GET", "POST"])
 def edit_category(category_id):
 def edit_category(category_id):
-    pass
+    category = Category.query.filter_by(id=category_id).first_or_404()
+
+    form = CategoryForm()
+
+    if form.validate_on_submit():
+        form.populate_obj(category)
+        category.save()
+    else:
+        form.title.data = category.title
+        form.description.data = category.description
+        form.position.data = category.position
+
+    return render_template("admin/category_form.html", form=form,
+                           title="Edit Category")
 
 
 
 
 @admin.route("/category/<int:category_id>/delete", methods=["GET", "POST"])
 @admin.route("/category/<int:category_id>/delete", methods=["GET", "POST"])
 def delete_category(category_id):
 def delete_category(category_id):
-    pass
+    category = Category.query.filter_by(id=category_id).first_or_404()
+
+    involved_users = User.query.filter(Forum.category_id == category.id,
+                                       Topic.forum_id == Forum.id,
+                                       Post.user_id == User.id).all()
+
+    category.delete(involved_users)
+    flash("Category with all associated forums deleted.", "success")
+    return redirect(url_for("admin.forums"))

+ 16 - 14
flaskbb/forum/models.py

@@ -382,18 +382,10 @@ class Forum(db.Model):
         db.session.commit()
         db.session.commit()
 
 
         # Update the users post count
         # Update the users post count
-        # Need to import it from here, because otherwise it would be
-        # a circular import
-        from flaskbb.user.models import User
-
-        users = User.query.\
-            filter(Topic.forum_id == self.id,
-                   Post.topic_id == Topic.id).\
-            all()
-
-        for user in users:
-            user.post_count = Post.query.filter_by(user_id=user.id).count()
-            db.session.commit()
+        if users:
+            for user in users:
+                user.post_count = Post.query.filter_by(user_id=user.id).count()
+                db.session.commit()
 
 
         return self
         return self
 
 
@@ -418,13 +410,23 @@ class Category(db.Model):
         db.session.commit()
         db.session.commit()
         return self
         return self
 
 
-    def delete(self):
-        """Deletes a category"""
+    def delete(self, users=None):
+        """Deletes a category. If a list with involved user objects is passed,
+        it will also update their post counts
+
+        :param users: A list with user objects
+        """
 
 
         # Delete all the forums in the category
         # Delete all the forums in the category
         for forum in self.forums:
         for forum in self.forums:
             forum.delete()
             forum.delete()
 
 
+        # Update the users post count
+        if users:
+            for user in users:
+                user.post_count = Post.query.filter_by(user_id=user.id).count()
+                db.session.commit()
+
         # and finally delete the category itself
         # and finally delete the category itself
         db.session.delete(self)
         db.session.delete(self)
         db.session.commit()
         db.session.commit()

+ 23 - 0
flaskbb/templates/admin/category_form.html

@@ -0,0 +1,23 @@
+{% set page_title = title %}
+{% set active_forum_nav=True %}
+
+{% extends "admin/admin_layout.html" %}
+{% block admin_content %}
+{% from "macros.html" import horizontal_field, render_boolean_field %}
+
+<form class="form-horizontal" role="form" method="post">
+    {{ form.hidden_tag() }}
+    <legend class="">{{ title }}</legend>
+        {{ horizontal_field(form.title) }}
+        {{ horizontal_field(form.description, rows=5, div_class="col-lg-9") }}
+
+        {{ horizontal_field(form.position) }}
+
+        <div class="form-group">
+            <div class="col-lg-offset-0 col-lg-9">
+                <button type="submit" class="btn btn-success">Save</button>
+            </div>
+        </div>
+</form>
+
+{% endblock %}

+ 3 - 4
flaskbb/templates/admin/edit_forum.html → flaskbb/templates/admin/forum_form.html

@@ -1,4 +1,4 @@
-{% set page_title = "Edit Forum" %}
+{% set page_title = title %}
 {% set active_forum_nav=True %}
 {% set active_forum_nav=True %}
 
 
 {% extends "admin/admin_layout.html" %}
 {% extends "admin/admin_layout.html" %}
@@ -7,16 +7,15 @@
 
 
 <form class="form-horizontal" role="form" method="post">
 <form class="form-horizontal" role="form" method="post">
     {{ form.hidden_tag() }}
     {{ form.hidden_tag() }}
-    <legend class="">Edit Forum</legend>
+    <legend class="">{{ title }}</legend>
         {{ horizontal_field(form.title) }}
         {{ horizontal_field(form.title) }}
         {{ horizontal_field(form.description, rows=5, div_class="col-lg-9") }}
         {{ horizontal_field(form.description, rows=5, div_class="col-lg-9") }}
 
 
-        {{ horizontal_field(form.parent) }}
+        {{ horizontal_field(form.category) }}
         {{ horizontal_field(form.position) }}
         {{ horizontal_field(form.position) }}
 
 
         {{ horizontal_field(form.moderators) }}
         {{ horizontal_field(form.moderators) }}
 
 
-        {{ render_boolean_field(form.is_category) }}
         {{ render_boolean_field(form.locked) }}
         {{ render_boolean_field(form.locked) }}
 
 
         <div class="form-group">
         <div class="form-group">

+ 1 - 1
flaskbb/templates/admin/forums.html

@@ -12,7 +12,7 @@
                 <div><strong><a href="{{ url_for('forum.view_category', category_id=category.id) }}">{{ category.title }}</a></strong></div>
                 <div><strong><a href="{{ url_for('forum.view_category', category_id=category.id) }}">{{ category.title }}</a></strong></div>
             </td>
             </td>
             <td valign="top" align="center" style="white-space: nowrap">
             <td valign="top" align="center" style="white-space: nowrap">
-                <a href="{{ url_for('admin.add_forum', category_id = category.id) }}">Add Forum</a> |
+                <a href="{{ url_for('admin.add_forum', category_id=category.id) }}">Add Forum</a> |
                 <a href="{{ url_for('admin.edit_category', category_id = category.id) }}">Edit</a> |
                 <a href="{{ url_for('admin.edit_category', category_id = category.id) }}">Edit</a> |
                 <a href="{{ url_for('admin.delete_category', category_id = category.id) }}">Delete</a>
                 <a href="{{ url_for('admin.delete_category', category_id = category.id) }}">Delete</a>
             </td>
             </td>

+ 2 - 2
flaskbb/templates/admin/edit_group.html → flaskbb/templates/admin/group_form.html

@@ -1,4 +1,4 @@
-{% set page_title = "Edit Group" %}
+{% set page_title = title %}
 {% set active_forum_nav=True %}
 {% set active_forum_nav=True %}
 
 
 {% extends "admin/admin_layout.html" %}
 {% extends "admin/admin_layout.html" %}
@@ -7,7 +7,7 @@
 
 
 <form class="form-horizontal" role="form" method="post">
 <form class="form-horizontal" role="form" method="post">
     {{ form.hidden_tag() }}
     {{ form.hidden_tag() }}
-    <legend class="">Edit Group</legend>
+    <legend class="">{{ title }}</legend>
         {{ horizontal_field(form.name) }}
         {{ horizontal_field(form.name) }}
         {{ horizontal_field(form.description) }}
         {{ horizontal_field(form.description) }}
 
 

+ 2 - 2
flaskbb/templates/admin/edit_user.html → flaskbb/templates/admin/user_form.html

@@ -1,4 +1,4 @@
-{% set page_title = "Edit User" %}
+{% set page_title = title %}
 {% set active_forum_nav=True %}
 {% set active_forum_nav=True %}
 
 
 {% extends "admin/admin_layout.html" %}
 {% extends "admin/admin_layout.html" %}
@@ -7,7 +7,7 @@
 
 
 <form class="form-horizontal" role="form" method="post">
 <form class="form-horizontal" role="form" method="post">
     {{ form.hidden_tag() }}
     {{ form.hidden_tag() }}
-    <legend class="">Edit User</legend>
+    <legend class="">{{ title }}</legend>
         {{ horizontal_field(form.username) }}
         {{ horizontal_field(form.username) }}
         {{ horizontal_field(form.email) }}
         {{ horizontal_field(form.email) }}
         {{ horizontal_field(form.password) }}
         {{ horizontal_field(form.password) }}