]> git.openstreetmap.org Git - osqa.git/commitdiff
Adds the option to create static pages with several options to customize its behaviour.
authorhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Mon, 7 Jun 2010 01:56:21 +0000 (01:56 +0000)
committerhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Mon, 7 Jun 2010 01:56:21 +0000 (01:56 +0000)
git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@381 0cfe37f9-358a-4d5e-be75-b63607b5c754

32 files changed:
forum/actions/__init__.py
forum/actions/meta.py
forum/actions/page.py [new file with mode: 0644]
forum/actions/user.py
forum/forms/__init__.py [new file with mode: 0644]
forum/forms/admin.py [new file with mode: 0644]
forum/forms/auth.py [moved from forum/authentication/forms.py with 96% similarity]
forum/forms/general.py [moved from forum/utils/forms.py with 100% similarity]
forum/forms/qanda.py [moved from forum/forms.py with 98% similarity]
forum/middleware/anon_user.py
forum/middleware/cancel.py
forum/models/__init__.py
forum/models/node.py
forum/models/page.py [new file with mode: 0644]
forum/settings/__init__.py
forum/settings/forms.py
forum/skins/default/media/js/osqa.admin.js
forum/skins/default/templates/osqaadmin/djstyle_base.html
forum/skins/default/templates/osqaadmin/edit_page.html [new file with mode: 0644]
forum/skins/default/templates/osqaadmin/static_pages.html [new file with mode: 0644]
forum/skins/default/templates/page.html [new file with mode: 0644]
forum/urls.py
forum/views/admin.py
forum/views/auth.py
forum/views/commands.py
forum/views/meta.py
forum/views/readers.py
forum/views/users.py
forum/views/writers.py
forum_modules/localauth/forms.py
forum_modules/localauth/views.py
manage.py

index a68106994501385853ebe1f9f2c712323bbbc806..4c6c6784b30ef42f2923805e2260430ad6041309 100644 (file)
@@ -1,3 +1,4 @@
 from meta import *\r
 from node import *\r
-from user import *
\ No newline at end of file
+from user import *\r
+from page import *
\ No newline at end of file
index adf51ca933c63fdf26d2b4a89aa8d4acb4f7c883..ccdaa75f390396d09b2687b95e1277f3b450e9b9 100644 (file)
@@ -157,7 +157,7 @@ class AcceptAnswerAction(ActionProxy):
 \r
         return _("%(user)s accepted %(answerer)s answer on %(asker)s question %(question)s") % {\r
             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),\r
-            'answerer': self.hyperlink(answer.author.get_profile_url(), self.friendly_username(viewer, answer.author)),\r
+            'answerer': self.hyperlink(answer.author.get_profile_url(), self.friendly_ownername(viewer, answer.author)),\r
             'asker': asker,\r
             'question': self.hyperlink(question.get_absolute_url(), question.title)\r
         }\r
diff --git a/forum/actions/page.py b/forum/actions/page.py
new file mode 100644 (file)
index 0000000..bfeda16
--- /dev/null
@@ -0,0 +1,58 @@
+from django.utils.translation import ugettext as _
+from forum.models.action import ActionProxy
+from forum.models import Page
+
+class NewPageAction(ActionProxy):
+    verb = _("created")
+
+    def process_data(self, **data):
+        title = data.pop('title')
+        body = data.pop('content')
+
+        page = Page(author=self.user, title=title, body=body, extra=data)
+        page.save()
+        self.node = page
+
+    def describe(self, viewer=None):
+        return _("%(user)s created a new page titled %(page)s") % {
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+            'page': self.hyperlink(self.node.get_absolute_url(), self.node.title)
+        }
+
+class EditPageAction(ActionProxy):
+    verb = _("edited")
+
+    def process_data(self, **data):
+        title = data.pop('title')
+        body = data.pop('content')
+
+        if (title != self.node.title) and (body != self.node.body):
+            self.node.create_revision(self.user, title=title, body=body)
+
+        self.node.extra = data
+        self.node.save()
+
+    def describe(self, viewer=None):
+        return _("%(user)s edited the page titled %(page)s") % {
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+            'page': self.hyperlink(self.node.get_absolute_url(), self.node.title)
+        }
+
+class PublishAction(ActionProxy):
+    verb = _("published")
+
+    def process_action(self):
+        self.node.marked = True
+        self.node.nstate.published = self
+        self.node.save()
+
+    def cancel_action(self):
+        self.node.marked = False
+        self.node.nstate.published = None
+        self.node.save()
+
+    def describe(self, viewer=None):
+        return _("%(user)s published a new page titled %(page)s") % {
+            'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+            'page': self.hyperlink(self.node.get_absolute_url(), self.node.title)
+        }
index 6c174cee2e92ed989feee691931b69115f702e28..df90c66f562ffd163ea818597968a96e6550c405 100644 (file)
@@ -24,7 +24,7 @@ class EditProfileAction(ActionProxy):
     def describe(self, viewer=None):
         return _("%(user)s edited %(hes_or_your)s %(profile_link)s") % {
             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
-            'hes_or_your': self.viewer_or_user_verb(viewer, self.user, _('your'), _('hes')),
+            'hes_or_your': self.viewer_or_user_verb(viewer, self.user, _('your'), _('his')),
             'profile_link': self.hyperlink(self.user.get_profile_url(), _('profile')),
         }
 
