return {'settings': settings}
def auth_processor(request):
- """
- Returns context variables required by apps that use Django's authentication
- system.
-
- If there is no 'user' attribute in the request, uses AnonymousUser (from
- django.contrib.auth).
- """
if hasattr(request, 'user'):
user = request.user
if user.is_authenticated():
TMP_MINICACHE_SECONDS = 5
class SettingSet(list):
- def __init__(self, name, title, description, weight=1000, markdown=False):
+ def __init__(self, name, title, description, weight=1000, markdown=False, can_preview=False):
self.name = name
self.title = title
self.description = description
self.weight = weight
self.markdown = markdown
+ self.can_preview = can_preview
class BaseSetting(object):
self._temp = None
if set is not None:
+ self.set = set
+
if not set.name in Setting.sets:
Setting.sets[set.name] = set
class SettingsSetForm(forms.Form):
- def __init__(self, set, data=None, *args, **kwargs):
- if data is None:
- initial = dict([(setting.name, setting.value) for setting in set])
- else:
- initial = None
+ def __init__(self, set, data=None, unsaved=None, *args, **kwargs):
+ initial = dict([(setting.name, setting.value) for setting in set])
+
+ if unsaved:
+ initial.update(unsaved)
super(SettingsSetForm, self).__init__(data, initial=initial, *args, **kwargs)
for setting in set:
- if isinstance(setting, (Setting.emulators.get(str, DummySetting), Setting.emulators.get(unicode, DummySetting))):
+ widget = setting.field_context.get('widget', None)
+
+ if widget is forms.RadioSelect or isinstance(widget, forms.RadioSelect):
+ field = forms.ChoiceField(**setting.field_context)
+ elif isinstance(setting, (Setting.emulators.get(str, DummySetting), Setting.emulators.get(unicode, DummySetting))):
if not setting.field_context.get('widget', None):
setting.field_context['widget'] = forms.TextInput(attrs={'class': 'longstring'})
field = forms.CharField(**setting.field_context)
from base import Setting, SettingSet
-from django.forms.widgets import Textarea
+from django.forms.widgets import Textarea, RadioSelect
from django.utils.translation import ugettext_lazy as _
STATIC_PAGE_REGISTRY = Setting('STATIC_PAGE_REGISTRY', {})
-CSS_SET = SettingSet('css', 'Custom CSS', "Define some custom css you can use to override the default css.", 2000)
+CSS_SET = SettingSet('css', 'Custom CSS', "Define some custom css you can use to override the default css.", 2000, can_preview=True)
USE_CUSTOM_CSS = Setting('USE_CUSTOM_CSS', False, CSS_SET, dict(
label = _("Use custom CSS"),
widget=Textarea(attrs={'rows': '25'}),
required=False))
+
+HEAD_AND_FOOT_SET = SettingSet('headandfoot', 'Header and Footer', "Adds a custom header and/or footer to your page", 2000, can_preview=True)
+
+USE_CUSTOM_HEADER = Setting('USE_CUSTOM_HEADER', False, HEAD_AND_FOOT_SET, dict(
+label = _("Use custom header"),
+help_text = _("Do you want to use a custom header."),
+required=False))
+
+CUSTOM_HEADER = Setting('CUSTOM_HEADER', '', HEAD_AND_FOOT_SET, dict(
+label = _("Custom Header"),
+help_text = _("Your custom header."),
+widget=Textarea(attrs={'rows': '25'}),
+required=False))
+
+USE_CUSTOM_FOOTER = Setting('USE_CUSTOM_FOOTER', False, HEAD_AND_FOOT_SET, dict(
+label = _("Use custom footer"),
+help_text = _("Do you want to use a custom footer."),
+required=False))
+
+CUSTOM_FOOTER = Setting('CUSTOM_FOOTER', '', HEAD_AND_FOOT_SET, dict(
+label = _("Custom Footer"),
+help_text = _("Your custom footer."),
+widget=Textarea(attrs={'rows': '25'}),
+required=False))
+
+CUSTOM_FOOTER_MODE_CHOICES = (
+ ('replace', _('Replace default footer')),
+ ('above', _('Above default footer')),
+ ('below', _('Below default footer')),
+)
+
+CUSTOM_FOOTER_MODE = Setting('CUSTOM_FOOTER_MODE', 'replace', HEAD_AND_FOOT_SET, dict(
+label = _("Custom Footer Mode"),
+help_text = _("How your custom footer will appear."),
+widget=RadioSelect,
+choices=CUSTOM_FOOTER_MODE_CHOICES,
+required=False))
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- base_content.html -->
-{% load i18n %}
-{% load extra_tags %}
+{% load i18n extra_tags extra_filters markup %}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{% block fulltitle %}{% block title %}{% endblock %} - {{ settings.APP_SHORT_NAME }}{% endblock %}</title>
{% endif %}
<link rel="shortcut icon" href="{{ settings.APP_FAVICON }}" />
<link href="{% media "/media/style/style.css" %}" rel="stylesheet" type="text/css" />
- {% if settings.USE_CUSTOM_CSS %}
+ {% if settings.USE_CUSTOM_CSS|or_preview:request %}
<link href="{% url custom_css %}" rel="stylesheet" type="text/css" />
{% endif %}
{% block forestyle %}{% endblock %}
{% endautoescape %}
<a id="close-notify" onclick="notify.close(true)">×</a>
</div>
+ {% if settings.USE_CUSTOM_HEADER|or_preview:request %}
+ <div id="custom_header">
+ {{ settings.CUSTOM_HEADER|or_preview:request|markdown:"settingsparser" }}
+ </div>
+ {% endif %}
{% include "header.html" %}
{% block page_center %}
<div id="wrapper">
<div class="spacer3"></div>
</div>
{% endblock %}
- {% include "footer.html" %}
+ {% if settings.USE_CUSTOM_FOOTER|or_preview:request %}
+ {% ifequal settings.CUSTOM_FOOTER_MODE|or_preview:request "above" %}
+ <div id="custom_footer">
+ {{ settings.CUSTOM_FOOTER|or_preview:request|markdown:"settingsparser" }}
+ </div>
+ {% endifequal %}
+ <div id="ground">
+ {% ifequal settings.CUSTOM_FOOTER_MODE|or_preview:request "replace" %}
+ {{ settings.CUSTOM_FOOTER|or_preview:request|markdown:"settingsparser" }}
+ {% else %}
+ {% include "footer.html" %}
+ {% endifequal %}
+ </div>
+ {% ifequal settings.CUSTOM_FOOTER_MODE|or_preview:request "below" %}
+ <div id="custom_footer">
+ {{ settings.CUSTOM_FOOTER|or_preview:request|markdown:"settingsparser" }}
+ </div>
+ {% endifequal %}
+ {% else %}
+ <div id="ground">
+ {% include "footer.html" %}
+ </div>
+ {% endif %}
{% block endjs %}
{% endblock %}
{% if settings.GOOGLE_ANALYTICS_KEY %}
{% load extra_tags %}
{% load i18n %}
- <div id="ground">
- <div>
- <div class="footerLinks" >
- <a href="{% url about %}">{% trans "about" %}</a><span class="link-separator"> |</span>
- <a href="{% url faq %}">{% trans "faq" %}</a><span class="link-separator"> |</span>
- <a href="{% url privacy %}">{% trans "privacy" %}</a><span class="link-separator"> |</span>
- {% if settings.SUPPORT_URL %}
- <a href="{{settings.SUPPORT_URL}}" target="_blank">{% trans "support" %}</a><span class="link-separator"> |</span>
- {% endif %}
- {% spaceless %}
- <a href=
- {% if settings.CONTACT_URL %}
- "{{settings.CONTACT_URL}}"
- target="_blank">
- {% else %}
- "{% url feedback %}?next={{request.path}}">
- {% endif %}
- {% trans "contact us" %}
- </a>
- {% endspaceless %}
- </div>
- <p>
- <a href="http://osqa.net" target="_blank" title="OSQA {{ settings.OSQA_VERSION }} ({{ settings.SVN_REVISION }})">
- powered by OSQA
- </a>
- </p>
- </div>
- <div id="licenseLogo">
- <a href="http://creativecommons.org/licenses/by/3.0/">
- <img src="{% media "/media/images/cc-wiki.png" %}" title="Creative Commons: Attribution - Share Alike" alt="cc-wiki" width="50" height="68" />
- </a>
- </div>
- </div>
+
+<div>
+ <div class="footerLinks" >
+ <a href="{% url about %}">{% trans "about" %}</a><span class="link-separator"> |</span>
+ <a href="{% url faq %}">{% trans "faq" %}</a><span class="link-separator"> |</span>
+ <a href="{% url privacy %}">{% trans "privacy" %}</a><span class="link-separator"> |</span>
+ {% if settings.SUPPORT_URL %}
+ <a href="{{settings.SUPPORT_URL}}" target="_blank">{% trans "support" %}</a><span class="link-separator"> |</span>
+ {% endif %}
+ {% spaceless %}
+ <a href=
+ {% if settings.CONTACT_URL %}
+ "{{settings.CONTACT_URL}}"
+ target="_blank">
+ {% else %}
+ "{% url feedback %}?next={{request.path}}">
+ {% endif %}
+ {% trans "contact us" %}
+ </a>
+ {% endspaceless %}
+ </div>
+ <p>
+ <a href="http://osqa.net" target="_blank" title="OSQA {{ settings.OSQA_VERSION }} ({{ settings.SVN_REVISION }})">
+ powered by OSQA
+ </a>
+ </p>
+</div>
+ <div id="licenseLogo">
+ <a href="http://creativecommons.org/licenses/by/3.0/">
+ <img src="{% media "/media/images/cc-wiki.png" %}" title="Creative Commons: Attribution - Share Alike" alt="cc-wiki" width="50" height="68" />
+ </a>
+ </div>
{% block admincontent %}{% endblock %}
</div>
<div id="content-related">
+ {% if unsaved %}
+ <div id="changes-box" class="module">
+ <h2>{% trans "Unpublished changes" %}</h2>
+ <p>
+ <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" />
+ {% trans "Items marked with this icon have unpublished changes." %}
+ </p>
+ </div>
+ {% endif %}
<div id="basic-sets-menu" class="module">
<h2>{% trans "Basic settings" %}</h2>
<ul>
<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>
- <li><a href="{% url admin_set allsets.css.name %}">{{ allsets.css.title }}</a></li>
+ <li>
+ <a href="{% url admin_set allsets.css.name %}">{{ allsets.css.title }}</a>
+ {% if "css" in unsaved %}<img width="12" height="12" src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" alt="{% trans "Unsaved changes" %}" />{% endif %}
+ </li>
+ <li>
+ <a href="{% url admin_set allsets.headandfoot.name %}">{{ allsets.headandfoot.title }}</a>
+ {% if "headandfoot" in unsaved %}<img width="12" height="12" src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" alt="{% trans "Unsaved changes" %}" />{% endif %}
+ </li>
</ul>
</div>
<div id="other-sets-menu" class="module">
<h2>{% trans "Other settings" %}</h2>
<ul>
{% for set in othersets %}
- <li><a href="{% url admin_set set.name %}">{{ set.title }}</a></li>
+ <li>
+ <a href="{% url admin_set set.name %}">{{ set.title }}</a>
+ {% if set.name in unsaved %}<img width="12" height="12" src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon_alert.gif" alt="{% trans "Unsaved changes" %}" />{% endif %}
+ </li>
{% endfor %}
</ul>
</div>
<tr>\r
<th></th>\r
<td>\r
- <input id="submit" name="submit" type="submit" value="Save" />\r
+ <input id="submit" name="submit" type="submit" value="{% trans "Save" %}" onclick="this.form.target=''; return true;" />\r
+ {% if form.set.can_preview %}\r
+ <input id="preview" name="preview" type="submit" value="{% trans "Preview" %}" onclick="this.form.target='_blank'; return true;" />\r
+ {% if form.set.name in unsaved %}\r
+ <input id="reset" name="reset" type="submit" value="{% trans "Reset Changes" %}" onclick="this.form.target=''; return true;" />\r
+ {% endif %}\r
+ {% endif %}\r
</td>\r
</tr>\r
</table>\r
return number
except:
return number
+
+@register.filter
+def or_preview(setting, request):
+ if request.user.is_superuser:
+ previewing = request.session.get('previewing_settings', {})
+ if setting.name in previewing:
+ return previewing[setting.name]
+
+ return setting.value
context['othersets'] = sorted(
[s for s in Setting.sets.values() if not s.name in
('basic', 'users', 'email', 'paths', 'extkeys', 'repgain', 'minrep', 'voting', 'badges', 'about', 'faq', 'sidebar',
- 'form', 'moderation', 'css')]
+ 'form', 'moderation', 'css', 'headandfoot')]
, lambda s1, s2: s1.weight - s2.weight)
+
+ unsaved = request.session.get('previewing_settings', {})
+ context['unsaved'] = set([getattr(settings, s).set.name for s in unsaved.keys() if hasattr(settings, s)])
+
+
return render_to_response(template, context, context_instance=RequestContext(request))
else:
return res
@admin_page
def settings_set(request, set_name):
- set = Setting.sets.get(set_name, None)
+ set = Setting.sets.get(set_name, {})
+ current_preview = request.session.get('previewing_settings', {})
if set is None:
raise Http404
form = SettingsSetForm(set, data=request.POST, files=request.FILES)
if form.is_valid():
- form.save()
- request.user.message_set.create(message=_("'%s' settings saved succesfully") % set_name)
+ if 'preview' in request.POST:
+ current_preview.update(form.cleaned_data)
+ request.session['previewing_settings'] = current_preview
+
+ return HttpResponseRedirect(reverse('index'))
+ else:
+ for s in set:
+ current_preview.pop(s.name, None)
+
+ request.session['previewing_settings'] = current_preview
+
+ if not 'reset' in request.POST:
+ form.save()
+ request.user.message_set.create(message=_("'%s' settings saved succesfully") % set_name)
- if set_name in ('minrep', 'badges', 'repgain'):
- settings.SETTINGS_PACK.set_value("custom")
+ if set_name in ('minrep', 'badges', 'repgain'):
+ settings.SETTINGS_PACK.set_value("custom")
- return HttpResponseRedirect(reverse('admin_set', args=[set_name]))
+ return HttpResponseRedirect(reverse('admin_set', args=[set_name]))
else:
- form = SettingsSetForm(set)
+ form = SettingsSetForm(set, unsaved=current_preview)
return 'osqaadmin/set.html', {
'form': form,
from forum import settings
from forum.utils.mail import send_template_email
from django.utils.safestring import mark_safe
+from forum.templatetags.extra_filters import or_preview
import re
def favicon(request):
return HttpResponseRedirect(str(settings.APP_FAVICON))
def custom_css(request):
- return HttpResponse(unicode(settings.CUSTOM_CSS), mimetype="text/css")
+ return HttpResponse(or_preview(settings.CUSTOM_CSS, request), mimetype="text/css")
def static(request, title, content):
return render_to_response('static.html', {'content' : content, 'title': title}, context_instance=RequestContext(request))