witten
/
luminotes
Archived
1
0
Fork 0

Lots of discussion forum / blog work.

This commit is contained in:
Dan Helfman 2008-11-18 13:28:51 -08:00
parent 4855ac0c7e
commit c211456130
9 changed files with 296 additions and 98 deletions

7
NEWS
View File

@ -6,10 +6,17 @@
* Improved site navigation by adding more useful links to the page footer. * 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 * Converted the Luminotes blog to work like a forum, so now you can post
comments on Luminotes blog posts. 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 * Fixed a bug in which search result note summaries were not showing the
portion of the note that matched the search term. (Luminotes Server) 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 * 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. 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 1.5.6: November 12, 2008
* Greatly improved the speed of wiki searching for Luminotes Server and * Greatly improved the speed of wiki searching for Luminotes Server and

View File

@ -13,6 +13,7 @@ from Notebooks import Notebooks
from Users import Access_error from Users import Access_error
from view.Forums_page import Forums_page from view.Forums_page import Forums_page
from view.Forum_page import Forum_page from view.Forum_page import Forum_page
from view.Forum_rss import Forum_rss
from view.Main_page import Main_page from view.Main_page import Main_page
@ -90,7 +91,7 @@ class Forum( object ):
self.__users = users self.__users = users
self.__name = name self.__name = name
@expose( view = Forum_page ) @expose( view = Forum_page, rss = Forum_rss )
@strongly_expire @strongly_expire
@end_transaction @end_transaction
@grab_user_id @grab_user_id
@ -102,8 +103,7 @@ class Forum( object ):
) )
def index( self, start = 0, count = 50, note_id = None, user_id = None ): 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 Provide the information necessary to display the current threads within a forum.
chronological order).
@type start: integer or NoneType @type start: integer or NoneType
@param start: index of first forum thread to display (optional, defaults to 0) @param start: index of first forum thread to display (optional, defaults to 0)
@ -130,19 +130,12 @@ class Forum( object ):
if anonymous is None: if anonymous is None:
raise Access_error() 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 # load a slice of the list of the threads in this forum, excluding those with a default name
threads = self.__database.select_many( threads = self.__database.select_many(
Notebook, Notebook,
anonymous.sql_load_notebooks( anonymous.sql_load_notebooks(
parents_only = False, undeleted_only = True, tag_name = u"forum", tag_value = self.__name, 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, start = start, count = count,
) )
) )
@ -263,6 +256,11 @@ class Forum( object ):
self.__database.commit() self.__database.commit()
if self.__name == "blog":
return dict(
redirect = u"/blog/%s" % thread_id,
)
return dict( return dict(
redirect = u"/forums/%s/%s" % ( self.__name, thread_id ), redirect = u"/forums/%s/%s" % ( self.__name, thread_id ),
) )

View File

@ -125,19 +125,17 @@ class Notebooks( object ):
result[ u"notebooks" ] = [ result[ u"notebooks" ] = [
notebook for notebook in result[ "notebooks" ] if notebook.object_id == notebook_id notebook for notebook in result[ "notebooks" ] if notebook.object_id == notebook_id
] ]
if len( result[ u"notebooks" ] ) == 0: if len( result[ u"notebooks" ] ) == 1:
raise Access_error() result[ u"notebooks" ][ 0 ].owner = False
result[ u"notebooks" ][ 0 ].owner = False
elif preview == u"viewer": elif preview == u"viewer":
read_write = False read_write = False
owner = False owner = False
result[ u"notebooks" ] = [ result[ u"notebooks" ] = [
notebook for notebook in result[ "notebooks" ] if notebook.object_id == notebook_id notebook for notebook in result[ "notebooks" ] if notebook.object_id == notebook_id
] ]
if len( result[ u"notebooks" ] ) == 0: if len( result[ u"notebooks" ] ) == 1:
raise Access_error() result[ u"notebooks" ][ 0 ].read_write = Notebook.READ_ONLY
result[ u"notebooks" ][ 0 ].read_write = Notebook.READ_ONLY result[ u"notebooks" ][ 0 ].owner = False
result[ u"notebooks" ][ 0 ].owner = False
elif preview in ( u"owner", u"default", None ): elif preview in ( u"owner", u"default", None ):
read_write = True read_write = True
owner = True owner = True
@ -155,7 +153,10 @@ class Notebooks( object ):
forum_tags = [ tag for tag in notebook.tags if tag.name == u"forum" ] forum_tags = [ tag for tag in notebook.tags if tag.name == u"forum" ]
if forum_tags: if forum_tags:
forum_name = forum_tags[ 0 ].value 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: if note_id:
redirect += u"?note_id=%s" % note_id redirect += u"?note_id=%s" % note_id

