changeset 1582:895436f44f93

merged
author Jaiditya Mathur <jaiditya.mathur@gmail.com>
date Fri, 27 Jul 2012 19:08:35 +0530
parents 613b370aa79f (current diff) 90d02867e144 (diff)
children f9d787239c02
files MoinMoin/templates/layout.html MoinMoin/themes/modernized/static/css/common.css
diffstat 10 files changed, 214 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/apps/frontend/views.py	Fri Jul 27 19:06:29 2012 +0530
+++ b/MoinMoin/apps/frontend/views.py	Fri Jul 27 19:08:35 2012 +0530
@@ -466,6 +466,67 @@
     return item.do_modify(contenttype, template_name)
 
 
+@frontend.route('/+blog/+<rev>/<itemname:item_name>', methods=['GET'])
+@frontend.route('/+blog/<itemname:item_name>', defaults=dict(rev=CURRENT), methods=['GET'])
+def show_blog(item_name, rev):
+    """
+    Show a blog item and a list of blog entries below it.
+
+    If supertag GET-parameter is defined, the list of blog entries consist only
+    of those entries that contain the supertag value in their lists of tags.
+    """
+    supertag = request.values.get('supertag')
+    flaskg.user.add_trail(item_name)
+    try:
+        item = Item.create(item_name, rev_id=rev)
+    except AccessDenied:
+        abort(403)
+    if isinstance(item, NonExistent):
+        abort(404, item_name)
+    # TODO: move to BlogItem class
+    prefix = item_name + u'/'
+    current_timestamp = int(time.time())
+    terms = [Term(WIKINAME, app.cfg.interwikiname),
+             # Only sub items of this item
+             Prefix(NAME_EXACT, prefix),
+             # Filter out those items that do not have a PTIME meta or PTIME is in the future.
+             DateRange(PTIME, start=None, end=datetime.utcfromtimestamp(current_timestamp)),
+            ]
+    if supertag:
+        terms.append(Term(TAGS, supertag))
+    query = And(terms)
+    revs = flaskg.storage.search(query, sortedby=[PTIME], reverse=True, limit=None)
+    blog_entry_items = [Item.create(rev.meta[NAME], rev_id=rev.revid) for rev in revs]
+    return render_template('blog.html',
+                           item_name=item.name,
+                           blog_item=item,
+                           blog_entry_items=blog_entry_items,
+                           supertag=supertag,
+                          )
+
+@frontend.route('/+blog_entry/+<rev>/<itemname:item_name>', methods=['GET'])
+@frontend.route('/+blog_entry/<itemname:item_name>', defaults=dict(rev=CURRENT), methods=['GET'])
+def show_blog_entry(item_name, rev):
+    flaskg.user.add_trail(item_name)
+    blog_item_name = item_name.rsplit('/', 1)[0]
+    if blog_item_name == item_name:
+        abort(403)
+    try:
+        item = Item.create(item_name, rev_id=rev)
+        blog_item = Item.create(blog_item_name)
+    except AccessDenied:
+        abort(403)
+    if isinstance(item, NonExistent):
+        abort(404, item_name)
+    if isinstance(blog_item, NonExistent):
+        abort(404, blog_item_name)
+    return render_template('blog_entry.html',
+                           item_name=item.name,
+                           blog_item=blog_item,
+                           blog_entry_item=item,
+                          )
+
+
 class TargetChangeForm(BaseChangeForm):
     target = RequiredText.using(label=L_('Target')).with_properties(placeholder=L_("The name of the target item"))
 
--- a/MoinMoin/constants/keys.py	Fri Jul 27 19:06:29 2012 +0530
+++ b/MoinMoin/constants/keys.py	Fri Jul 27 19:08:35 2012 +0530
@@ -81,6 +81,12 @@
 RESULTS_PER_PAGE = "results_per_page"
 DISABLED = "disabled"
 
+# keys for blog homepages
+LOGO = u"logo"
+SUPERTAGS = u"supertags"
+# keys for blog entries
+PTIME = u"ptime"
+
 # index names
 LATEST_REVS = 'latest_revs'
 ALL_REVS = 'all_revs'
