From 011baf2cb4714450dac02f216c19eb54d95d4ad9 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Fri, 25 Apr 2008 20:34:01 +0000 Subject: [PATCH] Adding unfinished Forums controller and associated tests. --- controller/Forums.py | 43 ++++++++++++++++++++++++++ controller/Root.py | 4 +++ controller/test/Test_forums.py | 55 +++++++++++++++++++++++++++++++++ static/css/product.css | 21 +++++++++++++ static/html/support.html | 31 +++++++++++++------ static/images/forums.png | Bin 0 -> 5057 bytes view/Forums_page.py | 46 +++++++++++++++++++++++++++ 7 files changed, 191 insertions(+), 9 deletions(-) create mode 100644 controller/Forums.py create mode 100644 controller/test/Test_forums.py create mode 100644 static/images/forums.png create mode 100644 view/Forums_page.py diff --git a/controller/Forums.py b/controller/Forums.py new file mode 100644 index 0000000..5eb668e --- /dev/null +++ b/controller/Forums.py @@ -0,0 +1,43 @@ +from Expose import expose +from Validate import validate +from Database import Valid_id, end_transaction +from Users import grab_user_id +from view.Forums_page import Forums_page + + +class Forums( object ): + """ + Controller for dealing with discussion forums, corresponding to the "/forums" URL. + """ + def __init__( self, database, users ): + """ + Create a new Forums object. + + @type database: controller.Database + @param database: database that forums are stored in + @type users: controller.Users + @param users: controller for all users + @rtype: Forums + @return: newly constructed Forums + """ + self.__database = database + self.__users = users + + @expose( view = Forums_page ) + @end_transaction + @grab_user_id + @validate( + user_id = Valid_id( none_okay = True ), + ) + def index( self, user_id ): + """ + Provide the information necessary to display the listing of available forums (currently hard-coded). + """ + result = self.__users.current( user_id ) + parents = [ notebook for notebook in result[ u"notebooks" ] if notebook.trash_id and not notebook.deleted ] + if len( parents ) > 0: + result[ "first_notebook" ] = parents[ 0 ] + else: + result[ "first_notebook" ] = None + + return result diff --git a/controller/Root.py b/controller/Root.py index 6867af7..06e656b 100644 --- a/controller/Root.py +++ b/controller/Root.py @@ -6,6 +6,7 @@ from Validate import validate, Valid_int, Valid_string from Notebooks import Notebooks from Users import Users, grab_user_id from Files import Files +from Forums import Forums from Database import Valid_id, end_transaction from model.Note import Note from model.Notebook import Notebook @@ -14,6 +15,7 @@ from view.Main_page import Main_page from view.Front_page import Front_page from view.Tour_page import Tour_page from view.Upgrade_page import Upgrade_page +from view.Forums_page import Forums_page from view.Notebook_rss import Notebook_rss from view.Json import Json from view.Error_page import Error_page @@ -47,6 +49,7 @@ class Root( object ): ) self.__files = Files( database, self.__users ) self.__notebooks = Notebooks( database, self.__users, self.__files, settings[ u"global" ].get( u"luminotes.https_url", u"" ) ) + self.__forums = Forums( database, self.__users ) self.__suppress_exceptions = suppress_exceptions # used for unit tests @expose( Main_page ) @@ -385,3 +388,4 @@ class Root( object ): notebooks = property( lambda self: self.__notebooks ) users = property( lambda self: self.__users ) files = property( lambda self: self.__files ) + forums = property( lambda self: self.__forums ) diff --git a/controller/test/Test_forums.py b/controller/test/Test_forums.py new file mode 100644 index 0000000..ec9a4a0 --- /dev/null +++ b/controller/test/Test_forums.py @@ -0,0 +1,55 @@ +import cherrypy +from model.Note import Note +from model.Notebook import Notebook +from model.User import User +from Test_controller import Test_controller + + +class Test_forums( Test_controller ): + def setUp( self ): + Test_controller.setUp( self ) + + 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.database.save( self.anon_notebook ) + self.anon_note = Note.create( + self.database.next_id( Note ), u"

my note

", + notebook_id = self.anon_notebook.object_id, + ) + self.database.save( self.anon_note ) + + self.login_note = Note.create( + self.database.next_id( Note ), u"

login