diff --git a/forum/forms/__init__.py b/forum/forms/__init__.py
new file mode 100644 (file)
index 0000000..ea5108c
--- /dev/null
@@ -0,0 +1,4 @@
+from qanda import *
+from admin import *
+from auth import *
+from general import *
diff --git a/forum/forms/admin.py b/forum/forms/admin.py
new file mode 100644 (file)
index 0000000..eabeb57
--- /dev/null
@@ -0,0 +1,86 @@
+import socket
+from django import forms
+from django.utils.translation import ugettext as _
+from qanda import TitleField, EditorField
+from forum import settings
+
+class IPListField(forms.CharField):
+    def clean(self, value):
+        ips = [ip.strip() for ip in value.strip().strip(',').split(',')]
+        iplist = []
+
+        if len(ips) < 1:
+            raise forms.ValidationError(_('Please input at least one ip address'))
+
+        for ip in ips:
+            try:
+                socket.inet_aton(ip)
+            except socket.error:
+                raise forms.ValidationError(_('Invalid ip address: %s' % ip))
+
+            if not len(ip.split('.')) == 4:
+                raise forms.ValidationError(_('Please use the dotted quad notation for the ip addresses'))
+
+            iplist.append(ip)
+
+        return iplist
+
+class MaintenanceModeForm(forms.Form):
+    ips = IPListField(label=_('Allow ips'),
+                      help_text=_('Comma separated list of ips allowed to access the site while in maintenance'),
+                      required=True,
+                      widget=forms.TextInput(attrs={'class': 'longstring'}))
+
+    message = forms.CharField(label=_('Message'),
+                              help_text=_('A message to display to your site visitors while in maintainance mode'),
+                              widget=forms.Textarea)
+
+
+TEMPLATE_CHOICES = (
+    ('default', _('Default')),
+    ('sidebar', _('Default with sidebar')),
+    ('none', _('None')),
+)
+
+RENDER_CHOICES = (
+    ('markdown', _('Markdown')),
+    ('html', _('HTML')),
+    ('escape', _('Escaped'))
+)
+
+class UrlFieldWidget(forms.TextInput):
+    def render(self, name, value, attrs=None):
+        if not value:
+            value = ''
+            
+        return """
+                <input class="url_field" type="text" name="%(name)s" value="%(value)s" />
+                <a class="url_field_anchor" target="_blank" href="%(app_url)s%(script_alias)s"></a>
+            """  % {'name': name, 'value': value, 'app_url': settings.APP_URL, 'script_alias': settings.FORUM_SCRIPT_ALIAS}
+
+
+class PageForm(forms.Form):
+
+    def __init__(self, page, *args, **kwargs):
+        if page:
+            initial = page.extra
+            initial.update(dict(title=page.title, content=page.body))
+            super(PageForm, self).__init__(initial=initial, *args, **kwargs)
+        else:
+            super(PageForm, self).__init__(*args, **kwargs)
+
+
+    title  = forms.CharField(label=_('Title'), max_length=255, widget=forms.TextInput(attrs={'class': 'longstring'}), initial='New page')
+    path  = forms.CharField(label=_('Page URL'), widget=UrlFieldWidget, initial='pages/new/')
+
+    content = forms.CharField(label=_('Page Content'), widget=forms.Textarea(attrs={'rows': 30}))
+    render = forms.ChoiceField(widget=forms.RadioSelect, choices=RENDER_CHOICES, initial='markdown', label=_('Render Mode'))
+
+    template = forms.ChoiceField(widget=forms.RadioSelect, choices=TEMPLATE_CHOICES, initial='default', label=_('Template'))
+    sidebar = forms.CharField(label=_('Sidebar Content'), widget=forms.Textarea(attrs={'rows': 20}), required=False)
+    sidebar_wrap = forms.BooleanField(label=_("Wrap sidebar block"), initial=True, required=False) 
+    sidebar_render = forms.ChoiceField(widget=forms.RadioSelect, choices=RENDER_CHOICES, initial='markdown', label=_('Sidebar Render Mode'))
+
+    comments = forms.BooleanField(label=_("Allow comments"), initial=False, required=False)
+
+    
\ No newline at end of file
similarity index 96%
rename from forum/authentication/forms.py
rename to forum/forms/auth.py
index 01c857d8e417a4e42ceead5cfd4f6b90f6d3ca73..594e59f8e526de85326df6fe14d2a2a4a6b88b37 100644 (file)
@@ -1,4 +1,4 @@
-from forum.utils.forms import NextUrlField,  UserNameField,  UserEmailField, SetPasswordForm
+from general import NextUrlField,  UserNameField,  UserEmailField, SetPasswordForm
 from forum.models import Question, User
 from django.contrib.contenttypes.models import ContentType
 from django.utils.translation import ugettext as _
