diff --git a/NEWS b/NEWS
index 044411f..324b61b 100644
--- a/NEWS
+++ b/NEWS
@@ -6,10 +6,17 @@
* Improved site navigation by adding more useful links to the page footer.
* Converted the Luminotes blog to work like a forum, so now you can post
comments on Luminotes blog posts.
+ * You can now subscribe to an RSS feed in order to follow a whole Luminotes
+ discussion forum.
+ * The listing of threads in a discussion forum now shows how many posts
+ there are in each thread.
* Fixed a bug in which search result note summaries were not showing the
portion of the note that matched the search term. (Luminotes Server)
* Fixed a visual bug in which undoing the deletion of a note didn't always
make the note reappear, even though the undeletion always worked.
+ * NOTE: After upgrading to this release, you must restart memcached to clear
+ the cache. Failing to do so will cause errors with the Notebook object.
+ This does not apply to Luminotes Desktop.
1.5.6: November 12, 2008
* Greatly improved the speed of wiki searching for Luminotes Server and
diff --git a/controller/Forums.py b/controller/Forums.py
index 6c50bb9..b1a78ab 100644
--- a/controller/Forums.py
+++ b/controller/Forums.py
@@ -13,6 +13,7 @@ from Notebooks import Notebooks
from Users import Access_error
from view.Forums_page import Forums_page
from view.Forum_page import Forum_page
+from view.Forum_rss import Forum_rss
from view.Main_page import Main_page
@@ -90,7 +91,7 @@ class Forum( object ):
self.__users = users
self.__name = name
- @expose( view = Forum_page )
+ @expose( view = Forum_page, rss = Forum_rss )
@strongly_expire
@end_transaction
@grab_user_id
@@ -102,8 +103,7 @@ class Forum( object ):
)
def index( self, start = 0, count = 50, note_id = None, user_id = None ):
"""
- Provide the information necessary to display the current threads within a forum (in reverse
- chronological order).
+ Provide the information necessary to display the current threads within a forum.
@type start: integer or NoneType
@param start: index of first forum thread to display (optional, defaults to 0)
@@ -130,19 +130,12 @@ class Forum( object ):
if anonymous is None:
raise Access_error()
- # whether this is a blog determines whether the posts are diplayed in forward or reverse
- # chronological order
- if self.__name == u"blog":
- reverse = False
- else:
- reverse = True
-
# load a slice of the list of the threads in this forum, excluding those with a default name
threads = self.__database.select_many(
Notebook,
anonymous.sql_load_notebooks(
parents_only = False, undeleted_only = True, tag_name = u"forum", tag_value = self.__name,
- exclude_notebook_name = self.DEFAULT_THREAD_NAME, reverse = reverse,
+ exclude_notebook_name = self.DEFAULT_THREAD_NAME, reverse = True,
start = start, count = count,
)
)
@@ -263,6 +256,11 @@ class Forum( object ):
self.__database.commit()
+ if self.__name == "blog":
+ return dict(
+ redirect = u"/blog/%s" % thread_id,
+ )
+
return dict(
redirect = u"/forums/%s/%s" % ( self.__name, thread_id ),
)
diff --git a/controller/Notebooks.py b/controller/Notebooks.py
index 853c5f5..c6e0b32 100644
--- a/controller/Notebooks.py
+++ b/controller/Notebooks.py
@@ -125,19 +125,17 @@ class Notebooks( object ):
result[ u"notebooks" ] = [
notebook for notebook in result[ "notebooks" ] if notebook.object_id == notebook_id
]
- if len( result[ u"notebooks" ] ) == 0:
- raise Access_error()
- result[ u"notebooks" ][ 0 ].owner = False
+ if len( result[ u"notebooks" ] ) == 1:
+ result[ u"notebooks" ][ 0 ].owner = False
elif preview == u"viewer":
read_write = False
owner = False
result[ u"notebooks" ] = [
notebook for notebook in result[ "notebooks" ] if notebook.object_id == notebook_id
]
- if len( result[ u"notebooks" ] ) == 0:
- raise Access_error()
- result[ u"notebooks" ][ 0 ].read_write = Notebook.READ_ONLY
- result[ u"notebooks" ][ 0 ].owner = False
+ if len( result[ u"notebooks" ] ) == 1:
+ result[ u"notebooks" ][ 0 ].read_write = Notebook.READ_ONLY
+ result[ u"notebooks" ][ 0 ].owner = False
elif preview in ( u"owner", u"default", None ):
read_write = True
owner = True
@@ -155,7 +153,10 @@ class Notebooks( object ):
forum_tags = [ tag for tag in notebook.tags if tag.name == u"forum" ]
if forum_tags:
forum_name = forum_tags[ 0 ].value
- redirect = u"/forums/%s/%s" % ( forum_name, notebook_id )
+ if forum_name == "blog":
+ redirect = u"/blog/%s" % notebook_id
+ else:
+ redirect = u"/forums/%s/%s" % ( forum_name, notebook_id )
if note_id:
redirect += u"?note_id=%s" % note_id
diff --git a/controller/test/Test_forums.py b/controller/test/Test_forums.py
index d96aff9..757f51c 100644
--- a/controller/test/Test_forums.py
+++ b/controller/test/Test_forums.py
@@ -15,7 +15,7 @@ class Test_forums( Test_controller ):
self.notebook = Notebook.create( self.database.next_id( Notebook ), u"my notebook", trash_id = u"foo" )
self.database.save( self.notebook )
- self.anon_notebook = Notebook.create( self.database.next_id( Notebook ), u"Luminotes" )
+ self.anon_notebook = Notebook.create( self.database.next_id( Notebook ), u"Luminotes", trash_id = u"bar" )
self.database.save( self.anon_notebook )
self.anon_note = Note.create(
self.database.next_id( Note ), u"
my note
",
@@ -43,6 +43,9 @@ class Test_forums( Test_controller ):
self.database.save( self.anonymous )
self.database.execute( self.anonymous.sql_save_notebook( self.anon_notebook.object_id ) )
+ self.blog_user = User.create( self.database.next_id( User ), u"witten", self.password, self.email_address )
+ self.database.save( self.blog_user )
+
tag_id = self.database.next_id( Tag )
self.forum_tag = Tag.create(
tag_id,
@@ -71,14 +74,26 @@ class Test_forums( Test_controller ):
self.anonymous.sql_save_notebook_tag( self.support_thread.object_id, self.forum_tag.object_id, value = u"support" ),
)
+ self.blog_thread = Notebook.create( self.database.next_id( Notebook ), u"Welcome to the blog!" )
+ self.database.save( self.blog_thread )
+ self.database.execute(
+ self.anonymous.sql_save_notebook( self.blog_thread.object_id, read_write = Notebook.READ_WRITE_FOR_OWN_NOTES ),
+ )
+ self.database.execute(
+ self.blog_user.sql_save_notebook( self.blog_thread.object_id, read_write = Notebook.READ_WRITE ),
+ )
+ self.database.execute(
+ self.anonymous.sql_save_notebook_tag( self.blog_thread.object_id, self.forum_tag.object_id, value = u"forum" ),
+ )
+
def test_index( self ):
result = self.http_get( "/forums/" )
assert result
assert result.get( u"redirect" ) is None
assert result[ u"user" ].username == u"anonymous"
- assert len( result[ u"notebooks" ] ) == 3
- assert result[ u"first_notebook" ] == None
+ assert len( result[ u"notebooks" ] ) == 4
+ assert result[ u"first_notebook" ].object_id == self.anon_notebook.object_id
assert result[ u"login_url" ] == u"https://luminotes.com/notebooks/%s?note_id=%s" % (
self.anon_notebook.object_id, self.login_note.object_id,
)
@@ -93,7 +108,7 @@ class Test_forums( Test_controller ):
assert result
assert result.get( u"redirect" ) is None
assert result[ u"user" ].username == self.user.username
- assert len( result[ u"notebooks" ] ) == 4
+ assert len( result[ u"notebooks" ] ) == 5
assert result[ u"first_notebook" ].object_id == self.notebook.object_id
assert result[ u"login_url" ] == None
assert result[ u"logout_url" ] == u"https://luminotes.com/users/logout"
@@ -123,6 +138,18 @@ class Test_forums( Test_controller ):
assert result[ u"count" ] == 50
assert result[ u"total_thread_count" ] == 1
+ def test_general_with_note_id( self ):
+ result = self.http_get( "/forums/general?note_id=blah" )
+
+ headers = result.get( "headers" )
+ assert headers
+ assert headers.get( "Location" ) == u"http:///forums/general/?note_id=blah"
+
+ def test_general_with_trailing_slash_and_note_id( self ):
+ result = self.http_get( "/forums/general/?note_id=blah" )
+
+ assert result.get( "redirect" ) == u"/forums/general/blah"
+
def test_support( self ):
result = self.http_get( "/forums/support/" )
@@ -223,7 +250,7 @@ class Test_forums( Test_controller ):
result = self.http_get( "/forums/general/%s" % self.general_thread.object_id )
assert result.get( u"user" ).object_id == self.anonymous.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 4
assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" )
assert result.get( u"logout_url" )
@@ -250,7 +277,7 @@ class Test_forums( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 4
+ assert len( result.get( u"notebooks" ) ) == 5
assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
@@ -322,7 +349,7 @@ class Test_forums( Test_controller ):
result = self.http_get( "/forums/general/%s" % self.general_thread.object_id )
assert result.get( u"user" ).object_id == self.anonymous.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 4
assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" )
assert result.get( u"logout_url" )
@@ -352,7 +379,7 @@ class Test_forums( Test_controller ):
result = self.http_get( "/forums/general/%s?start=1" % self.general_thread.object_id )
assert result.get( u"user" ).object_id == self.anonymous.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 4
assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" )
assert result.get( u"logout_url" )
@@ -381,7 +408,7 @@ class Test_forums( Test_controller ):
result = self.http_get( "/forums/general/%s?count=2" % self.general_thread.object_id )
assert result.get( u"user" ).object_id == self.anonymous.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 4
assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" )
assert result.get( u"logout_url" )
@@ -410,7 +437,7 @@ class Test_forums( Test_controller ):
result = self.http_get( "/forums/general/%s?start=1&count=1" % self.general_thread.object_id )
assert result.get( u"user" ).object_id == self.anonymous.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 4
assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" )
assert result.get( u"logout_url" )
@@ -438,7 +465,7 @@ class Test_forums( Test_controller ):
result = self.http_get( "/forums/general/%s?note_id=%s" % ( self.general_thread.object_id, self.note.object_id ) )
assert result.get( u"user" ).object_id == self.anonymous.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 4
assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" )
assert result.get( u"logout_url" )
@@ -461,7 +488,7 @@ class Test_forums( Test_controller ):
user = self.database.load( User, self.user.object_id )
assert user.storage_bytes == 0
- def __assert_new_forum_thread( self, thread, expected_id ):
+ def __assert_new_forum_thread( self, thread, expected_id, expected_user_id = None ):
assert thread
assert thread.object_id == expected_id
assert thread.name == u"new discussion"
@@ -469,7 +496,7 @@ class Test_forums( Test_controller ):
assert thread.read_write == Notebook.READ_WRITE_FOR_OWN_NOTES
assert thread.owner == False
assert thread.deleted == False
- assert thread.user_id == self.user.object_id
+ assert thread.user_id == ( expected_user_id or self.user.object_id )
def test_general_create_thread( self ):
self.login()
@@ -517,6 +544,62 @@ class Test_forums( Test_controller ):
assert headers
assert headers.get( "Location" ) == u"http:///login?after_login=%s" % urllib.quote( path )
+ def test_blog_create_thread( self ):
+ self.login_blog()
+
+ result = self.http_get(
+ "/blog/create_thread",
+ session_id = self.session_id,
+ )
+
+ redirect = result.get( u"redirect" )
+ assert redirect
+ assert redirect.startswith( u"/blog/" )
+ new_thread_id = redirect.split( "/blog/" )[ -1 ].split( u"?" )[ 0 ]
+
+ thread = cherrypy.root.users.load_notebook( self.blog_user.object_id, new_thread_id, read_write = True )
+ self.__assert_new_forum_thread( thread, new_thread_id, self.blog_user.object_id )
+ tags = self.database.select_many( Tag, thread.sql_load_tags( self.blog_user.object_id ) )
+ assert tags == []
+
+ thread = cherrypy.root.users.load_notebook( self.anonymous.object_id, new_thread_id, read_write = False )
+ self.__assert_new_forum_thread( thread, new_thread_id, self.blog_user.object_id )
+ tags = self.database.select_many( Tag, thread.sql_load_tags( self.anonymous.object_id ) )
+
+ assert tags
+ assert len( tags ) == 1
+ assert tags[ 0 ].name == u"forum"
+ assert tags[ 0 ].value == u"blog"
+
+ notes = self.database.select_many( Note, thread.sql_load_notes() )
+ assert notes
+ assert len( notes ) == 1
+ assert notes[ 0 ].title == None
+ assert notes[ 0 ].contents == u""
+ assert notes[ 0 ].notebook_id == thread.object_id
+ assert notes[ 0 ].startup is True
+ assert notes[ 0 ].deleted_from_id is None
+ assert notes[ 0 ].rank == 0
+ assert notes[ 0 ].user_id == self.blog_user.object_id
+
+ def test_blog_create_thread_without_login( self ):
+ path = "/blog/create_thread"
+ result = self.http_get( path )
+
+ headers = result.get( "headers" )
+ assert headers
+ assert headers.get( "Location" ) == u"http:///login?after_login=%s" % urllib.quote( path )
+
+ def test_blog_create_thread_without_access( self ):
+ self.login()
+
+ result = self.http_get(
+ "/blog/create_thread",
+ session_id = self.session_id,
+ )
+
+ assert u"access" in result[ u"body" ][ 0 ]
+
def login( self ):
result = self.http_post( "/users/login", dict(
username = self.username,
@@ -532,3 +615,12 @@ class Test_forums( Test_controller ):
login_button = u"login",
) )
self.session_id = result[ u"session_id" ]
+
+ def login_blog( self ):
+ result = self.http_post( "/users/login", dict(
+ username = self.blog_user.username,
+ password = self.password,
+ login_button = u"login",
+ ) )
+ self.session_id = result[ u"session_id" ]
+
diff --git a/controller/test/Test_notebooks.py b/controller/test/Test_notebooks.py
index 8329bba..15f7d8d 100644
--- a/controller/test/Test_notebooks.py
+++ b/controller/test/Test_notebooks.py
@@ -192,6 +192,33 @@ class Test_notebooks( Test_controller ):
redirect = result.get( "redirect" )
assert redirect == u"/forums/chickens/%s" % self.notebook.object_id
+ def test_default_blog( self ):
+ self.login()
+
+ tag_id = self.database.next_id( Tag, commit = False )
+ new_tag = Tag.create(
+ tag_id,
+ notebook_id = None, # this tag is not in the namespace of a single notebook
+ user_id = self.user.object_id,
+ name = u"forum",
+ description = u"a discussion forum"
+ )
+ self.database.save( new_tag, commit = False )
+
+ self.database.execute(
+ self.user.sql_save_notebook_tag( self.notebook.object_id, new_tag.object_id, value = u"blog" ),
+ commit = False,
+ )
+ self.database.commit()
+
+ result = self.http_get(
+ "/notebooks/%s" % self.notebook.object_id,
+ session_id = self.session_id,
+ )
+
+ redirect = result.get( "redirect" )
+ assert redirect == u"/blog/%s" % self.notebook.object_id
+
def test_default( self ):
self.login()
@@ -201,10 +228,10 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
- assert result.get( u"notebooks" )[ 2 ].object_id == self.notebook.object_id
- assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE
- assert result.get( u"notebooks" )[ 2 ].owner == True
+ assert len( result.get( u"notebooks" ) ) == 1
+ assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
+ assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
+ assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -309,10 +336,10 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
- assert result.get( u"notebooks" )[ 2 ].object_id == self.notebook.object_id
- assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE
- assert result.get( u"notebooks" )[ 2 ].owner == True
+ assert len( result.get( u"notebooks" ) ) == 1
+ assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
+ assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
+ assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -345,10 +372,7 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 1
- assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
- assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_ONLY
- assert result.get( u"notebooks" )[ 0 ].owner == False
+ assert len( result.get( u"notebooks" ) ) == 0
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -377,10 +401,7 @@ class Test_notebooks( Test_controller ):
# even though a collaborator preview is being requested, this user only has preview-level
# access. so read_write should be False on the returned notebook
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 1
- assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
- assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_ONLY
- assert result.get( u"notebooks" )[ 0 ].owner == False
+ assert len( result.get( u"notebooks" ) ) == 0
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -407,14 +428,12 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 1
notebook = result[ u"notebooks" ][ 0 ]
- if notebook.name == u"trash":
- notebook = result[ u"notebooks" ][ 1 ]
- assert notebook.object_id == self.anon_notebook.object_id
- assert notebook.read_write == Notebook.READ_ONLY
- assert notebook.owner == False
+ assert notebook.object_id == self.notebook.object_id
+ assert notebook.read_write == Notebook.READ_WRITE
+ assert notebook.owner == True
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -498,10 +517,10 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
- assert result.get( u"notebooks" )[ 2 ].object_id == self.notebook.object_id
- assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE
- assert result.get( u"notebooks" )[ 2 ].owner == True
+ assert len( result.get( u"notebooks" ) ) == 1
+ assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
+ assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
+ assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -541,10 +560,10 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
- assert result.get( u"notebooks" )[ 2 ].object_id == self.notebook.object_id
- assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE
- assert result.get( u"notebooks" )[ 2 ].owner == True
+ assert len( result.get( u"notebooks" ) ) == 1
+ assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
+ assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
+ assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -590,10 +609,10 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
- assert result.get( u"notebooks" )[ 2 ].object_id == self.notebook.object_id
- assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE
- assert result.get( u"notebooks" )[ 2 ].owner == True
+ assert len( result.get( u"notebooks" ) ) == 1
+ assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
+ assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
+ assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -632,10 +651,10 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
- assert result.get( u"notebooks" )[ 2 ].object_id == self.notebook.object_id
- assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE
- assert result.get( u"notebooks" )[ 2 ].owner == True
+ assert len( result.get( u"notebooks" ) ) == 1
+ assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
+ assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
+ assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -4749,7 +4768,7 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 1
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -4779,7 +4798,7 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 1
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -4808,7 +4827,7 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 1
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -4850,7 +4869,7 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 1
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -4880,7 +4899,7 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 1
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
@@ -4909,7 +4928,7 @@ class Test_notebooks( Test_controller ):
)
assert result.get( u"user" ).object_id == self.user.object_id
- assert len( result.get( u"notebooks" ) ) == 3
+ assert len( result.get( u"notebooks" ) ) == 1
assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" )
assert result.get( u"rate_plan" )
diff --git a/view/Forum_page.py b/view/Forum_page.py
index 954cd67..ed80123 100644
--- a/view/Forum_page.py
+++ b/view/Forum_page.py
@@ -1,8 +1,9 @@
import os.path
import cherrypy
+from datetime import datetime
from Product_page import Product_page
from Page_navigation import Page_navigation
-from Tags import Div, H1, A, P
+from Tags import Div, H1, A, P, Span, Link, Img
class Forum_page( Product_page ):
@@ -11,11 +12,12 @@ class Forum_page( Product_page ):
threads, total_thread_count, start = 0, count = None,
):
base_path = cherrypy.request.path
+ updates_path = "%s?rss" % base_path
- if base_path.startswith( u"/forums/" ):
- full_forum_name = u"%s forum" % forum_name
- else:
+ if forum_name == u"blog":
full_forum_name = u"Luminotes %s" % forum_name
+ else:
+ full_forum_name = u"%s forum" % forum_name
Product_page.__init__(
self,
@@ -24,15 +26,24 @@ class Forum_page( Product_page ):
login_url,
logout_url,
full_forum_name, # note title
+ Link( rel = u"alternate", type = u"application/rss+xml", title = full_forum_name, href = updates_path ) or None,
P(
H1( full_forum_name ),
),
Div(
- base_path.startswith( u"/forums/" ) and P(
- A( u"start a new discussion", href = os.path.join( base_path, u"create_thread" ) ),
- u" | ",
- A( u"all forums", href = u"/forums/" ),
+ P(
+ base_path.startswith( u"/forums/" ) and Span(
+ A( u"start a new discussion", href = os.path.join( base_path, u"create_thread" ) ),
+ u" | ",
+ A( u"all forums", href = u"/forums/" ),
+ u" | ",
+ ) or None,
+ A( u"subscribe to rss", href = updates_path ),
+ A(
+ Img( src = u"/static/images/rss.png", width = u"14", height = u"14", class_ = u"middle_image padding_left" ),
+ href = updates_path,
+ ),
class_ = u"small_text",
) or None,
[ Div(
@@ -40,8 +51,26 @@ class Forum_page( Product_page ):
thread.name,
href = os.path.join( base_path, thread.object_id ),
),
+ Span(
+ self.post_count( thread, forum_name ),
+ class_ = u"small_text",
+ )
) for thread in threads ],
class_ = u"forum_threads",
),
Page_navigation( base_path, len( threads ), total_thread_count, start, count ),
)
+
+ @staticmethod
+ def post_count( thread, forum_name ):
+ if forum_name != u"blog":
+ if thread.note_count > 1:
+ return u"(%s posts)" % thread.note_count
+ return None
+
+ if thread.note_count == 2:
+ return u"(1 comment)"
+ elif thread.note_count > 2:
+ return u"(%s comments)" % ( thread.note_count - 1 )
+
+ return None
diff --git a/view/Forum_rss.py b/view/Forum_rss.py
new file mode 100644
index 0000000..4d7ea87
--- /dev/null
+++ b/view/Forum_rss.py
@@ -0,0 +1,42 @@
+import cgi
+import os.path
+import cherrypy
+from Rss_channel import Rss_channel
+from Rss_item import Rss_item
+
+
+class Forum_rss( Rss_channel ):
+ def __init__(
+ self,
+ user,
+ notebooks,
+ first_notebook,
+ login_url,
+ logout_url,
+ rate_plan,
+ groups,
+ forum_name,
+ threads,
+ total_thread_count,
+ start = 0,
+ count = None,
+ ):
+ forum_path = cherrypy.request.base + cherrypy.request.path
+ if forum_name == u"blog":
+ full_forum_name = u"Luminotes %s" % forum_name
+ else:
+ full_forum_name = u"%s forum" % forum_name
+
+ Rss_channel.__init__(
+ self,
+ full_forum_name,
+ forum_path,
+ full_forum_name,
+ [ Rss_item(
+ title = cgi.escape( thread.name ),
+ link = os.path.join( forum_path, thread.object_id ),
+ description = cgi.escape( thread.name ),
+ date = thread.revision.strftime( "%Y-%m-%dT%H:%M:%SZ" ),
+ guid = os.path.join( forum_path, thread.object_id ),
+ ) for thread in threads ],
+ )
diff --git a/view/Link_area.py b/view/Link_area.py
index 38fc36d..c53387c 100644
--- a/view/Link_area.py
+++ b/view/Link_area.py
@@ -28,16 +28,14 @@ class Link_area( Div ):
Div.__init__(
self,
toolbar,
+ ( user.username == u"anonymous" ) and self.forum_link( forum_tag, forum_name ) or None,
( user.username != u"anonymous" ) and Div(
( notebook_path != u"/" ) and Div(
H4(
u"this %s" % notebook_word,
id = u"this_notebook_area_title",
),
- forum_tag and Div(
- A( u"%s forum" % forum_name, href = "/forums/%s" % forum_name ),
- class_ = u"link_area_item",
- ) or None,
+ self.forum_link( forum_tag, forum_name ),
( rate_plan.get( u"notebook_sharing" ) and notebook.name == u"Luminotes blog" ) and Div(
A(
@@ -208,3 +206,19 @@ class Link_area( Div ):
) or None,
id = u"link_area",
)
+
+ @staticmethod
+ def forum_link( forum_tag, forum_name ):
+ if not forum_tag:
+ return None
+
+ if forum_name == u"blog":
+ return Div(
+ A( u"Luminotes %s" % forum_name, href = "/blog/" ),
+ class_ = u"link_area_item",
+ )
+
+ return Div(
+ A( u"%s forum" % forum_name, href = "/forums/%s" % forum_name ),
+ class_ = u"link_area_item",
+ )
diff --git a/view/Main_page.py b/view/Main_page.py
index 451481b..77e474b 100644
--- a/view/Main_page.py
+++ b/view/Main_page.py
@@ -94,14 +94,13 @@ class Main_page( Page ):
updates_path = None
forum_tags = [ tag for tag in notebook.tags if tag.name == u"forum" ]
+ forum_tag = None
if notebook.name == u"Luminotes":
notebook_path = u"/"
updates_path = None # no RSS feed for the main notebook
elif notebook.name == u"Luminotes user guide":
notebook_path = u"/guide"
- elif notebook.name == u"Luminotes blog":
- notebook_path = u"/blog"
elif forum_tags:
forum_tag = forum_tags[ 0 ]
notebook_path = u"/forums/%s/%s" % ( forum_tag.value, notebook.object_id )
@@ -125,7 +124,6 @@ class Main_page( Page ):
"contact info": "contact",
"meet the team": "team",
"Luminotes user guide": "guide",
- "Luminotes blog": "blog",
"Luminotes privacy policy": "privacy",
}.get( header_note_title, header_note_title )
@@ -136,10 +134,8 @@ class Main_page( Page ):
self,
title,
Link( rel = u"stylesheet", type = u"text/css", href = u"/static/css/header.css" ),
- ( notebook.name == u"Luminotes blog" ) \
- and Link( rel = u"alternate", type = u"application/rss+xml", title = u"Luminotes blog", href = "/blog?rss" ) \
- or ( updates_path and \
- Link( rel = u"alternate", type = u"application/rss+xml", title = notebook.name, href = updates_path ) or None ),
+ updates_path and \
+ Link( rel = u"alternate", type = u"application/rss+xml", title = notebook.name, href = updates_path ) or None,
Script( type = u"text/javascript", src = u"/static/js/MochiKit.js" ) or None,
Script( type = u"text/javascript", src = u"/static/js/Invoker.js" ) or None,
Script( type = u"text/javascript", src = u"/static/js/Editor.js" ) or None,
@@ -170,7 +166,7 @@ class Main_page( Page ):
Toolbar(
notebook,
hide_toolbar = parent_id or notebook.read_write == Notebook.READ_ONLY,
- note_word = ( notebook.read_write == Notebook.READ_WRITE_FOR_OWN_NOTES ) and u"post" or u"note",
+ note_word = forum_tag and u"post" or u"note",
),
notebooks, notebook, parent_id, notebook_path, updates_path, user, rate_plan,
),
@@ -212,8 +208,6 @@ class Main_page( Page ):
Page_navigation(
notebook_path, len( notes ), total_notes_count, start, count,
),
- ( notebook.read_write == Notebook.READ_WRITE_FOR_OWN_NOTES and user.username and user.username != u"anonymous" ) and \
- P( u"If you write a comment, click the save button to publish it.", class_ = u"small_text" ) or None,
Div(
Span( id = u"notes_top" ),
id = u"notes",
@@ -231,6 +225,8 @@ class Main_page( Page ):
u"document.getElementById( 'static_notes' ).style.display = 'none';",
type = u"text/javascript",
),
+ ( forum_tag and user.username and user.username != u"anonymous" ) and \
+ P( u"If you write a comment, click the save button to publish it.", class_ = u"small_text" ) or None,
Page_navigation(
notebook_path, len( notes ), total_notes_count, start, count,
return_text = u"return to the discussion",