Refactor various site views into more generic locations, in preparation for
using access permissions to decide the fuctionality in the view, instead of
having lots of cut-and-paste copies of the same view functions.
site/home.py into more generic home.py
site/settings.py into more generic settings.py
site/docs/list.py into more generic docs/list.py
site/docs/edit.py into more generic docs/edit.py
Patch by: Todd Larsen
Review by: to-be-reviewed
--- a/app/soc/logic/key_name.py Sat Oct 18 04:56:39 2008 +0000
+++ b/app/soc/logic/key_name.py Sat Oct 18 05:11:37 2008 +0000
@@ -67,10 +67,10 @@
if not path:
raise Error('"path" must be non-False: "%s"' % path)
- return 'SiteSettings:%s' % path
+ return nameHomeSettings(path, entity_type='SiteSettings')
-def nameHomeSettings(path):
+def nameHomeSettings(path, entity_type='HomeSettings'):
"""Returns a HomeSettings key name constructed from a supplied path.
Raises:
@@ -79,7 +79,7 @@
if not path:
raise Error('"path" must be non-False: "%s"' % path)
- return 'HomeSettings:%s' % path
+ return '%s:%s' % (entity_type, path)
def nameUser(email):
--- a/app/soc/logic/site/map.py Sat Oct 18 04:56:39 2008 +0000
+++ b/app/soc/logic/site/map.py Sat Oct 18 05:11:37 2008 +0000
@@ -30,15 +30,23 @@
from django.conf.urls import defaults
from django.utils import datastructures
+from soc.logic import models
from soc.logic import path_link_name
from soc.logic.site import page
+import soc.logic.models.site_settings
+
# Home Page view
home = page.Page(
page.Url(
r'^$',
- 'soc.views.site.home.public'),
+ 'soc.views.home.public',
+ kwargs={
+ 'path': models.site_settings.logic.DEF_SITE_SETTINGS_PATH,
+ 'entity_type': 'SiteSettings',
+ 'template': 'soc/site/home/public.html',
+ }),
'Google Open Source Programs',
# it should be obvious that every page comes from the home page
in_breadcrumb=False)
@@ -91,7 +99,12 @@
site_home = page.Page(
page.Url(
r'^site/home$',
- 'soc.views.site.home.public'),
+ 'soc.views.home.public',
+ kwargs={
+ 'path': models.site_settings.logic.DEF_SITE_SETTINGS_PATH,
+ 'entity_type': 'SiteSettings',
+ 'template': 'soc/site/home/public.html',
+ }),
'Google Open Source Programs',
# it should be obvious that every page comes from the home page
in_breadcrumb=False)
@@ -99,7 +112,11 @@
site_settings_edit = page.Page(
page.Url(
r'^site/settings/edit$',
- 'soc.views.site.settings.edit'),
+ 'soc.views.settings.edit',
+ kwargs={
+ 'path': models.site_settings.logic.DEF_SITE_SETTINGS_PATH,
+ 'logic': models.site_settings.logic,
+ }),
'Site: Settings',
short_name='Site Settings',
parent=home)
@@ -160,32 +177,32 @@
site_docs_create = page.Page(
page.Url(
- r'^site/docs/edit$',
- 'soc.views.site.docs.edit.create'),
+ r'^docs/edit$',
+ 'soc.views.docs.edit.create'),
'Site: Create New Document',
'Create Site Document',
parent=site_docs_sub_menu)
site_docs_edit = page.Page(
page.Url(
- r'^site/docs/edit/%s$' % path_link_name.PATH_LINKNAME_ARGS_PATTERN,
- 'soc.views.site.docs.edit.edit'),
+ r'^docs/edit/%s$' % path_link_name.PATH_LINKNAME_ARGS_PATTERN,
+ 'soc.views.docs.edit.edit'),
'Site: Modify Existing Document',
short_name='Modify Site Document',
parent=site_docs_sub_menu)
site_docs_delete = page.Page(
page.Url(
- r'^site/docs/%s/delete$' % path_link_name.PATH_LINKNAME_ARGS_PATTERN,
- 'soc.views.site.docs.edit.delete'),
+ r'^docs/delete/%s$' % path_link_name.PATH_LINKNAME_ARGS_PATTERN,
+ 'soc.views.docs.edit.delete'),
'Site: Delete Existing Document',
short_name='Delete Site Document',
parent=site_docs_sub_menu)
site_docs_list = page.Page(
page.Url(
- r'^site/docs/list$',
- 'soc.views.site.docs.list.all'),
+ r'^docs/list$',
+ 'soc.views.docs.list.all'),
'Site: List of Documents',
short_name='List Site Documents',
parent=site_docs_sub_menu)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/templates/soc/docs/edit.html Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,59 @@
+{% extends "soc/base.html" %}
+{% comment %}
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+
+{% block scripts %}
+ <script type="text/javascript" src="/tiny_mce/tiny_mce_src.js"></script>
+{% endblock %}
+{% block header_title %}
+{{ page.short_name }}
+ {% if existing_doc %}
+ <a href="/docs/show/{{ existing_doc.partial_path }}/{{ existing_doc.link_name }}">"{{ existing_doc.title }}"</a>
+ {% endif %}
+{% endblock %}
+
+{% block body %}
+<p>
+<p>
+{% block instructions %}
+Please use this form to edit the document.
+{% endblock %}
+</p>
+<form method="POST">
+ <table>
+ {{ form.as_table }}
+ <tr>
+ <td colspan="4"> </td>
+ </tr>
+ </table>
+ <table>
+ <tr>
+ {% block submit_buttons %}
+ <td>
+ <input style="font-weight: bold" type="submit" value="Save Changes"/></span>
+ </td>
+ <td>
+ <input type="button" onclick="location.href='/'" value="Cancel"/>
+ </td>
+ {% if existing_doc %}
+ <td>
+ <input type="button" onclick="location.href='/docs/delete/{{ existing_doc.partial_path }}/{{ existing_doc.link_name }}'" value="Delete"/>
+ </td>
+ {% endif %}
+ {% endblock %}
+ </tr>
+ </table>
+</form>
+</p>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/templates/soc/docs/list/all.html Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,24 @@
+{% extends "soc/base.html" %}
+{% comment %}
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+{% load forms_helpers %}
+{% block body %}
+<p>
+<p>
+{% block instructions %}
+{% endblock %}
+</p>
+{% include list_main %}
+</p>
+{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/templates/soc/docs/list/docs_heading.html Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,9 @@
+<tr align="left">
+ <th>Path</th>
+ <th>Title</th>
+ <th>Linkname</th>
+ <th>Featured</th>
+ <th>Created By</th>
+ <th>Created On</th>
+ <th>Modified</th>
+</tr>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/templates/soc/docs/list/docs_row.html Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,15 @@
+<tr class="off" onmouseover="this.className='on'" onmouseout="this.className='off'"
+onclick="document.location.href='/site/docs/edit/{{ data_element.partial_path }}/{{ data_element.link_name }}'" name="name">
+ <td align="right">
+ <div class="title">
+ <a class="noul"
+ href="/docs/edit/{{ data_element.partial_path }}/{{ data_element.link_name }}">{{ data_element.partial_path}}/{{ data_element.link_name }}</a>
+ </div>
+ </td>
+ <td><div class="title">{{ data_element.title }}</div></td>
+ <td><div class="link_name">{{ data_element.link_name }}</div></td>
+ <td><div class="featured">{{ data_element.is_featured }}</div></td>
+ <td><div class="author">{{ data_element.author.link_name }}</div></td>
+ <td><div class="created">{{ data_element.created }}</div></td>
+ <td><div class="modified">{{ data_element.modified }}</div></td>
+</tr>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/templates/soc/home/public.html Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,63 @@
+{% extends "soc/base.html" %}
+{% comment %}
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+
+{% block scripts %}
+{% if home_settings.feed_url %}
+ <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+ <script type="text/javascript" src="/soc/content/js/blog.js"></script>
+ <script type="text/javascript">
+
+ google.load("feeds", "1");
+
+ function initialize() {
+ var blog = new BlogPreview(document.getElementById("blog"));
+ blog.show("{{ home_settings.feed_url }}");
+ }
+ google.setOnLoadCallback(initialize);
+
+ </script>
+{% endif %}
+{% endblock %}
+
+{% block page_title %}
+{% if home_document %}
+{{ home_document.title }}
+{% else %}
+{{ page.long_name }}
+{% endif %}
+{% endblock %}
+
+{% block header_title %}
+{% if home_document %}
+{{ home_document.short_name }}
+{% else %}
+{{ page.short_name }}
+{% endif %}
+{% endblock %}
+
+{% block body %}
+ {% if home_document %}
+ {{ home_document.content|safe }}
+ <div id="lastmodified">Last updated on: {{ home_document.modified }}</div>
+ {% else %}
+{% block missing_doc %}
+This is the default home page can be edited via Settings.
+{% endblock %}
+<p>
+ {% endif %}
+ {% if home_settings.feed_url %}
+ <div id="blog"></div>
+ {% endif %}
+{% endblock %}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/templates/soc/settings/edit.html Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,111 @@
+{% extends "soc/base.html" %}
+{% comment %}
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+
+{% block body %}
+<p>
+<p>
+{% block instructions %}
+Please use this form to set basic home page settings.
+{% endblock %}
+</p>
+<p>
+</p>
+<form method="POST">
+ <table>
+ {{ settings_form.as_table }}
+{% if home_doc %}
+ <tr>
+ <td colspan="4"> </td>
+ </tr>
+{% comment %}
+TODO(tlarsen): OK, this is pretty lame as well. I think we need some sort
+ of "Document preview" that can be appended to the end of the page. Also,
+ There is way too much text on this page. Can a UI wizard please fix this
+ UI?
+{% endcomment %}
+ <tr>
+ <td colspan="4">
+An existing Document is currently selected to provide the body contents of the home page:
+ </td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td colspan="3">
+ {{ home_doc.title }}
+ </td>
+ </tr>
+ <tr>
+ <th>Path:</th>
+ <td colspan="2">
+ {{ home_doc.partial_path }}/{{ home_doc.link_name }}
+ </td>
+ </tr>
+ <tr>
+ <th>Created By:</th>
+ <td colspan="2">
+ {{ home_doc.author.link_name }}
+ </td>
+ </tr>
+ <tr>
+ <th>Created On:</th>
+ <td colspan="2">
+ {{ home_doc.created }}
+ </td>
+ </tr>
+ <tr>
+ <th>Modified:</th>
+ <td colspan="2">
+ {{ home_doc.modified }}
+ </td>
+ </tr>
+{% endif %}
+ <tr>
+ <td colspan="4">
+ <p>
+ Any existing Document (to which access is permitted) can be used as the body contents of the home page.
+ <ul>
+ <li>
+<a href="/docs/edit">Create a new Document to use for the home page content here.</a>
+ </li>
+ <li>
+<a href="/docs/list">Edit an existing Document to use for the home page content here.</a>
+ </li>
+ </ul>
+Then, specify the Document to use below:
+</p>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="4"> </td>
+ </tr>
+ {{ doc_select_form.as_table }}
+ <tr>
+ <td colspan="4"> </td>
+ </tr>
+ <table>
+ <tr>
+ {% block submit_buttons %}
+ <td>
+ <input style="font-weight: bold" type="submit" value="Save Changes"/></span>
+ </td>
+ <td>
+ <input type="button" onclick="location.href='/'" value="Cancel"/>
+ </td>
+ {% endblock %}
+ </tr>
+ </table>
+</form>
+</p>
+{% endblock %}
--- a/app/soc/templates/soc/site/docs/edit.html Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-{% extends "soc/base.html" %}
-{% comment %}
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-{% endcomment %}
-
-{% block scripts %}
- <script type="text/javascript" src="/tiny_mce/tiny_mce_src.js"></script>
-{% endblock %}
-{% block header_title %}
-{{ page.short_name }}
- {% if existing_doc %}
- <a href="/docs/show/{{ existing_doc.partial_path }}/{{ existing_doc.link_name }}">"{{ existing_doc.title }}"</a>
- {% endif %}
-{% endblock %}
-
-{% block body %}
-<p>
-<p>
-{% block instructions %}
-Please use this form to edit the document.
-{% endblock %}
-</p>
-<form method="POST">
- <table>
- {{ form.as_table }}
- <tr>
- <td colspan="4"> </td>
- </tr>
- </table>
- <table>
- <tr>
- {% block submit_buttons %}
- <td>
- <input style="font-weight: bold" type="submit" value="Save Changes"/></span>
- </td>
- <td>
- <input type="button" onclick="location.href='/'" value="Cancel"/>
- </td>
- {% if existing_doc %}
- <td>
- <input type="button" onclick="location.href='/site/docs/{{ existing_doc.partial_path }}/{{ existing_doc.link_name }}/delete'" value="Delete"/>
- </td>
- {% endif %}
- {% endblock %}
- </tr>
- </table>
-</form>
-</p>
-{% endblock %}
--- a/app/soc/templates/soc/site/docs/list/all.html Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-{% extends "soc/base.html" %}
-{% comment %}
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-{% endcomment %}
-{% load forms_helpers %}
-{% block body %}
-<p>
-<p>
-{% block instructions %}
-List of Documents in Google Open Source Programs.
-{% endblock %}
-</p>
-{% include list_main %}
-</p>
-{% endblock %}
\ No newline at end of file
--- a/app/soc/templates/soc/site/docs/list/docs_heading.html Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-<tr align="left">
- <th>Path</th>
- <th>Title</th>
- <th>Partial Path</th>
- <th>Linkname</th>
- <th>Featured</th>
- <th>Created By</th>
- <th>Created On</th>
- <th>Modified</th>
-</tr>
--- a/app/soc/templates/soc/site/docs/list/docs_row.html Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-<tr class="off" onmouseover="this.className='on'" onmouseout="this.className='off'"
-onclick="document.location.href='/site/docs/edit/{{ data_element.partial_path }}/{{ data_element.link_name }}'" name="name">
- <td align="right">
- <div class="title">
- <a class="noul"
- href="/site/docs/edit/{{ data_element.partial_path }}/{{ data_element.link_name }}">{{ data_element.partial_path}}/{{ data_element.link_name }}</a>
- </div>
- </td>
- <td><div class="title">{{ data_element.title }}</div></td>
- <td><div class="partial_path">{{ data_element.partial_path }}</div></td>
- <td><div class="link_name">{{ data_element.link_name }}</div></td>
- <td><div class="featured">{{ data_element.is_featured }}</div></td>
- <td><div class="author">{{ data_element.author.link_name }}</div></td>
- <td><div class="created">{{ data_element.created }}</div></td>
- <td><div class="modified">{{ data_element.modified }}</div></td>
-</tr>
--- a/app/soc/templates/soc/site/home/public.html Sat Oct 18 04:56:39 2008 +0000
+++ b/app/soc/templates/soc/site/home/public.html Sat Oct 18 05:11:37 2008 +0000
@@ -1,4 +1,4 @@
-{% extends "soc/base.html" %}
+{% extends "soc/home/public.html" %}
{% comment %}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,50 +13,10 @@
limitations under the License.
{% endcomment %}
-{% block scripts %}
-{% if site_settings.feed_url %}
- <script type="text/javascript" src="http://www.google.com/jsapi"></script>
- <script type="text/javascript" src="/soc/content/js/blog.js"></script>
- <script type="text/javascript">
-
- google.load("feeds", "1");
-
- function initialize() {
- var blog = new BlogPreview(document.getElementById("blog"));
- blog.show("{{ site_settings.feed_url }}");
- }
- google.setOnLoadCallback(initialize);
-
- </script>
-{% endif %}
-{% endblock %}
-
-{% block page_title %}
-{% if site_document %}
-{{ site_document.title }}
-{% else %}
-Default Title
-{% endif %}
-{% endblock %}
-
-{% block header_title %}
-{% if site_document %}
-{{ site_document.title }}
-{% else %}
-Default Header
-{% endif %}
-{% endblock %}
-
-{% block body %}
- {% if site_document %}
- {{ site_document.content|safe }}
- <div id="lastmodified">Last updated on: {{ site_document.modified }}</div>
- {% else %}
-This is the default site home page that can be configured via the <a href="/site/settings/edit">Site Settings</a> interface.
-The <a href="/site/settings/edit">Site Settings</a> interface also provides a mechanism to select a feed to be displayed here.
+{% block missing_doc %}
+The contents of this default Site home page can be changed by editing the
+<a href="/site/docs/edit/site/home"><code>site/home</code> Document</a>.
+Other elements of this page, such as a feed to be displayed below this
+content, can be set using the <a href="/site/settings/edit">Site Settings</a> interface.
You need to sign in as site Developer in order to change <a href="/site/settings/edit">Site Settings</a>.
- {% endif %}
- {% if site_settings.feed_url %}
- <div id="blog"></div>
- {% endif %}
{% endblock %}
\ No newline at end of file
--- a/app/soc/templates/soc/site/settings/edit.html Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-{% extends "soc/base.html" %}
-{% comment %}
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-{% endcomment %}
-
-{% block scripts %}
- <script type="text/javascript" src="/tiny_mce/tiny_mce_src.js"></script>
-{% endblock %}
-
-{% block page_title %}Site Settings{% endblock %}
-{% block header_title %}
-Site Settings
-{% endblock %}
-
-{% block body %}
-<p>
-<p>
-{% block instructions %}
-Please use this form to set basic site settings.
-{% endblock %}
-</p>
-<form method="POST">
- <table>
- {{ document_form.as_table }}
- {{ settings_form.as_table }}
- <tr>
- <td colspan="4"> </td>
- </tr>
- <table>
- <tr>
- {% block submit_buttons %}
- <td>
- <input style="font-weight: bold" type="submit" value="Save Changes"/></span>
- </td>
- <td>
- <input type="button" onclick="location.href='/'" value="Cancel"/>
- </td>
- {% endblock %}
- </tr>
- </table>
-</form>
-</p>
-{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/views/docs/edit.py Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,331 @@
+#!/usr/bin/python2.5
+#
+# Copyright 2008 the Melange authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Views for editing and examining Documents.
+"""
+
+__authors__ = [
+ '"Todd Larsen" <tlarsen@google.com>',
+ ]
+
+
+from google.appengine.api import users
+
+from django import forms
+from django import http
+from django.utils.translation import ugettext_lazy
+
+from soc.logic import models
+from soc.logic import out_of_band
+from soc.logic import path_link_name
+from soc.logic.models import document
+
+from soc.views import helper
+from soc.views import simple
+from soc.views.helper import access
+from soc.views.helper import decorators
+from soc.views.user import profile
+
+import soc.models.document
+import soc.views.helper.forms
+import soc.views.helper.requests
+import soc.views.helper.responses
+import soc.views.helper.widgets
+import soc.views.out_of_band
+
+
+DEF_CREATE_NEW_DOC_MSG = ' You can create a new document by visiting the' \
+ ' <a href="/docs/edit">Create ' \
+ 'a New Document</a> page.'
+
+SUBMIT_MESSAGES = (
+ ugettext_lazy('Document saved.'),
+)
+
+
+def getDocForForm(form):
+ """Extracts doc fields from a form and creates a new doc from it
+ """
+
+ user = users.get_current_user()
+ if user:
+ email = user.email()
+ else:
+ email = None
+
+ partial_path = form.cleaned_data.get('partial_path')
+ link_name = form.cleaned_data.get('link_name')
+
+ properties = {}
+ properties['partial_path'] = partial_path
+ properties['link_name'] = link_name
+ properties['title'] = form.cleaned_data.get('title')
+ properties['short_name'] = form.cleaned_data.get('short_name')
+ properties['content'] = form.cleaned_data.get('content')
+ properties['author'] = models.user.logic.getFromFields(email=email)
+ properties['is_featured'] = form.cleaned_data.get('is_featured')
+
+ doc = document.logic.updateOrCreateFromFields(properties,
+ partial_path=partial_path,
+ link_name=link_name)
+ return doc
+
+
+class CreateForm(helper.forms.DbModelForm):
+ """Django form displayed when Developer creates a Document.
+ """
+ content = forms.fields.CharField(widget=helper.widgets.TinyMCE(
+ attrs={'rows':10, 'cols':40}))
+
+ class Meta:
+ model = soc.models.document.Document
+
+ #: list of model fields which will *not* be gathered by the form
+ exclude = ['inheritance_line', 'author', 'created', 'modified']
+
+ def clean_partial_path(self):
+ partial_path = self.cleaned_data.get('partial_path')
+ # TODO(tlarsen): combine path and link_name and check for uniqueness
+ return partial_path
+
+ def clean_link_name(self):
+ link_name = self.cleaned_data.get('link_name')
+ # TODO(tlarsen): combine path and link_name and check for uniqueness
+ return link_name
+
+
+DEF_DOCS_CREATE_TMPL = 'soc/docs/edit.html'
+
+@decorators.view
+def create(request, page=None, template=DEF_DOCS_CREATE_TMPL):
+ """View to create a new Document entity.
+
+ Args:
+ request: the standard django request object
+ page: a soc.logic.site.page.Page object which is abstraction that combines
+ a Django view with sidebar menu info
+ template: the "sibling" template (or a search list of such templates)
+ from which to construct the public.html template name (or names)
+
+ Returns:
+ A subclass of django.http.HttpResponse which either contains the form to
+ be filled out, or a redirect to the correct view in the interface.
+ """
+
+ try:
+ access.checkIsDeveloper(request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ # TODO(tlarsen): change this to just limit the Documents that can be
+ # created by the User in their current Role
+ return alt_response.response()
+
+ # create default template context for use with any templates
+ context = helper.responses.getUniversalContext(request)
+ context['page'] = page
+
+ if request.method == 'POST':
+ form = CreateForm(request.POST)
+
+ if form.is_valid():
+ doc = getDocForForm(form)
+
+ if not doc:
+ return http.HttpResponseRedirect('/')
+
+ new_path = path_link_name.combinePath([doc.partial_path, doc.link_name])
+
+ # redirect to new /docs/edit/new_path?s=0
+ # (causes 'Profile saved' message to be displayed)
+ return helper.responses.redirectToChangedSuffix(
+ request, None, new_path,
+ params=profile.SUBMIT_PROFILE_SAVED_PARAMS)
+ else: # method == 'GET':
+ # no link name specified, so start with an empty form
+ form = CreateForm()
+
+ context['form'] = form
+
+ return helper.responses.respond(request, template, context)
+
+
+DEF_DOCS_EDIT_TMPL = 'soc/docs/edit.html'
+
+class EditForm(CreateForm):
+ """Django form displayed a Document is edited.
+ """
+ doc_key_name = forms.fields.CharField(widget=forms.HiddenInput)
+ created_by = forms.fields.CharField(widget=helper.widgets.ReadOnlyInput(),
+ required=False)
+
+
+@decorators.view
+def edit(request, page=None, partial_path=None, link_name=None,
+ template=DEF_DOCS_EDIT_TMPL):
+ """View to modify the properties of a Document Model entity.
+
+ Args:
+ request: the standard django request object
+ page: a soc.logic.site.page.Page object which is abstraction that combines
+ a Django view with sidebar menu info
+ partial_path: the Document's site-unique "path" extracted from the URL,
+ minus the trailing link_name
+ link_name: the last portion of the Document's site-unique "path"
+ extracted from the URL
+ template: the "sibling" template (or a search list of such templates)
+ from which to construct the public.html template name (or names)
+
+ Returns:
+ A subclass of django.http.HttpResponse which either contains the form to
+ be filled out, or a redirect to the correct view in the interface.
+ """
+
+ try:
+ access.checkIsDeveloper(request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ # TODO(tlarsen): change this to just limit the Documents that can be
+ # edited by the User in their current Role
+ return alt_response.response()
+
+ # create default template context for use with any templates
+ context = helper.responses.getUniversalContext(request)
+ context['page'] = page
+
+ doc = None # assume that no Document entity will be found
+
+ path = path_link_name.combinePath([partial_path, link_name])
+
+ # try to fetch Document entity corresponding to path if one exists
+ try:
+ if path:
+ doc = document.logic.getFromFields(partial_path=partial_path,
+ link_name=link_name)
+ except out_of_band.ErrorResponse, error:
+ # show custom 404 page when path doesn't exist in Datastore
+ error.message = error.message + DEF_CREATE_NEW_DOC_MSG
+ return simple.errorResponse(request, page, error, template, context)
+
+ if request.method == 'POST':
+ form = EditForm(request.POST)
+
+ if form.is_valid():
+ doc = getDocForForm(form)
+
+ if not doc:
+ return http.HttpResponseRedirect('/')
+
+ new_path = path_link_name.combinePath([doc.partial_path, doc.link_name])
+
+ # redirect to new /docs/edit/new_path?s=0
+ # (causes 'Profile saved' message to be displayed)
+ return helper.responses.redirectToChangedSuffix(
+ request, path, new_path,
+ params=profile.SUBMIT_PROFILE_SAVED_PARAMS)
+ else: # method == 'GET':
+ # try to fetch Document entity corresponding to path if one exists
+ if path:
+ if doc:
+ # is 'Profile saved' parameter present, but referrer was not ourself?
+ # (e.g. someone bookmarked the GET that followed the POST submit)
+ if (request.GET.get(profile.SUBMIT_MSG_PARAM_NAME)
+ and (not helper.requests.isReferrerSelf(request, suffix=path))):
+ # redirect to aggressively remove 'Profile saved' query parameter
+ return http.HttpResponseRedirect(request.path)
+
+ # referrer was us, so select which submit message to display
+ # (may display no message if ?s=0 parameter is not present)
+ context['notice'] = (
+ helper.requests.getSingleIndexedParamValue(
+ request, profile.SUBMIT_MSG_PARAM_NAME,
+ values=SUBMIT_MESSAGES))
+
+ # populate form with the existing Document entity
+ author_link_name = doc.author.link_name
+ form = EditForm(initial={'doc_key_name': doc.key().name(),
+ 'title': doc.title, 'partial_path': doc.partial_path,
+ 'link_name': doc.link_name, 'short_name': doc.short_name,
+ 'content': doc.content, 'author': doc.author,
+ 'is_featured': doc.is_featured, 'created_by': author_link_name})
+ else:
+ if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME):
+ # redirect to aggressively remove 'Profile saved' query parameter
+ return http.HttpResponseRedirect(request.path)
+
+ context['lookup_error'] = ugettext_lazy(
+ 'Document with that path not found.')
+ form = EditForm(initial={'link_name': link_name})
+ else: # no link name specified in the URL
+ if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME):
+ # redirect to aggressively remove 'Profile saved' query parameter
+ return http.HttpResponseRedirect(request.path)
+
+ # no link name specified, so start with an empty form
+ form = EditForm()
+
+ context.update({'form': form,
+ 'existing_doc': doc})
+
+ return helper.responses.respond(request, template, context)
+
+
+@decorators.view
+def delete(request, page=None, partial_path=None, link_name=None,
+ template=DEF_DOCS_EDIT_TMPL):
+ """Request handler to delete Document Model entity.
+
+ Args:
+ request: the standard django request object
+ page: a soc.logic.site.page.Page object which is abstraction that combines
+ a Django view with sidebar menu info
+ partial_path: the Document's site-unique "path" extracted from the URL,
+ minus the trailing link_name
+ link_name: the last portion of the Document's site-unique "path"
+ extracted from the URL
+ template: the "sibling" template (or a search list of such templates)
+ from which to construct the public.html template name (or names)
+
+ Returns:
+ A subclass of django.http.HttpResponse which redirects
+ to /site/docs/list.
+ """
+
+ try:
+ access.checkIsDeveloper(request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ # TODO(tlarsen): change this to just limit the Documents that can be
+ # deleted by the User in their current Role
+ return alt_response.response()
+
+ # create default template context for use with any templates
+ context = helper.responses.getUniversalContext(request)
+ context['page'] = page
+
+ existing_doc = None
+ path = path_link_name.combinePath([partial_path, link_name])
+
+ # try to fetch Document entity corresponding to path if one exists
+ try:
+ if path:
+ existing_doc = document.logic.getFromFields(partial_path=partial_path,
+ link_name=link_name)
+ except out_of_band.ErrorResponse, error:
+ # show custom 404 page when path doesn't exist in Datastore
+ error.message = error.message + DEF_CREATE_NEW_DOC_MSG
+ return simple.errorResponse(request, page, error, template, context)
+
+ if existing_doc:
+ document.logic.delete(existing_doc)
+
+ return http.HttpResponseRedirect('/docs/list')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/views/docs/list.py Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,89 @@
+#!/usr/bin/python2.5
+#
+# Copyright 2008 the Melange authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Views for listing Documents.
+"""
+
+__authors__ = [
+ '"Todd Larsen" <tlarsen@google.com>',
+ ]
+
+
+from soc.logic.models import work
+from soc.views import helper
+from soc.views.helper import access
+from soc.views.helper import decorators
+
+import soc.logic
+import soc.models.document
+import soc.views.helper.lists
+import soc.views.helper.responses
+import soc.views.out_of_band
+
+
+DEF_DOCS_LIST_ALL_TMPL = 'soc/docs/list/all.html'
+
+
+@decorators.view
+def all(request, page=None, templates={}):
+ """Show a list of all Documents (limit rows per page).
+
+ Args:
+ request: the standard Django HTTP request object
+ page: a soc.logic.site.page.Page object which is abstraction that combines
+ a Django view with sidebar menu info
+ template: the "sibling" template (or a search list of such templates)
+ from which to construct an alternate template name (or names)
+
+ Returns:
+ A subclass of django.http.HttpResponse which either contains the form to
+ be filled out, or a redirect to the correct view in the interface.
+ """
+
+ try:
+ access.checkIsDeveloper(request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ return alt_response.response()
+
+ # create default template context for use with any templates
+ context = helper.responses.getUniversalContext(request)
+ context['page'] = page
+
+ offset, limit = helper.lists.cleanListParameters(
+ offset=request.GET.get('offset'), limit=request.GET.get('limit'))
+
+ # Fetch one more to see if there should be a 'next' link
+ docs = work.logic.getForLimitAndOffset(limit + 1, offset=offset)
+
+ context['pagination_form'] = helper.lists.makePaginationForm(request, limit)
+
+ list_templates = {
+ 'list_main': templates.get('list_main',
+ 'soc/list/list_main.html'),
+ 'list_pagination': templates.get('list_pagination',
+ 'soc/list/list_pagination.html'),
+ 'list_row': templates.get('list_row',
+ 'soc/docs/list/docs_row.html'),
+ 'list_heading': templates.get('list_heading',
+ 'soc/docs/list/docs_heading.html'),
+ }
+
+ context = helper.lists.setList(
+ request, context, docs,
+ offset=offset, limit=limit, list_templates=list_templates)
+
+ template = templates.get('all', DEF_DOCS_LIST_ALL_TMPL)
+ return helper.responses.respond(request, template, context)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/views/home.py Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,76 @@
+#!/usr/bin/python2.5
+#
+# Copyright 2008 the Melange authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Base for all (Site, Group, etc.) home page views.
+
+public: how the general public sees a "home" page
+"""
+
+__authors__ = [
+ '"Todd Larsen" <tlarsen@google.com>',
+ '"Pawel Solyga" <pawel.solyga@gmail.com>',
+ ]
+
+
+from google.appengine.ext import db
+
+from soc.logic import models
+from soc.views import helper
+from soc.views.helper import decorators
+
+import soc.logic.models.home_settings
+import soc.views.helper.responses
+import soc.views.helper.templates
+
+
+DEF_HOME_PUBLIC_TMPL = 'soc/home/public.html'
+
+@decorators.view
+def public(request, page=None, path=None, entity_type='HomeSettings',
+ template=DEF_HOME_PUBLIC_TMPL):
+ """How the "general public" sees a "home" page.
+
+ Args:
+ request: the standard django request object.
+ page: a soc.logic.site.page.Page object which is abstraction that
+ combines a Django view with sidebar menu info
+ path: path (entire "scoped" portion combined with the link_name)
+ used to retrieve the Group's "home" settings
+ template: the template path to use for rendering the template.
+
+ Returns:
+ A subclass of django.http.HttpResponse with generated template.
+ """
+ # create default template context for use with any templates
+ context = helper.responses.getUniversalContext(request)
+
+ settings = models.home_settings.logic.getFromFields(
+ path=path, entity_type=entity_type)
+
+ if settings:
+ context['home_settings'] = settings
+
+ # check if ReferenceProperty to home Document is valid
+ try:
+ home_doc = settings.home
+ except db.Error:
+ home_doc = None
+
+ if home_doc:
+ home_doc.content = helper.templates.unescape(home_doc.content)
+ context['home_document'] = home_doc
+
+ return helper.responses.respond(request, template, context=context)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/soc/views/settings.py Sat Oct 18 05:11:37 2008 +0000
@@ -0,0 +1,182 @@
+#!/usr/bin/python2.5
+#
+# Copyright 2008 the Melange authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Home page settings views.
+
+edit: settings view for authorized Developers, Administrators, etc.
+"""
+
+__authors__ = [
+ '"Pawel Solyga" <pawel.solyga@gmail.com>',
+ '"Todd Larsen" <tlarsen@google.com>',
+ ]
+
+
+from google.appengine.api import users
+from google.appengine.ext import db
+
+from django import forms
+from django.utils.translation import ugettext_lazy
+
+from soc.logic import models
+from soc.logic import validate
+from soc.logic.models import document
+from soc.views import helper
+from soc.views.helper import access
+from soc.views.helper import decorators
+
+import soc.logic.models.home_settings
+import soc.models.document
+import soc.models.home_settings
+import soc.models.work
+import soc.views.helper.forms
+import soc.views.helper.responses
+import soc.views.helper.templates
+import soc.views.helper.widgets
+import soc.views.out_of_band
+
+
+class SettingsForm(helper.forms.DbModelForm):
+ """Django form displayed when creating or editing Settings.
+ """
+
+ class Meta:
+ """Inner Meta class that defines some behavior for the form.
+ """
+ #: db.Model subclass for which the form will gather information
+ model = soc.models.home_settings.HomeSettings
+
+ #: list of model fields which will *not* be gathered by the form
+ exclude = ['inheritance_line', 'home']
+
+ def clean_feed_url(self):
+ feed_url = self.cleaned_data.get('feed_url')
+
+ if feed_url == '':
+ # feed url not supplied (which is OK), so do not try to validate it
+ return None
+
+ if not validate.isFeedURLValid(feed_url):
+ raise forms.ValidationError('This URL is not a valid ATOM or RSS feed.')
+
+ return feed_url
+
+
+class DocSelectForm(helper.forms.DbModelForm):
+ """Django form displayed to select a Document.
+ """
+
+ # TODO(tlarsen): partial_path will be a hard-coded read-only
+ # field for some (most?) User Roles
+ partial_path = forms.CharField(required=False,
+ label=soc.models.work.Work.partial_path.verbose_name,
+ help_text=soc.models.work.Work.partial_path.help_text)
+
+ # TODO(tlarsen): actually, using these two text fields to specify
+ # the Document is pretty cheesy; this needs to be some much better
+ # Role-scoped Document selector that we don't have yet
+ link_name = forms.CharField(required=False,
+ label=soc.models.work.Work.link_name.verbose_name,
+ help_text=soc.models.work.Work.link_name.help_text)
+
+ class Meta:
+ model = None
+
+
+DEF_HOME_EDIT_TMPL = 'soc/settings/edit.html'
+
+@decorators.view
+def edit(request, page=None, path=None, logic=models.home_settings.logic,
+ template=DEF_HOME_EDIT_TMPL):
+ """View for authorized User to edit contents of a home page.
+
+ Args:
+ request: the standard django request object.
+ page: a soc.logic.site.page.Page object which is abstraction that
+ combines a Django view with sidebar menu info
+ template: the template path to use for rendering the template.
+
+ Returns:
+ A subclass of django.http.HttpResponse with generated template.
+ """
+
+ try:
+ access.checkIsDeveloper(request)
+ except soc.views.out_of_band.AccessViolationResponse, alt_response:
+ # TODO(tlarsen): change this to just limit Settings paths that can be
+ # viewed or modified by the User in their current Role
+ return alt_response.response()
+
+ # create default template context for use with any templates
+ context = helper.responses.getUniversalContext(request)
+ context['page'] = page
+
+ settings_form = None
+ doc_select_form = None
+ home_doc = None
+
+ if request.method == 'POST':
+ settings_form = SettingsForm(request.POST)
+ doc_select_form = DocSelectForm(request.POST)
+
+ if doc_select_form.is_valid() and settings_form.is_valid():
+ fields = {'feed_url': settings_form.cleaned_data.get('feed_url')}
+ partial_path = doc_select_form.cleaned_data.get('partial_path')
+ link_name = doc_select_form.cleaned_data.get('link_name')
+
+ home_doc = document.logic.getFromFields(
+ partial_path=partial_path, link_name=link_name)
+
+ if home_doc:
+ fields['home'] = home_doc
+ context['notice'] = ugettext_lazy('Settings saved.')
+ else:
+ context['notice'] = ugettext_lazy('Document not specified or could not be found; other Settings saved.')
+
+ settings = logic.updateOrCreateFromFields(fields, path=path)
+
+ if settings.home:
+ home_doc = settings.home
+ else: # request.method == 'GET'
+ # try to fetch HomeSettings entity by unique key_name
+ settings = logic.getFromFields(path=path)
+
+ if settings:
+ # populate form with the existing HomeSettings entity
+ settings_form = SettingsForm(instance=settings)
+
+ # check if ReferenceProperty to home Document is valid
+ try:
+ home_doc = settings.home
+ except db.Error:
+ pass
+
+ if home_doc:
+ doc_select_form = DocSelectForm(initial={
+ 'partial_path': home_doc.partial_path,
+ 'link_name': home_doc.link_name})
+ else:
+ doc_select_form = DocSelectForm()
+ else:
+ # no SiteSettings entity exists for this key_name, so show a blank form
+ settings_form = SettingsForm()
+ doc_select_form = DocSelectForm()
+
+ context.update({'settings_form': settings_form,
+ 'doc_select_form': doc_select_form,
+ 'home_doc': home_doc})
+
+ return helper.responses.respond(request, template, context)
--- a/app/soc/views/site/docs/edit.py Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-#!/usr/bin/python2.5
-#
-# Copyright 2008 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Developer views for editing and examining Documents.
-"""
-
-__authors__ = [
- '"Todd Larsen" <tlarsen@google.com>',
- ]
-
-
-from google.appengine.api import users
-
-from django import forms
-from django import http
-from django.utils.translation import ugettext_lazy
-
-from soc.logic import models
-from soc.logic import out_of_band
-from soc.logic import path_link_name
-from soc.logic.models import document
-
-from soc.views import helper
-from soc.views import simple
-from soc.views.helper import access
-from soc.views.helper import decorators
-from soc.views.user import profile
-
-import soc.models.document
-import soc.views.helper.forms
-import soc.views.helper.requests
-import soc.views.helper.responses
-import soc.views.helper.widgets
-import soc.views.out_of_band
-
-
-DEF_CREATE_NEW_DOC_MSG = ' You can create a new document by visiting the' \
- ' <a href="/site/docs/edit">Create ' \
- 'a New Document</a> page.'
-
-SUBMIT_MESSAGES = (
- ugettext_lazy('Document saved.'),
-)
-
-
-def getDocForForm(form):
- """Extracts doc fields from a form and creates a new doc from it
- """
-
- user = users.get_current_user()
- if user:
- email = user.email()
- else:
- email = None
-
- partial_path = form.cleaned_data.get('partial_path')
- link_name = form.cleaned_data.get('link_name')
-
- properties = {}
- properties['partial_path'] = partial_path
- properties['link_name'] = link_name
- properties['title'] = form.cleaned_data.get('title')
- properties['short_name'] = form.cleaned_data.get('short_name')
- properties['content'] = form.cleaned_data.get('content')
- properties['author'] = models.user.logic.getFromFields(email=email)
- properties['is_featured'] = form.cleaned_data.get('is_featured')
-
- doc = document.logic.updateOrCreateFromFields(properties,
- partial_path=partial_path,
- link_name=link_name)
- return doc
-
-
-class CreateForm(helper.forms.DbModelForm):
- """Django form displayed when Developer creates a Document.
- """
- content = forms.fields.CharField(widget=helper.widgets.TinyMCE(
- attrs={'rows':10, 'cols':40}))
-
- class Meta:
- model = soc.models.document.Document
-
- #: list of model fields which will *not* be gathered by the form
- exclude = ['inheritance_line', 'author', 'created', 'modified']
-
- def clean_partial_path(self):
- partial_path = self.cleaned_data.get('partial_path')
- # TODO(tlarsen): combine path and link_name and check for uniqueness
- return partial_path
-
- def clean_link_name(self):
- link_name = self.cleaned_data.get('link_name')
- # TODO(tlarsen): combine path and link_name and check for uniqueness
- return link_name
-
-
-DEF_SITE_DOCS_CREATE_TMPL = 'soc/site/docs/edit.html'
-
-@decorators.view
-def create(request, page=None, template=DEF_SITE_DOCS_CREATE_TMPL):
- """View for a Developer to create a new Document entity.
-
- Args:
- request: the standard django request object
- page: a soc.logic.site.page.Page object which is abstraction that combines
- a Django view with sidebar menu info
- template: the "sibling" template (or a search list of such templates)
- from which to construct the public.html template name (or names)
-
- Returns:
- A subclass of django.http.HttpResponse which either contains the form to
- be filled out, or a redirect to the correct view in the interface.
- """
-
- try:
- access.checkIsDeveloper(request)
- except soc.views.out_of_band.AccessViolationResponse, alt_response:
- return alt_response.response()
-
- # create default template context for use with any templates
- context = helper.responses.getUniversalContext(request)
- context['page'] = page
-
- if request.method == 'POST':
- form = CreateForm(request.POST)
-
- if form.is_valid():
- doc = getDocForForm(form)
-
- if not doc:
- return http.HttpResponseRedirect('/')
-
- new_path = path_link_name.combinePath([doc.partial_path, doc.link_name])
-
- # redirect to new /site/docs/edit/new_path?s=0
- # (causes 'Profile saved' message to be displayed)
- return helper.responses.redirectToChangedSuffix(
- request, None, new_path,
- params=profile.SUBMIT_PROFILE_SAVED_PARAMS)
- else: # method == 'GET':
- # no link name specified, so start with an empty form
- form = CreateForm()
-
- context['form'] = form
-
- return helper.responses.respond(request, template, context)
-
-
-DEF_SITE_DOCS_EDIT_TMPL = 'soc/site/docs/edit.html'
-
-class EditForm(CreateForm):
- """Django form displayed when Developer edits a Document.
- """
- doc_key_name = forms.fields.CharField(widget=forms.HiddenInput)
- created_by = forms.fields.CharField(widget=helper.widgets.ReadOnlyInput(),
- required=False)
-
-
-@decorators.view
-def edit(request, page=None, partial_path=None, link_name=None,
- template=DEF_SITE_DOCS_EDIT_TMPL):
- """View for a Developer to modify the properties of a Document Model entity.
-
- Args:
- request: the standard django request object
- page: a soc.logic.site.page.Page object which is abstraction that combines
- a Django view with sidebar menu info
- partial_path: the Document's site-unique "path" extracted from the URL,
- minus the trailing link_name
- link_name: the last portion of the Document's site-unique "path"
- extracted from the URL
- template: the "sibling" template (or a search list of such templates)
- from which to construct the public.html template name (or names)
-
- Returns:
- A subclass of django.http.HttpResponse which either contains the form to
- be filled out, or a redirect to the correct view in the interface.
- """
-
- try:
- access.checkIsDeveloper(request)
- except soc.views.out_of_band.AccessViolationResponse, alt_response:
- return alt_response.response()
-
- # create default template context for use with any templates
- context = helper.responses.getUniversalContext(request)
- context['page'] = page
-
- doc = None # assume that no Document entity will be found
-
- path = path_link_name.combinePath([partial_path, link_name])
-
- # try to fetch Document entity corresponding to path if one exists
- try:
- if path:
- doc = document.logic.getFromFields(partial_path=partial_path,
- link_name=link_name)
- except out_of_band.ErrorResponse, error:
- # show custom 404 page when path doesn't exist in Datastore
- error.message = error.message + DEF_CREATE_NEW_DOC_MSG
- return simple.errorResponse(request, page, error, template, context)
-
- if request.method == 'POST':
- form = EditForm(request.POST)
-
- if form.is_valid():
- doc = getDocForForm(form)
-
- if not doc:
- return http.HttpResponseRedirect('/')
-
- new_path = path_link_name.combinePath([doc.partial_path, doc.link_name])
-
- # redirect to new /site/docs/edit/new_path?s=0
- # (causes 'Profile saved' message to be displayed)
- return helper.responses.redirectToChangedSuffix(
- request, path, new_path,
- params=profile.SUBMIT_PROFILE_SAVED_PARAMS)
- else: # method == 'GET':
- # try to fetch Document entity corresponding to path if one exists
- if path:
- if doc:
- # is 'Profile saved' parameter present, but referrer was not ourself?
- # (e.g. someone bookmarked the GET that followed the POST submit)
- if (request.GET.get(profile.SUBMIT_MSG_PARAM_NAME)
- and (not helper.requests.isReferrerSelf(request, suffix=path))):
- # redirect to aggressively remove 'Profile saved' query parameter
- return http.HttpResponseRedirect(request.path)
-
- # referrer was us, so select which submit message to display
- # (may display no message if ?s=0 parameter is not present)
- context['notice'] = (
- helper.requests.getSingleIndexedParamValue(
- request, profile.SUBMIT_MSG_PARAM_NAME,
- values=SUBMIT_MESSAGES))
-
- # populate form with the existing Document entity
- author_link_name = doc.author.link_name
- form = EditForm(initial={'doc_key_name': doc.key().name(),
- 'title': doc.title, 'partial_path': doc.partial_path,
- 'link_name': doc.link_name, 'short_name': doc.short_name,
- 'content': doc.content, 'author': doc.author,
- 'is_featured': doc.is_featured, 'created_by': author_link_name})
- else:
- if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME):
- # redirect to aggressively remove 'Profile saved' query parameter
- return http.HttpResponseRedirect(request.path)
-
- context['lookup_error'] = ugettext_lazy(
- 'Document with that path not found.')
- form = EditForm(initial={'link_name': link_name})
- else: # no link name specified in the URL
- if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME):
- # redirect to aggressively remove 'Profile saved' query parameter
- return http.HttpResponseRedirect(request.path)
-
- # no link name specified, so start with an empty form
- form = EditForm()
-
- context.update({'form': form,
- 'existing_doc': doc})
-
- return helper.responses.respond(request, template, context)
-
-
-@decorators.view
-def delete(request, page=None, partial_path=None, link_name=None,
- template=DEF_SITE_DOCS_EDIT_TMPL):
- """Request handler for a Developer to delete Document Model entity.
-
- Args:
- request: the standard django request object
- page: a soc.logic.site.page.Page object which is abstraction that combines
- a Django view with sidebar menu info
- partial_path: the Document's site-unique "path" extracted from the URL,
- minus the trailing link_name
- link_name: the last portion of the Document's site-unique "path"
- extracted from the URL
- template: the "sibling" template (or a search list of such templates)
- from which to construct the public.html template name (or names)
-
- Returns:
- A subclass of django.http.HttpResponse which redirects
- to /site/docs/list.
- """
-
- try:
- access.checkIsDeveloper(request)
- except soc.views.out_of_band.AccessViolationResponse, alt_response:
- return alt_response.response()
-
- # create default template context for use with any templates
- context = helper.responses.getUniversalContext(request)
-
- existing_doc = None
- path = path_link_name.combinePath([partial_path, link_name])
-
- # try to fetch Document entity corresponding to path if one exists
- try:
- if path:
- existing_doc = document.logic.getFromFields(partial_path=partial_path,
- link_name=link_name)
- except out_of_band.ErrorResponse, error:
- # show custom 404 page when path doesn't exist in Datastore
- error.message = error.message + DEF_CREATE_NEW_DOC_MSG
- return simple.errorResponse(request, page, error, template, context)
-
- if existing_doc:
- document.logic.delete(existing_doc)
-
- return http.HttpResponseRedirect('/site/docs/list')
\ No newline at end of file
--- a/app/soc/views/site/docs/list.py Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-#!/usr/bin/python2.5
-#
-# Copyright 2008 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Developer views for listing Documents.
-"""
-
-__authors__ = [
- '"Todd Larsen" <tlarsen@google.com>',
- ]
-
-
-from soc.logic.models import work
-from soc.views import helper
-from soc.views.helper import access
-from soc.views.helper import decorators
-
-import soc.logic
-import soc.models.document
-import soc.views.helper.lists
-import soc.views.helper.responses
-import soc.views.out_of_band
-
-
-DEF_SITE_DOCS_LIST_ALL_TMPL = 'soc/site/docs/list/all.html'
-
-
-@decorators.view
-def all(request, page=None, template=DEF_SITE_DOCS_LIST_ALL_TMPL):
- """Show a list of all Documents (limit rows per page).
-
- Args:
- request: the standard Django HTTP request object
- page: a soc.logic.site.page.Page object which is abstraction that combines
- a Django view with sidebar menu info
- template: the "sibling" template (or a search list of such templates)
- from which to construct an alternate template name (or names)
-
- Returns:
- A subclass of django.http.HttpResponse which either contains the form to
- be filled out, or a redirect to the correct view in the interface.
- """
-
- try:
- access.checkIsDeveloper(request)
- except soc.views.out_of_band.AccessViolationResponse, alt_response:
- return alt_response.response()
-
- # create default template context for use with any templates
- context = helper.responses.getUniversalContext(request)
- context['page'] = page
-
- offset, limit = helper.lists.cleanListParameters(
- offset=request.GET.get('offset'), limit=request.GET.get('limit'))
-
- # Fetch one more to see if there should be a 'next' link
- docs = work.logic.getForLimitAndOffset(limit + 1, offset=offset)
-
- context['pagination_form'] = helper.lists.makePaginationForm(request, limit)
-
- list_templates = {'list_main': 'soc/list/list_main.html',
- 'list_pagination': 'soc/list/list_pagination.html',
- 'list_row': 'soc/site/docs/list/docs_row.html',
- 'list_heading': 'soc/site/docs/list/docs_heading.html'}
-
- context = helper.lists.setList(
- request, context, docs,
- offset=offset, limit=limit, list_templates=list_templates)
-
- return helper.responses.respond(request, template, context)
\ No newline at end of file
--- a/app/soc/views/site/home.py Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#!/usr/bin/python2.5
-#
-# Copyright 2008 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Site-wide Melange home page views.
-
-public: how the general public sees the site home page of a Melange
- site
-"""
-
-__authors__ = [
- '"Pawel Solyga" <pawel.solyga@gmail.com>',
- ]
-
-
-from google.appengine.ext import db
-
-from soc.logic import models
-from soc.views import helper
-from soc.views.helper import decorators
-
-import soc.logic.models.site_settings
-import soc.views.helper.responses
-import soc.views.helper.templates
-
-
-DEF_SITE_HOME_PUBLIC_TMPL = 'soc/site/home/public.html'
-
-@decorators.view
-def public(request, page=None, template=DEF_SITE_HOME_PUBLIC_TMPL):
- """How the "general public" sees the Melange site home page.
-
- Args:
- request: the standard django request object.
- page: a soc.logic.site.page.Page object which is abstraction that combines
- a Django view with sidebar menu info
- template: the template path to use for rendering the template.
-
- Returns:
- A subclass of django.http.HttpResponse with generated template.
- """
- # create default template context for use with any templates
- context = helper.responses.getUniversalContext(request)
- context['page'] = page
-
- site_settings = models.site_settings.logic.getFromFields(
- path=models.site_settings.logic.DEF_SITE_SETTINGS_PATH)
-
- if site_settings:
- context['site_settings'] = site_settings
-
- # check if ReferenceProperty to home Document is valid
- try:
- site_doc = site_settings.home
- except db.Error:
- site_doc = None
-
- if site_doc:
- site_doc.content = helper.templates.unescape(site_doc.content)
- context['site_document'] = site_doc
-
- return helper.responses.respond(request, template, context=context)
\ No newline at end of file
--- a/app/soc/views/site/settings.py Sat Oct 18 04:56:39 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-#!/usr/bin/python2.5
-#
-# Copyright 2008 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Site-wide Melange home page views.
-
-public: how the general public sees the site home page of a Melange
- site
-
-edit: site settings view for logged-in Developers
-"""
-
-__authors__ = [
- '"Pawel Solyga" <pawel.solyga@gmail.com>',
- ]
-
-
-from google.appengine.api import users
-from google.appengine.ext import db
-
-from django import forms
-
-from soc.logic import models
-from soc.logic import validate
-from soc.logic.models import document
-from soc.views import helper
-from soc.views.helper import access
-from soc.views.helper import decorators
-
-import soc.logic.models.site_settings
-import soc.models.document
-import soc.models.site_settings
-import soc.views.helper.forms
-import soc.views.helper.responses
-import soc.views.helper.templates
-import soc.views.helper.widgets
-import soc.views.out_of_band
-
-
-class DocumentForm(helper.forms.DbModelForm):
- content = forms.fields.CharField(widget=helper.widgets.TinyMCE(
- attrs={'rows':10, 'cols':40}))
-
- class Meta:
- """Inner Meta class that defines some behavior for the form.
- """
- #: db.Model subclass for which the form will gather information
- model = soc.models.document.Document
-
- #: list of model fields which will *not* be gathered by the form
- exclude = ['partial_path', 'link_name',
- 'author', 'modified', 'created', 'inheritance_line']
-
-
-class SiteSettingsForm(helper.forms.DbModelForm):
- """Django form displayed when creating or editing Site Settings.
- """
- class Meta:
- """Inner Meta class that defines some behavior for the form.
- """
- #: db.Model subclass for which the form will gather information
- model = soc.models.site_settings.SiteSettings
-
- #: list of model fields which will *not* be gathered by the form
- exclude = ['inheritance_line', 'home']
-
- def clean_feed_url(self):
- feed_url = self.cleaned_data.get('feed_url')
-
- if feed_url == '':
- # feed url not supplied (which is OK), so do not try to validate it
- return None
-
- if not validate.isFeedURLValid(feed_url):
- raise forms.ValidationError('This URL is not a valid ATOM or RSS feed.')
-
- return feed_url
-
-
-DEF_SITE_HOME_EDIT_TMPL = 'soc/site/settings/edit.html'
-
-@decorators.view
-def edit(request, page=None, template=DEF_SITE_HOME_EDIT_TMPL):
- """View for Developer to edit content of Melange site home page.
-
- Args:
- request: the standard django request object.
- page: a soc.logic.site.page.Page object which is abstraction that combines
- a Django view with sidebar menu info
- template: the template path to use for rendering the template.
-
- Returns:
- A subclass of django.http.HttpResponse with generated template.
- """
-
- try:
- access.checkIsDeveloper(request)
- except soc.views.out_of_band.AccessViolationResponse, alt_response:
- return alt_response.response()
-
- # create default template context for use with any templates
- context = helper.responses.getUniversalContext(request)
-
- settings_form = None
- document_form = None
-
- if request.method == 'POST':
- document_form = DocumentForm(request.POST)
- settings_form = SiteSettingsForm(request.POST)
-
- if document_form.is_valid() and settings_form.is_valid():
- link_name = models.site_settings.logic.DEF_SITE_HOME_DOC_LINK_NAME
- partial_path = models.site_settings.logic.DEF_SITE_SETTINGS_PATH
- logged_in_id = users.get_current_user()
- author = models.user.logic.getFromFields(email=logged_in_id.email())
-
- properties = {
- 'title': document_form.cleaned_data.get('title'),
- 'short_name': document_form.cleaned_data.get('short_name'),
- 'content': document_form.cleaned_data.get('content'),
- 'link_name': link_name,
- 'partial_path': partial_path,
- 'id': logged_in_id,
- 'author': author,
- }
-
- site_doc = document.logic.updateOrCreateFromFields(
- properties, partial_path=partial_path, link_name=link_name)
-
- feed_url = settings_form.cleaned_data.get('feed_url')
-
- site_settings = models.site_settings.logic.updateOrCreateFromFields(
- {'feed_url': feed_url, 'home': site_doc},
- path=models.site_settings.logic.DEF_SITE_SETTINGS_PATH)
-
- context['notice'] = 'Site Settings saved.'
- else: # request.method == 'GET'
- # try to fetch SiteSettings entity by unique key_name
- site_settings = models.site_settings.logic.getFromFields(
- path=models.site_settings.logic.DEF_SITE_SETTINGS_PATH)
-
- if site_settings:
- # populate form with the existing SiteSettings entity
- settings_form = SiteSettingsForm(instance=site_settings)
-
- # check if ReferenceProperty to home Document is valid
- try:
- site_doc = site_settings.home
- except db.Error:
- site_doc = None
-
- else:
- # no SiteSettings entity exists for this key_name, so show a blank form
- settings_form = SiteSettingsForm()
- site_doc = None
-
- if site_doc:
- # populate form with the existing Document entity
- document_form = DocumentForm(instance=site_doc)
- else:
- # no Document entity exists for this key_name, so show a blank form
- document_form = DocumentForm()
-
- context.update({'document_form': document_form,
- 'settings_form': settings_form })
-
- return helper.responses.respond(request, template, context)
\ No newline at end of file