similarity index 100%
rename from forum/utils/forms.py
rename to forum/forms/general.py
similarity index 98%
rename from forum/forms.py
rename to forum/forms/qanda.py
index 0b865374625542efaa720a6766144cf7108a500b..7c58500975faca4b1f031ccf46948440e7a23224 100644 (file)
@@ -1,13 +1,12 @@
 import re
 from datetime import date
 from django import forms
-from models import *
+from forum.models import *
 from django.utils.translation import ugettext as _
 from django.contrib.humanize.templatetags.humanize import apnumber
-from forum.models import User
 
 from django.utils.safestring import mark_safe
-from forum.utils.forms import NextUrlField, UserNameField, SetPasswordForm
+from general import NextUrlField, UserNameField, SetPasswordForm
 from forum import settings
 import logging
 
@@ -255,6 +254,7 @@ class EditUserForm(forms.Form):
         if self.user.email != self.cleaned_data['email']:
             if settings.EMAIL_UNIQUE == True:
                 if 'email' in self.cleaned_data:
+                    from forum.models import User
                     try:
                         User.objects.get(email = self.cleaned_data['email'])
                     except User.DoesNotExist:
index a517f664b0e37c8c513cb5445e94a92bb3e8ed54..26c138c8fbc3beeadaea979ac3e046c3b57eea86 100644 (file)
@@ -1,5 +1,5 @@
 from django.http import HttpResponseRedirect
-from forum.utils.forms import get_next_url
+from forum.forms import get_next_url
 from django.utils.translation import ugettext as _
 from forum.user_messages import create_message, get_and_delete_messages
 from forum import settings
index 15a4371dabf83c10b01ebbeda4be3c273b303e0a..2d78a171c5e811ae4c9845a6a06a27ec1e72ec25 100644 (file)
@@ -1,5 +1,5 @@
 from django.http import HttpResponseRedirect
-from forum.utils.forms import get_next_url
+from forum.forms import get_next_url
 import logging
 class CancelActionMiddleware(object):
     def process_view(self, request, view_func, view_args, view_kwargs):
index 449ca3a8d94a7b5cc5c83681ab24cd5e1b05e949..7a15132362bc0bc70c0d83809d28a37818bc1278 100644 (file)
@@ -7,6 +7,7 @@ from comment import Comment
 from action import Action, ActionRepute
 from meta import Vote, Flag, Badge, Award
 from utils import KeyValue
+from page import Page
 
 try:
     from south.modelsinspector import add_introspection_rules
@@ -22,7 +23,7 @@ __all__ = [
         'Answer', 'AnswerRevision',
         'Tag', 'Comment', 'MarkedTag', 'Badge', 'Award',
         'ValidationHash', 'AuthKeyUserAssociation', 'SubscriptionSettings', 'KeyValue', 'User',
-        'Action', 'ActionRepute', 'Vote', 'Flag'
+        'Action', 'ActionRepute', 'Vote', 'Flag', 'Page'
         ]
 
 