View File

@ -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.notebook = Notebook.create( self.database.next_id( Notebook ), u"my notebook", trash_id = u"foo" )
self.database.save( self.notebook ) 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.database.save( self.anon_notebook )
self.anon_note = Note.create( self.anon_note = Note.create(
self.database.next_id( Note ), u"<h3>my note</h3>", self.database.next_id( Note ), u"<h3>my note</h3>",
@ -43,6 +43,9 @@ class Test_forums( Test_controller ):
self.database.save( self.anonymous ) self.database.save( self.anonymous )
self.database.execute( self.anonymous.sql_save_notebook( self.anon_notebook.object_id ) ) 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 ) tag_id = self.database.next_id( Tag )
self.forum_tag = Tag.create( self.forum_tag = Tag.create(
tag_id, 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.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 ): def test_index( self ):
result = self.http_get( "/forums/" ) result = self.http_get( "/forums/" )
assert result assert result
assert result.get( u"redirect" ) is None assert result.get( u"redirect" ) is None
assert result[ u"user" ].username == u"anonymous" assert result[ u"user" ].username == u"anonymous"
assert len( result[ u"notebooks" ] ) == 3 assert len( result[ u"notebooks" ] ) == 4
assert result[ u"first_notebook" ] == None 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" % ( assert result[ u"login_url" ] == u"https://luminotes.com/notebooks/%s?note_id=%s" % (
self.anon_notebook.object_id, self.login_note.object_id, self.anon_notebook.object_id, self.login_note.object_id,
) )
@ -93,7 +108,7 @@ class Test_forums( Test_controller ):
assert result assert result
assert result.get( u"redirect" ) is None assert result.get( u"redirect" ) is None
assert result[ u"user" ].username == self.user.username 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"first_notebook" ].object_id == self.notebook.object_id
assert result[ u"login_url" ] == None assert result[ u"login_url" ] == None
assert result[ u"logout_url" ] == u"https://luminotes.com/users/logout" 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"count" ] == 50
assert result[ u"total_thread_count" ] == 1 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 ): def test_support( self ):
result = self.http_get( "/forums/support/" ) 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 ) result = self.http_get( "/forums/general/%s" % self.general_thread.object_id )
assert result.get( u"user" ).object_id == self.anonymous.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"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" ) assert result.get( u"login_url" )
assert result.get( u"logout_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 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"notebooks" )[ 0 ].object_id == self.notebook.object_id
assert result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) 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 ) result = self.http_get( "/forums/general/%s" % self.general_thread.object_id )
assert result.get( u"user" ).object_id == self.anonymous.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"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" ) assert result.get( u"login_url" )
assert result.get( u"logout_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 ) 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 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"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" ) assert result.get( u"login_url" )
assert result.get( u"logout_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 ) 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 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"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" ) assert result.get( u"login_url" )
assert result.get( u"logout_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 ) 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 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"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" ) assert result.get( u"login_url" )
assert result.get( u"logout_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 ) ) 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 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"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
assert result.get( u"login_url" ) assert result.get( u"login_url" )
assert result.get( u"logout_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 ) user = self.database.load( User, self.user.object_id )
assert user.storage_bytes == 0 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
assert thread.object_id == expected_id assert thread.object_id == expected_id
assert thread.name == u"new discussion" 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.read_write == Notebook.READ_WRITE_FOR_OWN_NOTES
assert thread.owner == False assert thread.owner == False
assert thread.deleted == 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 ): def test_general_create_thread( self ):
self.login() self.login()
@ -517,6 +544,62 @@ class Test_forums( Test_controller ):
assert headers assert headers
assert headers.get( "Location" ) == u"http:///login?after_login=%s" % urllib.quote( path ) 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"<h3>"
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 ): def login( self ):
result = self.http_post( "/users/login", dict( result = self.http_post( "/users/login", dict(
username = self.username, username = self.username,
@ -532,3 +615,12 @@ class Test_forums( Test_controller ):
login_button = u"login", login_button = u"login",
) ) ) )
self.session_id = result[ u"session_id" ] 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" ]

View File

@ -192,6 +192,33 @@ class Test_notebooks( Test_controller ):
redirect = result.get( "redirect" ) redirect = result.get( "redirect" )
assert redirect == u"/forums/chickens/%s" % self.notebook.object_id 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 ): def test_default( self ):
self.login() self.login()
@ -201,10 +228,10 @@ class Test_notebooks( Test_controller ):
) )
assert result.get( u"user" ).object_id == self.user.object_id 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"notebooks" )[ 2 ].object_id == self.notebook.object_id assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
assert result.get( u"notebooks" )[ 2 ].owner == True assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"notebooks" )[ 2 ].object_id == self.notebook.object_id assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
assert result.get( u"notebooks" )[ 2 ].owner == True assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 result.get( u"user" ).object_id == self.user.object_id
assert len( result.get( u"notebooks" ) ) == 1 assert len( result.get( u"notebooks" ) ) == 0
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 result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 # 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 # access. so read_write should be False on the returned notebook
assert result.get( u"user" ).object_id == self.user.object_id assert result.get( u"user" ).object_id == self.user.object_id
assert len( result.get( u"notebooks" ) ) == 1 assert len( result.get( u"notebooks" ) ) == 0
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 result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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 ] 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.object_id == self.notebook.object_id
assert notebook.read_write == Notebook.READ_ONLY assert notebook.read_write == Notebook.READ_WRITE
assert notebook.owner == False assert notebook.owner == True
assert result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"notebooks" )[ 2 ].object_id == self.notebook.object_id assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
assert result.get( u"notebooks" )[ 2 ].owner == True assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"notebooks" )[ 2 ].object_id == self.notebook.object_id assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
assert result.get( u"notebooks" )[ 2 ].owner == True assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"notebooks" )[ 2 ].object_id == self.notebook.object_id assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
assert result.get( u"notebooks" )[ 2 ].owner == True assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"notebooks" )[ 2 ].object_id == self.notebook.object_id assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
assert result.get( u"notebooks" )[ 2 ].read_write == Notebook.READ_WRITE assert result.get( u"notebooks" )[ 0 ].read_write == Notebook.READ_WRITE
assert result.get( u"notebooks" )[ 2 ].owner == True assert result.get( u"notebooks" )[ 0 ].owner == True
assert result.get( u"login_url" ) is None assert result.get( u"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) 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 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"login_url" ) is None
assert result.get( u"logout_url" ) assert result.get( u"logout_url" )
assert result.get( u"rate_plan" ) assert result.get( u"rate_plan" )

View File

@ -1,8 +1,9 @@
import os.path import os.path
import cherrypy import cherrypy
from datetime import datetime
from Product_page import Product_page from Product_page import Product_page
from Page_navigation import Page_navigation 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 ): class Forum_page( Product_page ):
@ -11,11 +12,12 @@ class Forum_page( Product_page ):
threads, total_thread_count, start = 0, count = None, threads, total_thread_count, start = 0, count = None,
): ):
base_path = cherrypy.request.path base_path = cherrypy.request.path
updates_path = "%s?rss" % base_path
if base_path.startswith( u"/forums/" ): if forum_name == u"blog":
full_forum_name = u"%s forum" % forum_name
else:
full_forum_name = u"Luminotes %s" % forum_name full_forum_name = u"Luminotes %s" % forum_name
else:
full_forum_name = u"%s forum" % forum_name
Product_page.__init__( Product_page.__init__(
self, self,
@ -24,15 +26,24 @@ class Forum_page( Product_page ):
login_url, login_url,
logout_url, logout_url,
full_forum_name, # note title full_forum_name, # note title
Link( rel = u"alternate", type = u"application/rss+xml", title = full_forum_name, href = updates_path ) or None,
P( P(
H1( full_forum_name ), H1( full_forum_name ),
), ),
Div( Div(
base_path.startswith( u"/forums/" ) and P( P(
A( u"start a new discussion", href = os.path.join( base_path, u"create_thread" ) ), base_path.startswith( u"/forums/" ) and Span(
u" | ", A( u"start a new discussion", href = os.path.join( base_path, u"create_thread" ) ),
A( u"all forums", href = u"/forums/" ), 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", class_ = u"small_text",
) or None, ) or None,
[ Div( [ Div(
@ -40,8 +51,26 @@ class Forum_page( Product_page ):
thread.name, thread.name,
href = os.path.join( base_path, thread.object_id ), href = os.path.join( base_path, thread.object_id ),
), ),
Span(
self.post_count( thread, forum_name ),
class_ = u"small_text",
)
) for thread in threads ], ) for thread in threads ],
class_ = u"forum_threads", class_ = u"forum_threads",
), ),
Page_navigation( base_path, len( threads ), total_thread_count, start, count ), 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

42
view/Forum_rss.py Normal file
View File

@ -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 ],
)