", + notebook_id = self.anon_notebook.object_id, + ) + self.database.save( self.login_note ) + + self.username = u"mulder" + self.password = u"trustno1" + self.email_address = u"outthere@example.com" + self.user = None + self.session_id = None + + self.user = User.create( self.database.next_id( User ), self.username, self.password, self.email_address ) + self.database.save( self.user ) + self.database.execute( self.user.sql_save_notebook( self.notebook.object_id ) ) + + self.anonymous = User.create( self.database.next_id( User ), u"anonymous" ) + self.database.save( self.anonymous ) + self.database.execute( self.anonymous.sql_save_notebook( self.anon_notebook.object_id ) ) + + 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" ] ) == 1 + assert result[ u"first_notebook" ] == None + assert result[ u"login_url" ] == u"https://luminotes.com/notebooks/%s?note_id=%s" % ( + self.anon_notebook.object_id, self.login_note.object_id, + ) + assert result[ u"logout_url" ] == u"https://luminotes.com/users/logout" + assert result[ u"rate_plan" ] diff --git a/static/css/product.css b/static/css/product.css index d84d594..94a10ab 100644 --- a/static/css/product.css +++ b/static/css/product.css @@ -198,6 +198,27 @@ margin: 0 auto; } +.forums_area { + text-align: center; + padding-top: 1em; + padding-bottom: 1em; + background-color: #ffffff; + border-bottom: 1px solid #cccccc; + margin: 0 auto; +} + +.forums_text { + text-align: left; + width: 500px; + margin: 0 auto; + margin-top: 1em; +} + +.forum_title { + font-weight: bold; + font-size: 105%; +} + .tour_screenshot { margin: 1.5em 1em 0.25em 1em; border: 1px solid #999999; diff --git a/static/html/support.html b/static/html/support.html index f0cb0f9..3d0cbf8 100644 --- a/static/html/support.html +++ b/static/html/support.html @@ -1,22 +1,35 @@

support

-

frequently asked questions

+

frequently asked questions

-The Luminotes faq covers some of the -most common questions about the software, so it's a good place to start. +The Luminotes faq covers some of the most common questions about the software, +so it's a good place to start.

-

Luminotes User Guide

+

user guide

-The User Guide explains every feature of -Luminotes in full detail, and it even includes tips for organizing your wiki. +The Luminotes user guide explains every feature of Luminotes in full detail, +and it even includes tips for organizing your wiki.

-

contact info

+

discussion forums

-Have a question? I'll be happy to answer it. Check out my contact info for details. +In the Luminotes discussion forums, you can ask about Luminotes features and +chat with your fellow Luminoters. +

+ +

blog

+ +

+With the Luminotes blog, you can stay up to date on all the latest features +and announcements. +

+ +

contact support

+ +

+Have a question? I'll be happy to answer it.

diff --git a/static/images/forums.png b/static/images/forums.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ed619c46d9cf0a2f05691499741b49fe437b43 GIT binary patch literal 5057 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 literal 0 HcmV?d00001 diff --git a/view/Forums_page.py b/view/Forums_page.py new file mode 100644 index 0000000..117ed3b --- /dev/null +++ b/view/Forums_page.py @@ -0,0 +1,46 @@ +from Product_page import Product_page +from Tags import Div, Img, A, P, Span, I, Br + + +class Forums_page( Product_page ): + def __init__( self, user, notebooks, first_notebook, login_url, logout_url, rate_plan ): + Product_page.__init__( + self, + user, + first_notebook, + login_url, + logout_url, + u"forums", # note title + + Div( + Div( + Img( + src = u"/static/images/forums.png", + width = u"335", height = u"47", + alt = u"Discussion Forums", + ), + ), + Div( + Span( A( u"technical support", href = u"/forums/support" ), class_ = u"forum_title" ), + P( u"Having a problem with your wiki? Something not working as expected? Ask about it here." ), + + Span( A( u"feature requests", href = u"/forums/features" ), class_ = u"forum_title" ), + P( u"Discuss your ideas for new Luminotes features and enhancements." ), + + Span( A( u"general discussion", href = u"/forums/general" ), class_ = u"forum_title" ), + P( u"Swap tips about making the most out of your personal wiki." ), + class_ = u"forums_text", + ), + class_ = u"forums_area", + ), + + Div( + P( + Span( u"Need more help?", class_ = u"hook_action_question" ), Br(), + A( u"Contact support directly", href = u"/contact_info", class_ = u"hook_action" ), + class_ = u"hook_action_area", + separator = u"", + ), + class_ = u"center_area", + ), + )