index bf05cb54beb0f24be0ec6d6daf6ee886c5f35aa4..b0f53612493f57952ba91fc9bfa653e3fd46f6ae 100644 (file)
@@ -23,8 +23,12 @@ class NodeContent(models.Model):
     def html(self):
         return self.as_markdown()
 
+    @classmethod
+    def _as_markdown(cls, content, *extensions):
+        return mark_safe(sanitize_html(markdown.markdown(content, extensions=extensions)))
+
     def as_markdown(self, *extensions):
-        return mark_safe(sanitize_html(markdown.markdown(self.body, extensions=extensions)))
+        return self._as_markdown(self.body, *extensions)
 
     @property
     def headline(self):
diff --git a/forum/models/page.py b/forum/models/page.py
new file mode 100644 (file)
index 0000000..ff3b1a4
--- /dev/null
@@ -0,0 +1,40 @@
+from base import *
+from django.utils.translation import ugettext as _
+
+class Page(Node):
+    friendly_name = _("page")
+
+    @property
+    def published(self):
+        return self.marked
+
+    def save(self, *args, **kwargs):
+        old_options = self._original_state.get('extra', None)
+
+        super(Page, self).save(*args, **kwargs)
+
+        registry = settings.STATIC_PAGE_REGISTRY
+
+        if old_options:
+            registry.pop(old_options.get('path', ''), None)
+
+        registry[self.extra['path']] = self.id
+
+
+        settings.STATIC_PAGE_REGISTRY.set_value(registry)
+
+    @property
+    def headline(self):
+        if self.published:
+            return self.title
+        else:
+            return _("[Unpublished] %s") % self.title
+
+    @models.permalink
+    def get_absolute_url(self):
+        return ('static_page', (), {'path': self.extra['path']})
+
+    class Meta(Node.Meta):
+        proxy = True
+
+    
\ No newline at end of file
index 95f2441641dc56aca0da2a165ab704c38fda916b..addab2d0e68cc179f8c1e96b202bde880483fe40 100644 (file)
@@ -1,6 +1,5 @@
 import os.path
 from base import Setting, SettingSet
-from forms import ImageFormWidget
 
 from django.forms.widgets import Textarea
 from django.utils.translation import ugettext_lazy as _
@@ -18,6 +17,8 @@ DJSTYLE_ADMIN_INTERFACE = Setting('DJSTYLE_ADMIN_INTERFACE', True)
 APP_URL = djsettings.APP_URL
 FORUM_SCRIPT_ALIAS = djsettings.FORUM_SCRIPT_ALIAS
 
+STATIC_PAGE_REGISTRY = Setting('STATIC_PAGE_REGISTRY', {})
+
 
 from basic import *
 from sidebar import *
index 27581d5412eb95c3e953865102c1386c545a6184..432ba0b8053d37d1cdea4514deafecfa2ae9a841 100644 (file)
@@ -1,8 +1,7 @@
 import os
-import socket
 from string import strip
 from django import forms
-from base import Setting
+from forum.settings.base import Setting
 from django.utils.translation import ugettext as _
 from django.core.files.storage import FileSystemStorage
 
@@ -110,36 +109,5 @@ class CommaStringListWidget(forms.Textarea):
             return ', '.join(data[name])    
 
 
-class IPListField(forms.CharField):
-    def clean(self, value):
-        ips = [ip.strip() for ip in value.strip().strip(',').split(',')]
-        iplist = []
-
-        if len(ips) < 1:
-            raise forms.ValidationError(_('Please input at least one ip address'))    
-
-        for ip in ips:
-            try:
-                socket.inet_aton(ip)
-            except socket.error:
-                raise forms.ValidationError(_('Invalid ip address: %s' % ip))
-
-            if not len(ip.split('.')) == 4:
-                raise forms.ValidationError(_('Please use the dotted quad notation for the ip addresses'))
-
-            iplist.append(ip)
-
-        return iplist
-
-class MaintenanceModeForm(forms.Form):
-    ips = IPListField(label=_('Allow ips'),
-                      help_text=_('Comma separated list of ips allowed to access the site while in maintenance'),
-                      required=True,
-                      widget=forms.TextInput(attrs={'class': 'longstring'}))
-
-    message = forms.CharField(label=_('Message'),
-                              help_text=_('A message to display to your site visitors while in maintainance mode'),
-                              widget=forms.Textarea)
-
 
 
index 634f4c8fcfb8694739e24bf54e28b5f69c36f9be..cce64a5daa6acb962e69a2099fd48bffdd1a850a 100644 (file)
@@ -41,4 +41,21 @@ $(function() {
             }\r
         }\r
     });\r
