Refactor various site views into more generic locations, in preparation for
authorTodd Larsen <tlarsen@google.com>
Sat, 18 Oct 2008 05:11:37 +0000
changeset 377 d94ec6f104cc
parent 376 ce8b3a9fa0de
child 378 51c41e8bd45f
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
app/soc/logic/key_name.py
app/soc/logic/site/map.py
app/soc/templates/soc/docs/edit.html
app/soc/templates/soc/docs/list/all.html
app/soc/templates/soc/docs/list/docs_heading.html
app/soc/templates/soc/docs/list/docs_row.html
app/soc/templates/soc/home/public.html
app/soc/templates/soc/settings/edit.html
app/soc/templates/soc/site/docs/edit.html
app/soc/templates/soc/site/docs/list/all.html
app/soc/templates/soc/site/docs/list/docs_heading.html
app/soc/templates/soc/site/docs/list/docs_row.html
app/soc/templates/soc/site/home/public.html
app/soc/templates/soc/site/settings/edit.html
app/soc/views/docs/edit.py
app/soc/views/docs/list.py
app/soc/views/group/__init__.py
app/soc/views/home.py
app/soc/views/settings.py
app/soc/views/site/docs/__init__.py
app/soc/views/site/docs/edit.py
app/soc/views/site/docs/list.py
app/soc/views/site/home.py
app/soc/views/site/settings.py
--- 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">&nbsp;</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">&nbsp;</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>&nbsp;</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">&nbsp;</td>
+  </tr>
+	{{ doc_select_form.as_table }}
+  <tr>
+   <td colspan="4">&nbsp;</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">&nbsp;</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">&nbsp;</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