aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/media_types
diff options
context:
space:
mode:
authorSebastian Spaeth <Sebastian@SSpaeth.de>2013-12-12 16:24:34 +0100
committerSebastian Spaeth <Sebastian@SSpaeth.de>2013-12-12 16:24:34 +0100
commita42dda21f96f5124d97011c318f068b92a4222b0 (patch)
tree13edbe92814c93a4b7cd01ff4ff1af779f3706a7 /mediagoblin/media_types
parent070bc99c1eaecb6b8ca3d5f5a38942491bb1ef37 (diff)
parentafff1492f89822d6c36fcad8b74953db2375cebf (diff)
downloadmediagoblin-a42dda21f96f5124d97011c318f068b92a4222b0.tar.lz
mediagoblin-a42dda21f96f5124d97011c318f068b92a4222b0.tar.xz
mediagoblin-a42dda21f96f5124d97011c318f068b92a4222b0.zip
Merge branch 'master' into upstream-master
Conflicts: mediagoblin/templates/mediagoblin/base.html mediagoblin/templates/mediagoblin/user_pages/user.html
Diffstat (limited to 'mediagoblin/media_types')
-rw-r--r--mediagoblin/media_types/blog/__init__.py121
-rw-r--r--mediagoblin/media_types/blog/config_spec.ini2
-rw-r--r--mediagoblin/media_types/blog/forms.py46
-rw-r--r--mediagoblin/media_types/blog/lib.py49
-rw-r--r--mediagoblin/media_types/blog/models.py79
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_about.html38
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_admin_dashboard.html110
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_confirm_delete.html53
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_edit_create.html41
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_edit_create.html53
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_listing.html66
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/blogpost_draft_view.html42
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/list_of_blogs.html69
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogging.html22
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogs_dashboard.html27
-rw-r--r--mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_create_blog.html22
-rw-r--r--mediagoblin/media_types/blog/views.py382
-rw-r--r--mediagoblin/media_types/image/__init__.py2
18 files changed, 1224 insertions, 0 deletions
diff --git a/mediagoblin/media_types/blog/__init__.py b/mediagoblin/media_types/blog/__init__.py
new file mode 100644
index 00000000..8a61c6e0
--- /dev/null
+++ b/mediagoblin/media_types/blog/__init__.py
@@ -0,0 +1,121 @@
+#GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import logging
+_log = logging.getLogger(__name__)
+
+from mediagoblin.media_types import MediaManagerBase
+from mediagoblin.media_types.blog.models import Blog, BlogPostData
+
+from mediagoblin.tools import pluginapi
+
+PLUGIN_DIR = os.path.dirname(__file__)
+MEDIA_TYPE = 'mediagoblin.media_types.blogpost'
+
+
+def setup_plugin():
+ config = pluginapi.get_config(MEDIA_TYPE)
+ _log.info("setting up blog media type plugin.")
+
+ routes = [
+ #blog_create
+ ('mediagoblin.media_types.blog.create',
+ '/u/<string:user>/b/create/',
+ 'mediagoblin.media_types.blog.views:blog_edit'
+ ),
+ #blog_edit
+ ('mediagoblin.media_types.blog.edit',
+ '/u/<string:user>/b/<string:blog_slug>/edit/',
+ 'mediagoblin.media_types.blog.views:blog_edit'
+ ),
+ #blog post create
+ ('mediagoblin.media_types.blog.blogpost.create',
+ '/u/<string:user>/b/<string:blog_slug>/p/create/',
+ 'mediagoblin.media_types.blog.views:blogpost_create'
+ ),
+ #blog post edit
+ ('mediagoblin.media_types.blog.blogpost.edit',
+ '/u/<string:user>/b/<string:blog_slug>/p/<string:blog_post_slug>/edit/',
+ 'mediagoblin.media_types.blog.views:blogpost_edit'
+ ),
+ #blog collection dashboard in case of multiple blogs
+ ('mediagoblin.media_types.blog.blog_admin_dashboard',
+ '/u/<string:user>/b/dashboard/',
+ 'mediagoblin.media_types.blog.views:blog_dashboard'
+ ),
+ #blog dashboard
+ ('mediagoblin.media_types.blog.blog-dashboard',
+ '/u/<string:user>/b/<string:blog_slug>/dashboard/',
+ 'mediagoblin.media_types.blog.views:blog_dashboard'
+ ),
+ #blog post listing view
+ ('mediagoblin.media_types.blog.blog_post_listing',
+ '/u/<string:user>/b/<string:blog_slug>/',
+ 'mediagoblin.media_types.blog.views:blog_post_listing'
+ ),
+ #blog post draft view
+ ('mediagoblin.media_types.blog.blogpost_draft_view',
+ '/u/<string:user>/b/<string:blog_slug>/p/<string:blog_post_slug>/draft/',
+ 'mediagoblin.media_types.blog.views:draft_view'
+ ),
+ #blog delete view
+ ('mediagoblin.media_types.blog.blog_delete',
+ '/u/<string:user>/b/<string:blog_slug>/delete/',
+ 'mediagoblin.media_types.blog.views:blog_delete'
+ ),
+ # blog about view
+ ('mediagoblin.media_types.blog.blog_about',
+ '/u/<string:user>/b/<string:blog_slug>/about/',
+ 'mediagoblin.media_types.blog.views:blog_about_view'
+ )]
+
+
+ pluginapi.register_routes(routes)
+ pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates'))
+ pluginapi.register_template_hooks({"user_profile": "mediagoblin/blog/url_to_blogs_dashboard.html",
+ "blog_dashboard_home": "mediagoblin/blog/url_to_blogging.html",
+ "create_blog_home": "mediagoblin/blog/url_to_create_blog.html",
+ })
+
+
+class BlogPostMediaManager(MediaManagerBase):
+ human_readable = "Blog Post"
+ display_template = "mediagoblin/media_displays/blogpost.html"
+ default_thumb = "images/media_thumbs/blogpost.jpg"
+
+ def get_blog_by_blogpost(self):
+ blog_post_data = BlogPostData.query.filter_by(media_entry=self.entry.id).first()
+ blog = Blog.query.filter_by(id=blog_post_data.blog).first()
+ return blog
+
+def add_to_user_home_context(context):
+ blogs = context['request'].db.Blog.query.filter_by(author=context['user'].id)
+
+ if blogs:
+ context['blogs'] = blogs
+ else:
+ context['blogs'] = None
+ return context
+
+
+hooks = {
+ 'setup': setup_plugin,
+ ('media_manager', MEDIA_TYPE): lambda: BlogPostMediaManager,
+ # Inject blog context on user profile page
+ ("mediagoblin.user_pages.user_home",
+ "mediagoblin/user_pages/user.html"): add_to_user_home_context
+}
diff --git a/mediagoblin/media_types/blog/config_spec.ini b/mediagoblin/media_types/blog/config_spec.ini
new file mode 100644
index 00000000..77038f47
--- /dev/null
+++ b/mediagoblin/media_types/blog/config_spec.ini
@@ -0,0 +1,2 @@
+[plugin_spec]
+max_blog_count = integer(default=4)
diff --git a/mediagoblin/media_types/blog/forms.py b/mediagoblin/media_types/blog/forms.py
new file mode 100644
index 00000000..1cc41a02
--- /dev/null
+++ b/mediagoblin/media_types/blog/forms.py
@@ -0,0 +1,46 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import wtforms
+
+from mediagoblin.tools.text import tag_length_validator, TOO_LONG_TAG_WARNING
+from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
+from mediagoblin.tools.licenses import licenses_as_choices
+
+class BlogPostEditForm(wtforms.Form):
+ title = wtforms.TextField(_('Title'),
+ [wtforms.validators.Length(min=0, max=500)])
+ description = wtforms.TextAreaField(_('Description'))
+ tags = wtforms.TextField(_('Tags'), [tag_length_validator],
+ description="Seperate tags by commas.")
+ license = wtforms.SelectField(_('License'),
+ [wtforms.validators.Optional(),], choices=licenses_as_choices())
+
+class BlogEditForm(wtforms.Form):
+ title = wtforms.TextField(_('Title'),
+ [wtforms.validators.Length(min=0, max=500)])
+ description = wtforms.TextAreaField(_('Description'))
+
+
+class ConfirmDeleteForm(wtforms.Form):
+ confirm = wtforms.BooleanField(
+ _('I am sure I want to delete this'))
+
+
+
+
+
+
diff --git a/mediagoblin/media_types/blog/lib.py b/mediagoblin/media_types/blog/lib.py
new file mode 100644
index 00000000..73ed6060
--- /dev/null
+++ b/mediagoblin/media_types/blog/lib.py
@@ -0,0 +1,49 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+def check_blog_slug_used(author_id, slug, ignore_b_id=None):
+ from mediagoblin.media_types.blog.models import Blog
+ query = Blog.query.filter_by(author=author_id, slug=slug)
+ if ignore_b_id:
+ query = query.filter(Blog.id != ignore_b_id)
+ does_exist = query.first() is not None
+ return does_exist
+
+def may_edit_blogpost(request, blog):
+ if request.user.is_admin or request.user.id == blog.author:
+ return True
+ return False
+
+def set_blogpost_state(request, blogpost):
+ if request.form['status'] == 'Publish':
+ blogpost.state = u'processed'
+ else:
+ blogpost.state = u'failed'
+
+def get_all_blogposts_of_blog(request, blog, state=None):
+ blog_posts_list = []
+ blog_post_data = request.db.BlogPostData.query.filter_by(blog=blog.id).all()
+ for each_blog_post_data in blog_post_data:
+ blog_post = each_blog_post_data.get_media_entry
+ if state == None:
+ blog_posts_list.append(blog_post)
+ if blog_post.state == state:
+ blog_posts_list.append(blog_post)
+ blog_posts_list.reverse()
+ return blog_posts_list
+
+
diff --git a/mediagoblin/media_types/blog/models.py b/mediagoblin/media_types/blog/models.py
new file mode 100644
index 00000000..7c55e359
--- /dev/null
+++ b/mediagoblin/media_types/blog/models.py
@@ -0,0 +1,79 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import datetime
+
+from mediagoblin.db.base import Base
+from mediagoblin.db.base import Session
+from mediagoblin.db.models import Collection, User, MediaEntry
+from mediagoblin.db.mixin import GenerateSlugMixin
+
+from mediagoblin.media_types.blog.lib import check_blog_slug_used
+
+from mediagoblin.tools.text import cleaned_markdown_conversion
+
+from sqlalchemy import (
+ Column, Integer, ForeignKey, Unicode, UnicodeText, DateTime)
+from sqlalchemy.orm import relationship, backref
+
+
+class BlogMixin(GenerateSlugMixin):
+ def check_slug_used(self, slug):
+ return check_blog_slug_used(self.author, slug, self.id)
+
+class Blog(Base, BlogMixin):
+ __tablename__ = "mediatype__blogs"
+ id = Column(Integer, primary_key=True)
+ title = Column(Unicode)
+ description = Column(UnicodeText)
+ author = Column(Integer, ForeignKey(User.id), nullable=False, index=True) #similar to uploader
+ created = Column(DateTime, nullable=False, default=datetime.datetime.now, index=True)
+ slug = Column(Unicode)
+
+
+ def get_all_blog_posts(self, state=None):
+ blog_posts = Session.query(MediaEntry).join(BlogPostData)\
+ .filter(BlogPostData.blog == self.id)
+ if state is not None:
+ blog_posts = blog_posts.filter(MediaEntry.state==state)
+ return blog_posts
+
+ def delete(self, **kwargs):
+ all_posts = self.get_all_blog_posts()
+ for post in all_posts:
+ post.delete(del_orphan_tags=False, commit=False)
+ from mediagoblin.db.util import clean_orphan_tags
+ clean_orphan_tags(commit=False)
+ super(Blog, self).delete(**kwargs)
+
+
+
+
+BACKREF_NAME = "blogpost__media_data"
+
+class BlogPostData(Base):
+ __tablename__ = "blogpost__mediadata"
+
+ # The primary key *and* reference to the main media_entry
+ media_entry = Column(Integer, ForeignKey('core__media_entries.id'), primary_key=True)
+ blog = Column(Integer, ForeignKey('mediatype__blogs.id'), nullable=False)
+ get_media_entry = relationship("MediaEntry",
+ backref=backref(BACKREF_NAME, uselist=False,
+ cascade="all, delete-orphan"))
+
+
+DATA_MODEL = BlogPostData
+MODELS = [BlogPostData, Blog]
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_about.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_about.html
new file mode 100644
index 00000000..ed2611d6
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_about.html
@@ -0,0 +1,38 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{% extends "mediagoblin/base.html" %}
+
+
+{% block mediagoblin_head%}
+<style type = "text/css">
+ h2 { font-weight: bold; text-transform:capitalize; }
+ #blogs_list {border-collapse:separate; border-spacing: 40px 0px ;}
+</style>
+{% endblock %}
+
+{% block mediagoblin_content %}
+ <h2> {{ blog.title }}</h2>
+ <br/>
+ <p> {{ blog.description|safe }}</p>
+ <br/>
+ <em>{{ blog.created.strftime("%d %b, %Y") }}</em>
+ &nbsp;
+ <em>posts({{ blogpost_count }})</em>
+{% endblock mediagoblin_content %}
+
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_admin_dashboard.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_admin_dashboard.html
new file mode 100644
index 00000000..1316083b
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_admin_dashboard.html
@@ -0,0 +1,110 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{% extends "mediagoblin/base.html" %}
+{% from "mediagoblin/utils/pagination.html" import render_pagination %}
+
+{% block title -%}
+{{blog.title}} Dashboard &mdash; {{ super() }}
+{%- endblock title %}
+
+{% block mediagoblin_head%}
+<style type = "text/css">
+ td > a { text-decoration:none; font-weight: bold; }
+</style>
+{% endblock %}
+
+
+{% block mediagoblin_content %}
+<h1 style="text-transform:capitalize"> {{blog.title}}</h1>
+<p>
+ {{blog.description|safe}}
+</p>
+<p>
+ {% set blogpost_create_url = request.urlgen('mediagoblin.media_types.blog.blogpost.create',
+ blog_slug=blog.slug,
+ user=request.user.username) %}
+<a class="button_action" href="{{ blogpost_create_url }}">
+{%- trans %}Add Blog Post{% endtrans -%}
+</a>
+&middot;
+ {% set blog_edit_url = request.urlgen('mediagoblin.media_types.blog.edit',
+ blog_slug=blog.slug,
+ user=request.user.username) %}
+<a class="button_action" href="{{ blog_edit_url }}">
+{%- trans %}Edit Blog{% endtrans -%}
+</a>
+&middot;
+ {% set blog_delete_url = request.urlgen('mediagoblin.media_types.blog.blog_delete',
+ blog_slug=blog.slug,
+ user=request.user.username) %}
+<a class="button_action" href="{{ blog_delete_url }}">
+{%- trans %}Delete Blog{% endtrans -%}
+</a>
+</p>
+<h2> Blog Post Entries </h2>
+ {% if blog_posts_list.count() %}
+ <table class="media_panel processing">
+ <tr>
+ <th>Title</th>
+ <th>submitted</th>
+ <th></th>
+ </tr>
+ {% for blog_post in blog_posts_list %}
+ <tr>
+ {% if blog_post.state == 'processed' %}
+ <td><a href="{{ blog_post.url_for_self(request.urlgen) }}">{{ blog_post.title }}</a></td>
+ {% else %}
+ {% set draft_url = request.urlgen('mediagoblin.media_types.blog.blogpost_draft_view',
+ blog_slug=blog.slug, user=request.user.username,
+ blog_post_slug=blog_post.slug) %}
+ <td><a href="{{ draft_url }}">{{ blog_post.title }}</a></td>
+ {% endif %}
+ <td>{{ blog_post.created.strftime("%F %R") }}</td>
+
+ {% if blog_post.state == 'processed' %}
+ <td><h6><em>Published</em></h6></td>
+ {% else %}
+ <td><h6><em>Draft</em></h6></td>
+ {% endif %}
+ {% set blogpost_edit_url = request.urlgen('mediagoblin.media_types.blog.blogpost.edit',
+ blog_slug=blog.slug, user=request.user.username,
+ blog_post_slug=blog_post.slug) %}
+ {% set blogpost_delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete',
+ user= blog_post.get_uploader.username,
+ media_id=blog_post.id) %}
+ <td>
+ <a class="button_action" href="{{ blogpost_edit_url }}">{% trans %}Edit{% endtrans %}</a>
+ <a class="button_action" href="{{ blogpost_delete_url }}">{% trans %}Delete{% endtrans %}</a>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ {% set blogpost_listing_url = request.urlgen('mediagoblin.media_types.blog.blog_post_listing',
+ blog_slug=blog_slug, user=user.username) %}
+ <br/>
+ <br/>
+ <a href="{{ blogpost_listing_url}}">{% trans %}<em> Go to list view </em>{% endtrans %}</a>
+ {% else %}
+ {% trans %} No blog post yet. {% endtrans %}
+ {% endif %}
+ {{ render_pagination(request, pagination) }}
+{% endblock %}
+
+
+
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_confirm_delete.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_confirm_delete.html
new file mode 100644
index 00000000..f98764be
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_confirm_delete.html
@@ -0,0 +1,53 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_content %}
+
+ <form action="{{ request.urlgen('mediagoblin.media_types.blog.blog_delete',
+ user=request.user.username,
+ blog_slug=blog.slug) }}"
+ method="POST" enctype="multipart/form-data">
+ <div class="form_box">
+ <h1>
+ {%- trans title=blog.title -%}
+ Really delete {{ title }}?
+ {%- endtrans %}
+ </h1>
+
+ <br/>
+
+ <p class="delete_checkbox_box">
+ {{ form.confirm }}
+ {{ wtforms_util.render_label(form.confirm) }}
+ </p>
+
+ <div class="form_submit_buttons">
+ {# TODO: This isn't a button really... might do unexpected things :) #}
+ {% set blog_dashboard_url = request.urlgen('mediagoblin.media_types.blog.blog-dashboard',
+ blog_slug=blog.slug, user=request.user.username) %}
+
+ <a class="button_action" href="{{ blog_dashboard_url }}">{% trans %}Cancel{% endtrans %}</a>
+ <input type="submit" value="{% trans %}Delete permanently{% endtrans %}" class="button_form" />
+ {{ csrf_token }}
+ </div>
+ </div>
+ </form>
+{% endblock %}
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_edit_create.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_edit_create.html
new file mode 100644
index 00000000..f4bbcb8f
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_edit_create.html
@@ -0,0 +1,41 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_content %}
+ <form action=""
+ method="POST" enctype="multipart/form-data">
+ <div class="blog_form_box_xl">
+ <h1>{% trans %}Create/Edit a Blog{% endtrans %}</h1>
+ <b>Title</b>
+ <div class="blog_form_field_input input">
+ <h3>{{ form.title}}</h3>
+ </div>
+ <b>Description</b>
+ <div class="blog_form_field_input textarea">
+ <h3>{{form.description|safe}}</h3>
+ </div>
+ <div class="form_submit_buttons">
+ {{ csrf_token }}
+ <input type="submit" value="{% trans %}Add{% endtrans %}" class="button_form" />
+ </div>
+ </div>
+ </form>
+{% endblock %}
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_edit_create.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_edit_create.html
new file mode 100644
index 00000000..e1f6ed90
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_edit_create.html
@@ -0,0 +1,53 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block title -%}
+ {% trans %}Create/Edit a blog post.{% endtrans %} &mdash; {{ super() }}
+{%- endblock %}
+
+{% block mediagoblin_content %}
+ <form action="" method="POST">
+ <div class="blog_form_box_xl">
+ <h1>{% trans %}Create/Edit a Blog Post.{% endtrans %}</h1>
+ <b>Title</b>
+ <div class="blog_form_field_input input">
+ <h3>{{ form.title}}</h3>
+ </div>
+ <b>Description</b>
+ <div class="blog_form_field_input textarea">
+ <h3>{{form.description|safe}}</h3>
+ </div>
+ <b>Tags</b>
+ <div class="blog_form_field_input input">
+ <h3>{{form.tags}}</h3>
+ </div>
+ <b>License</b>
+ <div class="blog_form_field_input input">
+ <h3>{{form.license}}</h3>
+ </div>
+ <div class="form_submit_buttons">
+ {{ csrf_token }}
+ <input type="submit" name="status" value="Publish" class="button_form">
+ <input type="submit" name="status" value="Save as Draft" class="button_form">
+ </div>
+ </div>
+ </form>
+{% endblock %}
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_listing.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_listing.html
new file mode 100644
index 00000000..3ec84006
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blog_post_listing.html
@@ -0,0 +1,66 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+{% from "mediagoblin/utils/pagination.html" import render_pagination %}
+
+{% block title -%}
+ {% trans %}{{ blog_owner }} 's Blog{% endtrans %} &mdash; {{ super() }}
+{%- endblock %}
+
+{% block mediagoblin_head -%}
+ <style type="text/css">
+ h4 {margin:0; padding : 0;
+ font-size:.7 em;}
+ a{text-decoration:none;
+ text-transform:capitalize
+ }
+
+ </style>
+{%- endblock %}
+
+{% block mediagoblin_content %}
+ <div class="b_list_owner"> <h1><font color="black"> {{ blog.title }} <font size="2">by {{ blog_owner }}</font> </font></h1></div>
+ <div>
+ {% for post in blog_posts %}
+ <div class="b_listing_title"><a href="{{ post.url_for_self(request.urlgen) }}">
+ <h2><font color="black">{{ post.title }}</font></h2></a>
+ </div>
+ <h4 align="right">{{ post.created.strftime("%d %b, %Y") }}</h4>
+ {% if post.tags %}
+ {% for tag in post.tags %}
+ <a href="{{ request.urlgen(
+ 'mediagoblin.user_pages.user_tag_gallery',
+ tag=tag['slug'],
+ user=post.get_uploader.username) }}">{{ tag['name'] }} |</a>
+ {% endfor %}
+ {% endif %}
+ <div class="b_list_des"> <p>{{ post.description|safe }} </p></div>
+ </br>
+ </br>
+ {% endfor %}
+ </div>
+ <br/>
+ <br/>
+ {% set blog_about_url = request.urlgen('mediagoblin.media_types.blog.blog_about',
+ blog_slug=blog.slug, user=blog_owner) %}
+ <a style="text-decoration:underline" href="{{ blog_about_url}}">About Blog</a>
+ <br/>
+ {{ render_pagination(request, pagination) }}
+{% endblock %}
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/blogpost_draft_view.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blogpost_draft_view.html
new file mode 100644
index 00000000..7c634877
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/blogpost_draft_view.html
@@ -0,0 +1,42 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{% extends 'mediagoblin/base.html' %}
+
+{% block mediagoblin_head %}
+ {{ super() }}
+{% endblock %}
+
+{% block mediagoblin_content %}
+<h1> {{ blogpost.title}}</h1>
+<p>{{ blogpost.description|safe}}</p>
+
+{% set blogpost_edit_url = request.urlgen('mediagoblin.media_types.blog.blogpost.edit',
+ blog_slug=blog.slug, user=request.user.username,
+ blog_post_slug=blogpost.slug) %}
+{% set blogpost_delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete',
+ user= blogpost.get_uploader.username,
+ media_id=blogpost.id) %}
+ <a class="button_action" href="{{ blogpost_edit_url }}">{% trans %}Edit{% endtrans %}</a>
+ <a class="button_action" href="{{ blogpost_delete_url }}">{% trans %}Delete{% endtrans %}</a>
+
+{% endblock %}
+
+
+
+
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/list_of_blogs.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/list_of_blogs.html
new file mode 100644
index 00000000..f19a9225
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/list_of_blogs.html
@@ -0,0 +1,69 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{% extends "mediagoblin/base.html" %}
+
+
+{% block mediagoblin_head%}
+<style type = "text/css">
+ table a { text-decoration:none; font-weight: bold; text-transform:capitalize; }
+ #blogs_list {border-collapse:separate; border-spacing: 40px 0px ;}
+</style>
+{% endblock %}
+
+{% block mediagoblin_content %}
+ {% if blogs %}
+ <h2>My Blogs</h2>
+ <table id="blogs_list">
+ {% for blog in blogs %}
+ {% set others_blog_url = request.urlgen('mediagoblin.media_types.blog.blog_post_listing',
+ blog_slug=blog.slug, user=user.username) %}
+
+ <tr>
+ {% if not request.user or request.user.username != user.username%}
+ <td><a href="{{ others_blog_url }}">{{ blog.title }}</a></td>
+ {% else %}
+ {% set my_blog_url = request.urlgen('mediagoblin.media_types.blog.blog-dashboard',
+ blog_slug=blog.slug, user=request.user.username) %}
+ <td><a href="{{ my_blog_url }}">{{ blog.title }}</a></td>
+ {% endif %}
+ <td>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</td>
+ <td><a class="button_action" href="{{ others_blog_url }}">{% trans %}View{% endtrans %}</a></td>
+ </tr>
+ {% endfor %}
+ </table>
+ {% else %}
+
+ {% if request.user and request.user.username==user.username %}
+ <p>You have not created any blog yet.</p>
+ {% else %}
+ <p>No blog has been created by <strong>{{ user.username }}</strong>yet.</p>
+ {% endif %}
+ {% endif %}
+ <br/>
+ <br/>
+ <br/>
+ {% if blogs.__len__() <max_blog_count and request.user and request.user.username==user.username %}
+ {% set blog_create_url = request.urlgen('mediagoblin.media_types.blog.create',
+ user=request.user.username) %}
+
+ <a class="button_action" href="{{ blog_create_url }}">{% trans %}Create a Blog{% endtrans %}</a>
+ {% endif %}
+
+{% endblock mediagoblin_content %}
+
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogging.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogging.html
new file mode 100644
index 00000000..bf688b0f
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogging.html
@@ -0,0 +1,22 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+ <a href="{{ request.urlgen('mediagoblin.media_types.blog.blog_admin_dashboard',
+ user=request.user.username) }}">
+ {%- trans %} Blog Dashboard {% endtrans -%}
+ </a>
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogs_dashboard.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogs_dashboard.html
new file mode 100644
index 00000000..483c1455
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_blogs_dashboard.html
@@ -0,0 +1,27 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{#This injects the URL to a user's blog dashboard on her profile.
+#}
+{%if blogs %}
+<h3>Blog</h3>
+{% set blogs_url = request.urlgen('mediagoblin.media_types.blog.blog_admin_dashboard',
+ blogs=blogs, user=user.username) %}
+
+<p><a href="{{ blogs_url }}"><em>Go to blogs</em></a></p>
+{%endif%}
diff --git a/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_create_blog.html b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_create_blog.html
new file mode 100644
index 00000000..d7d33adb
--- /dev/null
+++ b/mediagoblin/media_types/blog/templates/mediagoblin/blog/url_to_create_blog.html
@@ -0,0 +1,22 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+ <a class="button_action" href="{{ request.urlgen('mediagoblin.media_types.blog.create',
+ user=request.user.username) }}">
+ {%- trans %} Create Blog {% endtrans -%}
+ </a>
+
diff --git a/mediagoblin/media_types/blog/views.py b/mediagoblin/media_types/blog/views.py
new file mode 100644
index 00000000..b8e1d845
--- /dev/null
+++ b/mediagoblin/media_types/blog/views.py
@@ -0,0 +1,382 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import logging
+_log = logging.getLogger(__name__)
+
+from datetime import datetime
+
+from werkzeug.exceptions import Forbidden
+from mediagoblin.tools import pluginapi
+
+from mediagoblin import mg_globals
+
+from mediagoblin.media_types.blog import forms as blog_forms
+from mediagoblin.media_types.blog.models import Blog, BlogPostData
+from mediagoblin.media_types.blog.lib import may_edit_blogpost, set_blogpost_state, get_all_blogposts_of_blog
+
+from mediagoblin.messages import add_message, SUCCESS, ERROR
+from mediagoblin.decorators import (require_active_login, active_user_from_url,
+ get_media_entry_by_id, user_may_alter_collection,
+ get_user_collection, uses_pagination)
+from mediagoblin.tools.pagination import Pagination
+from mediagoblin.tools.response import (render_to_response,
+ redirect, render_404)
+from mediagoblin.tools.translate import pass_to_ugettext as _
+from mediagoblin.tools.template import render_template
+from mediagoblin.tools.text import (
+ convert_to_tag_list_of_dicts, media_tags_as_string, clean_html,
+ cleaned_markdown_conversion)
+
+from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used
+from mediagoblin.db.models import User, Collection, MediaEntry
+
+from mediagoblin.notifications import add_comment_subscription
+
+
+@require_active_login
+def blog_edit(request):
+ """
+ View for editing an existing blog or creating a new blog
+ if user have not exceeded maximum allowed acount of blogs.
+ """
+ url_user = request.matchdict.get('user', None)
+ blog_slug = request.matchdict.get('blog_slug', None)
+
+ config = pluginapi.get_config('mediagoblin.media_types.blog')
+ max_blog_count = config['max_blog_count']
+ form = blog_forms.BlogEditForm(request.form)
+ # creating a blog
+ if not blog_slug:
+ if Blog.query.filter_by(author=request.user.id).count()<max_blog_count:
+ if request.method=='GET':
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blog_edit_create.html',
+ {'form': form,
+ 'user' : request.user,
+ 'app_config': mg_globals.app_config})
+
+ if request.method=='POST' and form.validate():
+ _log.info("Here")
+ blog = request.db.Blog()
+ blog.title = unicode(form.title.data)
+ blog.description = unicode(cleaned_markdown_conversion((form.description.data)))
+ blog.author = request.user.id
+ blog.generate_slug()
+
+ blog.save()
+ return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
+ user=request.user.username
+ )
+ else:
+ add_message(request, ERROR, "Welcome! You already have created \
+ maximum number of blogs.")
+ return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
+ user=request.user.username)
+
+
+ #Blog already exists.
+ else:
+ blog = request.db.Blog.query.filter_by(slug=blog_slug).first()
+ if not blog:
+ return render_404(request)
+ if request.method == 'GET':
+ defaults = dict(
+ title = blog.title,
+ description = cleaned_markdown_conversion(blog.description),
+ author = request.user.id)
+
+ form = blog_forms.BlogEditForm(**defaults)
+
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blog_edit_create.html',
+ {'form': form,
+ 'user': request.user,
+ 'app_config': mg_globals.app_config})
+ else:
+ if request.method == 'POST' and form.validate():
+ blog.title = unicode(form.title.data)
+ blog.description = unicode(cleaned_markdown_conversion((form.description.data)))
+ blog.author = request.user.id
+ blog.generate_slug()
+
+ blog.save()
+ add_message(request, SUCCESS, "Your blog is updated.")
+ return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
+ user=request.user.username,
+ blog_slug=blog.slug)
+
+
+@require_active_login
+def blogpost_create(request):
+
+ form = blog_forms.BlogPostEditForm(request.form, license=request.user.license_preference)
+
+ if request.method == 'POST' and form.validate():
+ blog_slug = request.matchdict.get('blog_slug')
+ blog = request.db.Blog.query.filter_by(slug=blog_slug,
+ author=request.user.id).first()
+ if not blog:
+ return render_404(request)
+
+ blogpost = request.db.MediaEntry()
+ blogpost.media_type = 'mediagoblin.media_types.blogpost'
+ blogpost.title = unicode(form.title.data)
+ blogpost.description = unicode(cleaned_markdown_conversion((form.description.data)))
+ blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data)
+ blogpost.license = unicode(form.license.data) or None
+ blogpost.uploader = request.user.id
+ blogpost.generate_slug()
+
+ set_blogpost_state(request, blogpost)
+ blogpost.save()
+
+ # connect this blogpost to its blog
+ blog_post_data = request.db.BlogPostData()
+ blog_post_data.blog = blog.id
+ blog_post_data.media_entry = blogpost.id
+ blog_post_data.save()
+
+ add_message(request, SUCCESS, _('Woohoo! Submitted!'))
+ add_comment_subscription(request.user, blogpost)
+ return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
+ user=request.user.username,
+ blog_slug=blog.slug)
+
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blog_post_edit_create.html',
+ {'form': form,
+ 'app_config': mg_globals.app_config,
+ 'user': request.user.username})
+
+
+@require_active_login
+def blogpost_edit(request):
+
+ blog_slug = request.matchdict.get('blog_slug', None)
+ blog_post_slug = request.matchdict.get('blog_post_slug', None)
+
+ blogpost = request.db.MediaEntry.query.filter_by(slug=blog_post_slug, uploader=request.user.id).first()
+ blog = request.db.Blog.query.filter_by(slug=blog_slug, author=request.user.id).first()
+
+ if not blogpost or not blog:
+ return render_404(request)
+
+ defaults = dict(
+ title = blogpost.title,
+ description = cleaned_markdown_conversion(blogpost.description),
+ tags=media_tags_as_string(blogpost.tags),
+ license=blogpost.license)
+
+ form = blog_forms.BlogPostEditForm(request.form, **defaults)
+ if request.method == 'POST' and form.validate():
+ blogpost.title = unicode(form.title.data)
+ blogpost.description = unicode(cleaned_markdown_conversion((form.description.data)))
+ blogpost.tags = convert_to_tag_list_of_dicts(form.tags.data)
+ blogpost.license = unicode(form.license.data)
+ set_blogpost_state(request, blogpost)
+ blogpost.generate_slug()
+ blogpost.save()
+
+ add_message(request, SUCCESS, _('Woohoo! edited blogpost is submitted'))
+ return redirect(request, "mediagoblin.media_types.blog.blog-dashboard",
+ user=request.user.username,
+ blog_slug=blog.slug)
+
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blog_post_edit_create.html',
+ {'form': form,
+ 'app_config': mg_globals.app_config,
+ 'user': request.user.username,
+ 'blog_post_slug': blog_post_slug
+ })
+
+
+@uses_pagination
+def blog_dashboard(request, page):
+ """
+ Dashboard for a blog, only accessible to
+ the owner of the blog.
+ """
+ url_user = request.matchdict.get('user')
+ user = request.db.User.query.filter_by(username=url_user).one()
+ blog_slug = request.matchdict.get('blog_slug', None)
+ blogs = request.db.Blog.query.filter_by(author=user.id)
+ config = pluginapi.get_config('mediagoblin.media_types.blog')
+ max_blog_count = config['max_blog_count']
+ if (request.user and request.user.id == user.id) or (request.user and request.user.is_admin):
+ if blog_slug:
+ blog = blogs.filter(Blog.slug==blog_slug).first()
+ if not blog:
+ return render_404(request)
+ else:
+ blog_posts_list = blog.get_all_blog_posts().order_by(MediaEntry.created.desc())
+ pagination = Pagination(page, blog_posts_list)
+ pagination.per_page = 15
+ blog_posts_on_a_page = pagination()
+ if may_edit_blogpost(request, blog):
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blog_admin_dashboard.html',
+ {'blog_posts_list': blog_posts_on_a_page,
+ 'blog_slug':blog_slug,
+ 'blog':blog,
+ 'user':user,
+ 'pagination':pagination
+ })
+ if not request.user or request.user.id != user.id or not blog_slug:
+ blogs = blogs.all()
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/list_of_blogs.html',
+ {
+ 'blogs':blogs,
+ 'user':user,
+ 'max_blog_count':max_blog_count
+ })
+
+
+@uses_pagination
+def blog_post_listing(request, page):
+ """
+ Page, listing all the blog posts of a particular blog.
+ """
+ blog_owner = request.matchdict.get('user')
+ blog_slug = request.matchdict.get('blog_slug', None)
+ owner_user = User.query.filter_by(username=blog_owner).one()
+ blog = request.db.Blog.query.filter_by(slug=blog_slug).first()
+
+ if not owner_user or not blog:
+ return render_404(request)
+
+ all_blog_posts = blog.get_all_blog_posts(u'processed').order_by(MediaEntry.created.desc())
+ pagination = Pagination(page, all_blog_posts)
+ pagination.per_page = 8
+ blog_posts_on_a_page = pagination()
+
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blog_post_listing.html',
+ {'blog_posts': blog_posts_on_a_page,
+ 'pagination': pagination,
+ 'blog_owner': blog_owner,
+ 'blog':blog
+ })
+
+
+@require_active_login
+def draft_view(request):
+
+ blog_slug = request.matchdict.get('blog_slug', None)
+ blog_post_slug = request.matchdict.get('blog_post_slug', None)
+ user = request.matchdict.get('user')
+
+ blog = request.db.Blog.query.filter_by(author=request.user.id, slug=blog_slug).first()
+ blogpost = request.db.MediaEntry.query.filter_by(state = u'failed', uploader=request.user.id, slug=blog_post_slug).first()
+
+ if not blog or not blogpost:
+ return render_404(request)
+
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blogpost_draft_view.html',
+ {'blogpost':blogpost,
+ 'blog': blog
+ })
+
+
+@require_active_login
+def blog_delete(request, **kwargs):
+ """
+ Deletes a blog and media entries, tags associated with it.
+ """
+ url_user = request.matchdict.get('user')
+ owner_user = request.db.User.query.filter_by(username=url_user).first()
+
+ blog_slug = request.matchdict.get('blog_slug', None)
+ blog = request.db.Blog.query.filter_by(slug=blog_slug, author=owner_user.id).first()
+ if not blog:
+ return render_404(reequest)
+
+ form = blog_forms.ConfirmDeleteForm(request.form)
+ if request.user.id == blog.author or request.user.is_admin:
+ if request.method == 'POST' and form.validate():
+ if form.confirm.data is True:
+ blog.delete()
+ add_message(
+ request, SUCCESS, _('You deleted the Blog.'))
+ return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
+ user=request.user.username)
+ else:
+ add_message(
+ request, ERROR,
+ _("The media was not deleted because you didn't check that you were sure."))
+ return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
+ user=request.user.username)
+ else:
+ if request.user.is_admin:
+ add_message(
+ request, WARNING,
+ _("You are about to delete another user's Blog. "
+ "Proceed with caution."))
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blog_confirm_delete.html',
+ {'blog':blog,
+ 'form':form
+ })
+ else:
+ add_message(
+ request, ERROR,
+ _("The blog was not deleted because you have no rights."))
+ return redirect(request, "mediagoblin.media_types.blog.blog_admin_dashboard",
+ user=request.user.username)
+
+
+def blog_about_view(request):
+ """
+ Page containing blog description and statistics
+ """
+ blog_slug = request.matchdict.get('blog_slug', None)
+ url_user = request.matchdict.get('user', None)
+
+ user = request.db.User.query.filter_by(username=url_user).first()
+ blog = request.db.Blog.query.filter_by(author=user.id, slug=blog_slug).first()
+
+ if not user or not blog:
+ return render_404(request)
+
+ else:
+ blog_posts_processed = blog.get_all_blog_posts(u'processed').count()
+ return render_to_response(
+ request,
+ 'mediagoblin/blog/blog_about.html',
+ {'user': user,
+ 'blog': blog,
+ 'blogpost_count': blog_posts_processed
+ })
+
+
+
+
+
+
+
+
diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py
index 06e0f08f..f5b49f01 100644
--- a/mediagoblin/media_types/image/__init__.py
+++ b/mediagoblin/media_types/image/__init__.py
@@ -27,6 +27,8 @@ _log = logging.getLogger(__name__)
ACCEPTED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "tiff"]
MEDIA_TYPE = 'mediagoblin.media_types.image'
+def setup_plugin():
+ config = pluginapi.get_config(MEDIA_TYPE)
class ImageMediaManager(MediaManagerBase):
human_readable = "Image"