+\r
+    $('.url_field').each(function() {\r
+        var $input = $(this);\r
+        var $anchor = $input.parent().find('.url_field_anchor');\r
+        var app_url = $anchor.attr('href');\r
+\r
+        function rewrite_anchor() {\r
+            var val = app_url + $input.val();\r
+\r
+            $anchor.attr('href', val);\r
+            $anchor.html(val);\r
+\r
+        }\r
+\r
+        $input.keyup(rewrite_anchor);\r
+        rewrite_anchor();        \r
+    });\r
 });
\ No newline at end of file
index 2d74adf1de217e0db053b950ada16d4628800a4a..7798b49004fb0a829298729bdd4f1cfc27456989 100644 (file)
@@ -38,7 +38,7 @@
             </div>
         </div>
         <div class="breadcrumbs">
-            <a href="{% url index %}">{% trans "Home" %}</a> &gt
+            <a href="{% url index %}">{% trans "Home" %}</a> &gt;
             <a href="{% url admin_index %}">{% trans "Dashboard" %}</a> &gt;
             {% block pagename %}{% endblock %} - 
             {% block description %}{% endblock %}
@@ -82,6 +82,7 @@
                 <div id="pages-sets-menu" class="module">
                     <h2>{% trans "Static content" %}</h2>
                     <ul>
+                        <li><a href="{% url admin_static_pages %}">{% trans "Custom Pages" %}</a></li>
                         <li><a href="{% url admin_set allsets.about.name %}">{{ allsets.about.title }}</a></li>
                         <li><a href="{% url admin_set allsets.faq.name %}">{{ allsets.faq.title }}</a></li>
                         <li><a href="{% url admin_set allsets.sidebar.name %}">{{ allsets.sidebar.title }}</a></li>