View File

@ -28,16 +28,14 @@ class Link_area( Div ):
Div.__init__( Div.__init__(
self, self,
toolbar, toolbar,
( user.username == u"anonymous" ) and self.forum_link( forum_tag, forum_name ) or None,
( user.username != u"anonymous" ) and Div( ( user.username != u"anonymous" ) and Div(
( notebook_path != u"/" ) and Div( ( notebook_path != u"/" ) and Div(
H4( H4(
u"this %s" % notebook_word, u"this %s" % notebook_word,
id = u"this_notebook_area_title", id = u"this_notebook_area_title",
), ),
forum_tag and Div( self.forum_link( forum_tag, forum_name ),
A( u"%s forum" % forum_name, href = "/forums/%s" % forum_name ),
class_ = u"link_area_item",
) or None,
( rate_plan.get( u"notebook_sharing" ) and notebook.name == u"Luminotes blog" ) and Div( ( rate_plan.get( u"notebook_sharing" ) and notebook.name == u"Luminotes blog" ) and Div(
A( A(
@ -208,3 +206,19 @@ class Link_area( Div ):
) or None, ) or None,
id = u"link_area", 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",
)

View File

@ -94,14 +94,13 @@ class Main_page( Page ):
updates_path = None updates_path = None
forum_tags = [ tag for tag in notebook.tags if tag.name == u"forum" ] forum_tags = [ tag for tag in notebook.tags if tag.name == u"forum" ]
forum_tag = None
if notebook.name == u"Luminotes": if notebook.name == u"Luminotes":
notebook_path = u"/" notebook_path = u"/"
updates_path = None # no RSS feed for the main notebook updates_path = None # no RSS feed for the main notebook
elif notebook.name == u"Luminotes user guide": elif notebook.name == u"Luminotes user guide":
notebook_path = u"/guide" notebook_path = u"/guide"
elif notebook.name == u"Luminotes blog":
notebook_path = u"/blog"
elif forum_tags: elif forum_tags:
forum_tag = forum_tags[ 0 ] forum_tag = forum_tags[ 0 ]
notebook_path = u"/forums/%s/%s" % ( forum_tag.value, notebook.object_id ) notebook_path = u"/forums/%s/%s" % ( forum_tag.value, notebook.object_id )
@ -125,7 +124,6 @@ class Main_page( Page ):
"contact info": "contact", "contact info": "contact",
"meet the team": "team", "meet the team": "team",
"Luminotes user guide": "guide", "Luminotes user guide": "guide",
"Luminotes blog": "blog",
"Luminotes privacy policy": "privacy", "Luminotes privacy policy": "privacy",
}.get( header_note_title, header_note_title ) }.get( header_note_title, header_note_title )
@ -136,10 +134,8 @@ class Main_page( Page ):
self, self,
title, title,
Link( rel = u"stylesheet", type = u"text/css", href = u"/static/css/header.css" ), Link( rel = u"stylesheet", type = u"text/css", href = u"/static/css/header.css" ),
( notebook.name == u"Luminotes blog" ) \ updates_path and \
and Link( rel = u"alternate", type = u"application/rss+xml", title = u"Luminotes blog", href = "/blog?rss" ) \ Link( rel = u"alternate", type = u"application/rss+xml", title = notebook.name, href = updates_path ) or None,
or ( 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/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/Invoker.js" ) or None,
Script( type = u"text/javascript", src = u"/static/js/Editor.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( Toolbar(
notebook, notebook,
hide_toolbar = parent_id or notebook.read_write == Notebook.READ_ONLY, 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, notebooks, notebook, parent_id, notebook_path, updates_path, user, rate_plan,
), ),
@ -212,8 +208,6 @@ class Main_page( Page ):
Page_navigation( Page_navigation(
notebook_path, len( notes ), total_notes_count, start, count, 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( Div(
Span( id = u"notes_top" ), Span( id = u"notes_top" ),
id = u"notes", id = u"notes",
@ -231,6 +225,8 @@ class Main_page( Page ):
u"document.getElementById( 'static_notes' ).style.display = 'none';", u"document.getElementById( 'static_notes' ).style.display = 'none';",
type = u"text/javascript", 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( Page_navigation(
notebook_path, len( notes ), total_notes_count, start, count, notebook_path, len( notes ), total_notes_count, start, count,
return_text = u"return to the discussion", return_text = u"return to the discussion",