--- a/MoinMoin/converter/macro.py	Fri Jul 27 19:06:29 2012 +0530
+++ b/MoinMoin/converter/macro.py	Fri Jul 27 19:08:35 2012 +0530
@@ -85,7 +85,7 @@
             # and makes the wiki UI unusable (by emitting a Server Error),
             # thus, in case of exceptions, we just log the problem and return
             # some standard text.
-            logger.exception("Macro {0} raised an exception:".format(name))
+            logging.exception("Macro {0} raised an exception:".format(name))
             elem_error.append(_('<<%(macro_name)s: execution failed [%(error_msg)s] (see also the log)>>',
                     macro_name=name,
                     error_msg=unicode(e),
--- a/MoinMoin/forms.py	Fri Jul 27 19:06:29 2012 +0530
+++ b/MoinMoin/forms.py	Fri Jul 27 19:08:35 2012 +0530
@@ -8,10 +8,9 @@
 """
 
 
-from functools import reduce
-from operator import add
+import re
 
-from flatland import Element, Form, String, Integer, Boolean, Enum, MultiValue, Dict
+from flatland import Element, Form, String, Integer, Boolean, Enum, Dict, JoinedString
 from flatland.validation import Validator, Present, IsEmail, ValueBetween, URLValidator, Converted, ValueAtLeast
 
 from MoinMoin.constants.forms import *
@@ -53,7 +52,7 @@
 Select = Enum.with_properties(widget=WIDGET_SELECT)
 
 # XXX Need a better one than plain text box
-Tags = MultiValue.of(String).with_properties(widget=WIDGET_TEXT).using(label=L_('Tags'), optional=True)
+Tags = JoinedString.of(String).with_properties(widget=WIDGET_TEXT).using(label=L_('Tags'), optional=True, separator=', ', separator_regex=re.compile(r'\s*,\s*'))
 
 Search = Text.using(default=u'', optional=True).with_properties(widget=WIDGET_SEARCH, placeholder=L_("Search Query"))
 
--- a/MoinMoin/storage/middleware/indexing.py	Fri Jul 27 19:06:29 2012 +0530
+++ b/MoinMoin/storage/middleware/indexing.py	Fri Jul 27 19:08:35 2012 +0530
@@ -78,6 +78,7 @@
                             LANGUAGE, USERID, ADDRESS, HOSTNAME, SIZE, ACTION, COMMENT, SUMMARY, \
                             CONTENT, EXTERNALLINKS, ITEMLINKS, ITEMTRANSCLUSIONS, ACL, EMAIL, OPENID, \
                             ITEMID, REVID, CURRENT, PARENTID, \
+                            PTIME, \
                             LATEST_REVS, ALL_REVS, \
                             CONTENTTYPE_USER
 from MoinMoin.constants import keys
@@ -106,9 +107,10 @@
     doc = dict([(str(key), value)
                 for key, value in meta.items()
                 if key in schema])
-    if MTIME in doc:
-        # we have UNIX UTC timestamp (int), whoosh wants datetime
-        doc[MTIME] = datetime.datetime.utcfromtimestamp(doc[MTIME])
+    for key in [MTIME, PTIME]:
+        if key in doc:
+            # we have UNIX UTC timestamp (int), whoosh wants datetime
+            doc[key] = datetime.datetime.utcfromtimestamp(doc[key])
     doc[NAME_EXACT] = doc[NAME]
     doc[WIKINAME] = wikiname
     doc[CONTENT] = content
@@ -269,6 +271,12 @@
         }
         latest_revs_fields.update(**userprofile_fields)
 
+        blog_entry_fields = {
+            # publish time from metadata (converted to UTC datetime)
+            PTIME: DATETIME(stored=True)
+        }
+        latest_revs_fields.update(**blog_entry_fields)
+
         all_revs_fields = {
             ITEMID: ID(stored=True),
         }
@@ -977,7 +985,7 @@
             # we have a result document from whoosh, which has quite a lot
             # of the usually wanted metadata, avoid storage access, use this.
             value = self._doc[key]
-            if key == MTIME:
+            if key in [MTIME, PTIME]:
                 # whoosh has a datetime object, but we want a UNIX timestamp
                 value = utctimestamp(value)
             return value
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/templates/blog.html	Fri Jul 27 19:08:35 2012 +0530
@@ -0,0 +1,29 @@
+{% extends theme("blog_layout.html") %}
+
+{% set no_entries_msg = _("There are no entries in this blog.") %}
+{% if supertag %}
+    {% set no_entries_msg = _("There are no entries in the \"%(supertag)s\" blog category.", supertag=supertag) %}
+{% endif %}
+
+{% block pagepath %}
+    {{ super() }}
+    {% if supertag %}
+        <span class="sep">/</span>
+        {{ _("Category:") }}
+        {% if blog_name %}
+            <a href="{{ url_for('frontend.show_blog', item_name=blog_name, supertag=supertag) }}">{{ supertag }}</a>
+        {% else %}
+            {{ supertag }}
+        {% endif %}
+    {% endif %}
+{% endblock %}
+
+{% block blog_content %}
+    {% if blog_entry_items %}
+        {% for entry_item in blog_entry_items %}
+            {{ show_blog_entry(entry_item) }}
+        {% endfor %}
+    {% else %}
+        {{ no_entries_msg }}
+    {% endif %}
+{% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/templates/blog_entry.html	Fri Jul 27 19:08:35 2012 +0530
@@ -0,0 +1,7 @@
+{% extends theme("blog_layout.html") %}
+
+{% block blog_content %}
+    {% if blog_entry_item %}
+        {{ show_blog_entry(blog_entry_item) }}
+    {% endif %}
+{% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/templates/blog_layout.html	Fri Jul 27 19:08:35 2012 +0530
@@ -0,0 +1,78 @@
+{% extends theme("layout.html") %}
+{% import "utils.html" as utils %}
+
+{% macro show_blog_entry(entry_item) %}
+    {% if entry_item.meta['summary'] %}
+        {% set title = entry_item.meta['summary'] %}
+    {% else %}
+        {% set title = entry_item.name %}
+    {% endif %}
+    <h1><a href="{{ url_for('frontend.show_item', item_name=entry_item.name) }}"
+        title="{{ title }}" class="moin-blog-entry-link">{{ title }}</a></h1>
+    <div class="moin-blog-entry-info">
+        {% set publish_time = entry_item.meta['ptime'] %}
+        {% if publish_time %}
+            {{ _("Published on") }} {{ entry_item.meta['ptime']|datetimeformat }}
+            {{ _("by") }} {{ utils.editor_info(entry_item.meta) }}
+        {% else %}
+            {{ _("It is not published yet.") }}
+        {% endif %}
+    </div>
+    <div class="moin-blog-entry-content">
+        {{ entry_item._render_data()|safe }} {# rendered blog entry content #}
+    </div>
+    <div class="moin-blog-entry-bottominfo">
+        {% set tags = entry_item.meta['tags']|sort %}
+        {% if tags %} {# display blog entry's tags as a list if it is not empty #}
+            <div class="moin-blog-entry-tags">
+                {{ _("Tags:") }}
+                <ul class="moin-blog-entry-tags">
+                    {% for tag in tags %}
+                        <li><a href="{{ url_for('frontend.tagged_items', tag=tag) }}">{{ tag }}</a></li>
+                    {% endfor %}
+                </ul>
+            </div>
+        {% endif %}
+        <div class="moin-blog-entry-comments">
+            {% set discussion_item_name = '{0}/{1}'.format(entry_item.name, cfg.supplementation_item_names[0]) %}
+            <a href="{{ url_for('frontend.show_item', item_name=discussion_item_name) }}">{{ _("Discussion page") }}</a>
+        </div>
+    </div>
+{% endmacro %}
+
+{% macro widget_supertags(blog_name, supertags) %}
+    <div id="moin-blog-categories">
+        <h2>{{ _("Categories") }}</h2>
+        <ul>
+            {% for supertag in supertags %}
+                <li><a href="{{ url_for('frontend.show_blog', item_name=blog_name, supertag=supertag) }}">{{ supertag }}</a></li>
+            {% endfor %}
+        </ul>
+    </div>
+{% endmacro %}
+
+{% if blog_item %}
+    {% set blog_header = blog_item._render_data()|safe %}
+    {% set blog_name = blog_item.name %}
+    {% set supertags = blog_item.meta['supertags'] %}
+{% endif %}
+
+{% block content %}
+    {% block content_data %}
+        <div id="moin-content-data">
+            <div id="moin-blog-header">
+                {% if blog_header %}
+                    {{ blog_header }}
+                {% endif %}
+            </div>
+            <div id="moin-blog-content">
+            {% block blog_content %}<br />{% endblock %}
+            </div>
+            {% if blog_name and supertags %}
+                <div id="moin-blog-sidebar">
+                    {{ widget_supertags(blog_name, supertags) }}
+                </div>
+            {% endif %}
+        </div>
+    {% endblock %}
+{% endblock %}
--- a/MoinMoin/templates/layout.html	Fri Jul 27 19:06:29 2012 +0530
+++ b/MoinMoin/templates/layout.html	Fri Jul 27 19:08:35 2012 +0530
@@ -39,7 +39,7 @@
 
     <div id="moin-username">
         {% if user.valid -%}
-	    {% set avatar = user.avatar(20) %}
+            {% set avatar = user.avatar(20) %}
             {% if avatar %}
                 <img id="moin-avatar" rel="noreferrer" src="{{ avatar }}" />
             {%- endif %}
@@ -79,22 +79,24 @@
         {%- endif %}
         <span id="moin-pagelocation">
             <span class="moin-pagepath">
+            {% block pagepath %}
                 {% for segment_name, segment_path, exists in theme_supp.location_breadcrumbs(item_name) -%}
                     {% if not loop.last -%}
                         <a href="{{ url_for('frontend.show_item', item_name=segment_path) }}" {% if not exists %}class="moin-nonexistent"{% endif %}>
                             {{ segment_name|shorten_item_name }}
                         </a>
-			<span class="sep">/</span>
+                        <span class="sep">/</span>
                     {% else %}
-		        {% if title_name %}
+                        {% if title_name %}
                             {{ title_name }}
                         {% else %}
                         <a href="{{ url_for('frontend.show_item', item_name=segment_path) }}" {% if not exists %}class="moin-nonexistent"{% endif %}>
                             {{ segment_name|shorten_item_name }}
                         </a>
-		        {%- endif %}
+                        {%- endif %}
                     {%- endif %}
                 {%- endfor %}
+            {% endblock %}
             </span>
         </span>
     </div>
--- a/MoinMoin/themes/modernized/static/css/common.css	Fri Jul 27 19:06:29 2012 +0530
+++ b/MoinMoin/themes/modernized/static/css/common.css	Fri Jul 27 19:08:35 2012 +0530
@@ -47,6 +47,17 @@
 hr { display: block; height: 1px; border: 0; border-top: 1px solid #cccccc; margin: 1em 0; padding: 0; }
 input, select { vertical-align: middle; }
 /* end HTML5 reset */
+/* blog page */
+#moin-blog-header { margin: 1em 0 -1em 0; }
+#moin-blog-content { padding: 0 2em 0 0; display: table-cell }
+#moin-blog-sidebar { width: 15em; display: table-cell; }
+.moin-blog-entry-info { font-size: 0.8em; color: #888888; }
+.moin-blog-entry-bottominfo { font-size: 0.8em; color: #888888; padding: 0em 1em; border: 1px solid #DEDEDE;}
+ul.moin-blog-entry-tags { list-style: none; display: inline; margin: 0; }
+ul.moin-blog-entry-tags li { display: inline; }
+ul.moin-blog-entry-tags li:after { content: ","; } 
+ul.moin-blog-entry-tags li:last-child:after { content: ""; }
+
 /* smileys -- <span class="moin-text-icon moin-smile">:-)</span> */
 .moin-text-icon { font-size: 0; color: transparent; }
 .moin-alert:before { content: url('../img/smileys/alert.png'); }