diff --git a/forum/skins/default/templates/osqaadmin/edit_page.html b/forum/skins/default/templates/osqaadmin/edit_page.html
new file mode 100644 (file)
index 0000000..269cec8
--- /dev/null
@@ -0,0 +1,32 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+
+{% block subtitle %}{% trans "Editing page" %}{% endblock %}
+{% block pagename %}
+    <a href="{% url admin_static_pages %}">{% trans "Static Pages" %}</a> &gt;
+    {% if page %}{% trans "Editing page" %}{% else %}{% trans "Creating page" %}{% endif %}
+{% endblock %}
+{% block description %}
+    {% if page %}{{ page.title }}{% else %}{% trans "New page" %}{% endif %}
+    ({% if published %}{% trans "Published" %}{% else %}{% trans "Unpublished" %}{% endif %})    
+{% endblock %}
+
+{% block admincontent %}
+    <form action="" method="post" accept-charset="utf-8">
+        <table style="width: 100%">
+        {{ form.as_table }}
+        <tr>
+            <th></th>
+            <td>
+                <input id="submit" name="submit" type="submit" value="{% trans "Save" %}" />
+                {% if published %}
+                    <input id="unpublish" name="unpublish" type="submit" value="{% trans "Unpublish" %}" />
+                {% else %}
+                    <input id="publish" name="publish" type="submit" value="{% trans "Publish" %}" />
+                {% endif %}
+            </td>
+        </tr>
+        </table>
+    </form>
+{% endblock %}
\ No newline at end of file
diff --git a/forum/skins/default/templates/osqaadmin/static_pages.html b/forum/skins/default/templates/osqaadmin/static_pages.html
new file mode 100644 (file)
index 0000000..7d0e567
--- /dev/null
@@ -0,0 +1,28 @@
+{% extends basetemplate %}
+
+{% load i18n %}
+
+{% block subtitle %}{% trans "Static pages" %}{% endblock %}
+{% block pagename %}{% trans "Static pages" %}{% endblock %}
+{% block description %}{% trans "Allows you to create a set of static pages" %}{% endblock %}
+
+{% block admincontent %}
+    <h1>{% trans "Select page to edit" %}</h1>
+    <ul class="object-tools">
+        <li><a class="addlink" href="{% url admin_new_page %}">{% trans "New page" %}</a></li>
+    </ul>
+    <div class="module">
+        <table style="width: 100%">
+            <caption>{% trans "Pages" %}</caption>
+            <tbody>
+                {% for page in pages %}
+                    <tr>
+                        <th scope="row"><a href="{% url admin_edit_page id=page.id %}">{{ page.headline }}</a></th>
+                        <td><a class="changelink" href="{% url admin_edit_page id=page.id %}">{% trans "Edit" %}</a></td>
+                    </tr>
+                {% endfor %}
+            </tbody>
+        </table>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/forum/skins/default/templates/page.html b/forum/skins/default/templates/page.html
new file mode 100644 (file)
index 0000000..cf9b459
--- /dev/null
@@ -0,0 +1,27 @@
+{% extends base %}
+{% load i18n markup node_tags general_sidebar_tags %}
+{% block title %}{% spaceless %}{{ page.title }}{% endspaceless %}{% endblock %}
+
+{% block content %}
+<div class="headNormal">{{ page.title }}</div>
+<div class="content">
+{{ body }}
+</div>
+{% if page.extra.comments %}
+    {% comments page request.user %}
+{% endif %}
+{% endblock %}
+
+{% ifequal page.extra.template "sidebar" %}
+    {% block sidebar %}
+        {% sidebar_upper %}
+        {% if page.extra.sidebar %}
+            {% if page.extra.sidebar_wrap %}<div class="boxC"><div class="body">{% endif %}
+                {{ sidebar }}
+            {% if page.extra.sidebar_wrap %}</div></div>{% endif %}
+        {% endif %}
+        {% sidebar_lower %}
+    {% endblock %}
+{% endifequal %}
+
+
index 9ba2ebdcd4d38828d12d3e79951aa95eb2aa7843..e517ddbf71ab6332e0da35fae0d284519c9f3a84 100644 (file)
@@ -140,8 +140,14 @@ urlpatterns += patterns('',
     url(r'^%s%s(?P<set_name>\w+)/(?P<var_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.get_default, name="admin_default"),
     url(r'^%s%s$' % (_('admin/'), _('maintenance/')), app.admin.maintenance, name="admin_maintenance"),
     url(r'^%s%s$' % (_('admin/'), _('flagged_posts/')), app.admin.flagged_posts, name="admin_flagged_posts"),
+    url(r'^%s%s$' % (_('admin/'), _('static_pages/')), app.admin.static_pages, name="admin_static_pages"),
+
+    url(r'^%s%s%s$' % (_('admin/'), _('static_pages/'), _('new/')), app.admin.edit_page, name="admin_new_page"),
+    url(r'^%s%s%s(?P<id>\d+)/$' % (_('admin/'), _('static_pages/'), _('edit/')), app.admin.edit_page, name="admin_edit_page"),
 
     url(r'^%s%s(?P<set_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.settings_set, name="admin_set"),
 
     url(r'^feeds/rss/$', RssLastestQuestionsFeed, name="latest_questions_feed"),
+
+    url(r'^(?P<path>.+)$', app.meta.page, name="static_page")
 )
index 2b3426efac14622346f92d6474f2f2fd975dd6af..800e59fdbed7446d3652007fc1d2c1e45a728036 100644 (file)
@@ -1,7 +1,7 @@
 from datetime import datetime, timedelta
 import time
 
-from django.shortcuts import render_to_response
+from django.shortcuts import render_to_response, get_object_or_404
 from django.core.urlresolvers import reverse
 from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
 from django.template import RequestContext
@@ -9,9 +9,11 @@ from django.utils.translation import ugettext as _
 from django.utils import simplejson
 from django.db.models import Sum
 from forum.settings.base import Setting
-from forum.settings.forms import SettingsSetForm, MaintenanceModeForm
+from forum.forms import MaintenanceModeForm, PageForm
+from forum.settings.forms import SettingsSetForm
 
-from forum.models import Question, Answer, User, Node, Action
+from forum.models import Question, Answer, User, Node, Action, Page
+from forum.actions import NewPageAction, EditPageAction, PublishAction
 from forum import settings
 
 def super_user_required(fn):
@@ -283,4 +285,51 @@ def flagged_posts(request):
         'flagged_posts': get_flagged_posts(),
     })
 
+@admin_page
+def static_pages(request):
+    pages = Page.objects.all()
+
+    return ('osqaadmin/static_pages.html', {
+        'pages': pages,
+    })
+
+@admin_page
+def edit_page(request, id=None):
+    if id:
+        page = get_object_or_404(Page, id=id)
+    else:
+        page = None
+
+    if request.POST:
+        form = PageForm(page, request.POST)
+
+        if form.is_valid():
+            if form.has_changed():
+                if not page:
+                    page = NewPageAction(user=request.user, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data).node
+                else:
+                    EditPageAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save(data=form.cleaned_data)
+
+            if ('publish' in request.POST) and (not page.published):
+                PublishAction(user=request.user, node=page, ip=request.META['REMOTE_ADDR']).save()
+            elif ('unpublish' in request.POST) and page.published:
+                page.nstate.published.cancel(ip=request.META['REMOTE_ADDR'])
+
+            return HttpResponseRedirect(reverse('admin_edit_page', kwargs={'id': page.id}))
+
+    else:
+        form = PageForm(page)
+
+    if page:
+        published = page.published
+    else:
+        published = False
+
+    return ('osqaadmin/edit_page.html', {
+        'page': page,
+        'form': form,
+        'published': published
+    })
+
+
 
index 1230cf7f90408288037ff5ca5aec992443ad3b7b..ebccf0eefdc5669a8953537eb71ffb7788f94d1a 100644 (file)
@@ -12,7 +12,7 @@ from django.http import get_host
 import types
 import datetime
 
-from forum.authentication.forms import SimpleRegistrationForm, SimpleEmailSubscribeForm, \
+from forum.forms import SimpleRegistrationForm, SimpleEmailSubscribeForm, \
         TemporaryLoginRequestForm, ChangePasswordForm, SetPasswordForm
 from forum.utils.mail import send_email, send_template_email
 
index 456199d8c1c05d75e996c20e42df288796631e46..ed6c03ffbe923b62886c5e4190baf732bf1cbeca 100644 (file)
@@ -292,8 +292,9 @@ def accept_answer(request, id):
         answer.nstate.accepted.cancel(user, ip=request.META['REMOTE_ADDR'])
         commands['unmark_accepted'] = [answer.id]
     else:
-        if question.answer_accepted:
-            accepted = question.accepted_answer
+        accepted = question.accepted_answer
+
+        if accepted:
             accepted.nstate.accepted.cancel(user, ip=request.META['REMOTE_ADDR'])
             commands['unmark_accepted'] = [accepted.id]
 
index b4cb75affa147a78a03a66b9f42b92bd7cd6bde6..608d1cb1aa02ee4253e064082846cf21476149b2 100644 (file)
@@ -3,18 +3,19 @@ from itertools import groupby
 from django.shortcuts import render_to_response, get_object_or_404
 from django.core.urlresolvers import reverse
 from django.template import RequestContext, loader
-from django.http import HttpResponseRedirect, HttpResponse
+from django.http import HttpResponseRedirect, HttpResponse, Http404
 from django.views.static import serve
 from forum import settings
 from forum.forms import FeedbackForm
 from django.core.urlresolvers import reverse
 from django.utils.translation import ugettext as _
 from django.db.models import Count
-from forum.utils.forms import get_next_url
-from forum.models import Badge, Award, User
+from forum.forms import get_next_url
+from forum.models import Badge, Award, User, Page
 from forum.badges.base import BadgesMeta
 from forum import settings
 from forum.utils.mail import send_template_email
+from django.utils.safestring import mark_safe
 import re
 
 def favicon(request):
@@ -94,3 +95,50 @@ def badge(request, id, slug):
         'badge' : badge,
     }, context_instance=RequestContext(request))
 
+def page(request, path):
+    if path in settings.STATIC_PAGE_REGISTRY:
+        try:
+            page = Page.objects.get(id=settings.STATIC_PAGE_REGISTRY[path])
+
+            if not page.published or request.user.is_superuser:
+                raise Http404
+        except:
+            raise Http404
+    else:
+        raise Http404
+
+    template = page.extra.get('template', 'default')
+    sidebar = page.extra.get('sidebar', '')
+
+    if template == 'default':
+        base = 'base_content.html'
+    elif template == 'sidebar':
+        base = 'base.html'
+
+        sidebar_render = page.extra.get('render', 'markdown')
+
+        if sidebar_render == 'markdown':
+            sidebar = page._as_markdown(sidebar)
+        elif sidebar_render == 'html':
+            sidebar = mark_safe(sidebar)
+
+    else:
+        return HttpResponse(page.body)
+
+    render = page.extra.get('render', 'markdown')
+
+    if render == 'markdown':
+        body = page.as_markdown()
+    elif render == 'html':
+        body = mark_safe(page.body)
+    else:
+        body = page.body
+
+    return render_to_response('page.html', {
+        'page' : page,
+        'body' : body,
+        'sidebar': sidebar,
+        'base': base,        
+        }, context_instance=RequestContext(request))
+
+
index 6e75b378a1572b2900f78933db16bdeab4157f69..a1bb746ddd65ff834b16aeb232ec49d7e6cb3a51 100644 (file)
@@ -24,7 +24,7 @@ from forum.utils.html import sanitize_html
 from forum.utils.diff import textDiff as htmldiff
 from forum.forms import *
 from forum.models import *
-from forum.utils.forms import get_next_url
+from forum.forms import get_next_url
 from forum.actions import QuestionViewAction
 from forum.modules.decorators import decoratable
 import decorators
index 6bc3477d35c4461d6618e88527572a41c53ee083..da556be2654706cf0124786f99bd6b7663142f7e 100644 (file)
@@ -204,7 +204,7 @@ def user_stats(request, user):
 \r
 @user_view('users/recent.html', 'recent', _('recent user activity'), _('recent activity'))\r
 def user_recent(request, user):\r
-    activities = user.actions.exclude(action_type__in=("voteup", "votedown", "voteupcomment", "flag")).order_by('-action_date')[:USERS_PAGE_SIZE]\r
+    activities = user.actions.exclude(action_type__in=("voteup", "votedown", "voteupcomment", "flag", "newpage", "editpage")).order_by('-action_date')[:USERS_PAGE_SIZE]\r
 \r
     return {"view_user" : user, "activities" : activities}\r
 \r
index b6e13af629fe3af691889d3f71d9b96d2bceec14..aace1f6aa269d63fe6bcd5e974aacabf8054a924 100644 (file)
@@ -17,7 +17,7 @@ from forum.actions import AskAction, AnswerAction, ReviseAction, RollbackAction,
 from forum.modules.decorators import decoratable
 from forum.forms import *
 from forum.models import *
-from forum.utils.forms import get_next_url
+from forum.forms import get_next_url
 
 
 def upload(request):#ajax upload file to a question or answer
index a3fd9928be7a59beb026f38f431fb2a2dc687583..961c7da389674583cbe1d923b429839f94e5fc7e 100644 (file)
@@ -1,4 +1,4 @@
-from forum.utils.forms import NextUrlField,  UserNameField,  UserEmailField, SetPasswordForm
+from forum.forms import NextUrlField,  UserNameField,  UserEmailField, SetPasswordForm
 from forum.models import Question
 from forum.modules import call_all_handlers
 from django.contrib.contenttypes.models import ContentType
index 4392c5a939837cf078c4335dfef0333a60fb4a3e..e1daff3e7b87b8bb551a36207ed21743ec869596 100644 (file)
@@ -4,7 +4,7 @@ from django.template import RequestContext
 from django.utils.translation import ugettext as _
 
 from forms import ClassicRegisterForm
-from forum.authentication.forms import SimpleEmailSubscribeForm
+from forum.forms import SimpleEmailSubscribeForm
 from forum.views.auth import login_and_forward
 from forum.actions import UserJoinsAction
 
index bcd2f8ee599be94b17e98c4395b50ddf357384c5..f9894f584e6defa2ad62893817cdaabee0e0e20a 100644 (file)
--- a/manage.py
+++ b/manage.py
@@ -6,7 +6,7 @@ except ImportError, e:
     import traceback
     traceback.print_exc()
     import sys
-    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+    sys.stderr.write("Error: Can't find the file 'forms.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file forms.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
     sys.exit(1)
 
 if __name__ == "__main__":