diff --git a/NEWS b/NEWS index c26446b..b0789cf 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +1.2.18: March ??, 2008 + * Newly redesigned upgrade/pricing/signup page. + 1.2.17: March 18, 2008 * Internet Explorer expects quoted download filenames, while Firefox doesn't. So I took that into account by quoting conditionally based on the diff --git a/controller/Root.py b/controller/Root.py index 2df7657..e1dd779 100644 --- a/controller/Root.py +++ b/controller/Root.py @@ -13,8 +13,8 @@ from model.User import User 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.Notebook_rss import Notebook_rss -from view.Upgrade_note import Upgrade_note from view.Json import Json from view.Error_page import Error_page from view.Not_found_page import Not_found_page @@ -79,6 +79,8 @@ class Root( object ): if note_title in ( u"sign_up", u"login" ) and https_url and cherrypy.request.remote_addr != https_proxy_ip: if invite_id: return dict( redirect = u"%s/%s?invite_id=%s" % ( https_url, note_title, invite_id ) ) + if after_login: + return dict( redirect = u"%s/%s?after_login=%s" % ( https_url, note_title, after_login ) ) else: return dict( redirect = u"%s/%s" % ( https_url, note_title ) ) @@ -270,48 +272,35 @@ class Root( object ): return result - @expose( view = Main_page ) + @expose( view = Upgrade_page ) @strongly_expire @end_transaction @grab_user_id @validate( user_id = Valid_id( none_okay = True ), ) - def upgrade( self, user_id = None ): + def pricing( self, user_id = None ): """ - Provide the information necessary to display the Luminotes upgrade page. + Provide the information necessary to display the Luminotes pricing page. """ - anonymous = self.__database.select_one( User, User.sql_load_by_username( u"anonymous" ) ) - if anonymous: - main_notebook = self.__database.select_one( Notebook, anonymous.sql_load_notebooks( undeleted_only = True ) ) - else: - main_notebook = None - - if user_id: - user = self.__database.load( User, user_id ) - else: - user = None - - https_url = self.__settings[ u"global" ].get( u"luminotes.https_url" ) result = self.__users.current( user_id ) - result[ "notebook" ] = main_notebook - result[ "startup_notes" ] = self.__database.select_many( Note, main_notebook.sql_load_startup_notes() ) - result[ "total_notes_count" ] = self.__database.select_one( Note, main_notebook.sql_count_notes() ) - result[ "note_read_write" ] = False - result[ "notes" ] = [ Note.create( - object_id = u"upgrade", - contents = unicode( Upgrade_note( - self.__settings[ u"global" ].get( u"luminotes.rate_plans", [] ), - self.__settings[ u"global" ].get( u"luminotes.unsubscribe_button" ), - https_url, - user, - ) ), - notebook_id = main_notebook.object_id, - ) ] - result[ "invites" ] = [] + 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 + + result[ "rate_plans" ] = self.__settings[ u"global" ].get( u"luminotes.rate_plans", [] ) + result[ "unsubscribe_button" ] = self.__settings[ u"global" ].get( u"luminotes.unsubscribe_button" ) return result + @expose() + def upgrade( self ): + return dict( + redirect = u"/pricing", + ) + # TODO: move this method to controller.Notebooks, and maybe give it a more sensible name @expose( view = Json ) @end_transaction diff --git a/controller/test/Test_root.py b/controller/test/Test_root.py index c328ceb..c0a8c7e 100644 --- a/controller/test/Test_root.py +++ b/controller/test/Test_root.py @@ -326,8 +326,8 @@ class Test_root( Test_controller ): assert u"error" not in result assert result[ u"notebook" ].object_id == self.privacy_notebook.object_id - def test_upgrade( self ): - result = self.http_get( "/upgrade" ) + def test_pricing( self ): + result = self.http_get( "/pricing" ) assert result[ u"user" ].username == u"anonymous" assert len( result[ u"notebooks" ] ) == 4 @@ -341,27 +341,14 @@ class Test_root( Test_controller ): assert rate_plan[ u"name" ] == u"super" assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10 - assert result[ u"notebook" ].object_id == self.anon_notebook.object_id - assert len( result[ u"startup_notes" ] ) == 0 - assert result[ u"note_read_write" ] is False + assert result[ u"first_notebook" ] == None + assert result[ u"rate_plans" ] == self.settings[ u"global" ].get( u"luminotes.rate_plans", [] ) + assert result[ u"unsubscribe_button" ] == self.settings[ u"global" ].get( u"luminotes.unsubscribe_button" ) - assert result[ u"notes" ] - assert len( result[ u"notes" ] ) == 1 - assert result[ u"notes" ][ 0 ].title == u"upgrade your wiki" - assert result[ u"notes" ][ 0 ].notebook_id == self.anon_notebook.object_id - - contents = result[ u"notes" ][ 0 ].contents - assert u"upgrade" in contents - assert u"Super" in contents - assert u"Extra super" in contents - - # since the user is not logged in, no subscription buttons should be shown - assert u"button" not in contents - - def test_upgrade_after_login( self ): + def test_pricing_after_login( self ): self.login() - result = self.http_get( "/upgrade", session_id = self.session_id ) + result = self.http_get( "/pricing", session_id = self.session_id ) assert result[ u"user" ].username == self.username assert len( result[ u"notebooks" ] ) == 5 @@ -375,22 +362,14 @@ class Test_root( Test_controller ): assert rate_plan[ u"name" ] == u"super" assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10 - assert result[ u"notebook" ].object_id == self.anon_notebook.object_id - assert len( result[ u"startup_notes" ] ) == 0 - assert result[ u"note_read_write" ] is False + assert result[ u"first_notebook" ].object_id == self.notebook.object_id + assert result[ u"rate_plans" ] == self.settings[ u"global" ].get( u"luminotes.rate_plans", [] ) + assert result[ u"unsubscribe_button" ] == self.settings[ u"global" ].get( u"luminotes.unsubscribe_button" ) - assert result[ u"notes" ] - assert len( result[ u"notes" ] ) == 1 - assert result[ u"notes" ][ 0 ].title == u"upgrade your wiki" - assert result[ u"notes" ][ 0 ].notebook_id == self.anon_notebook.object_id + def upgrade( self ): + result = self.http_get( "/upgrade" ) - contents = result[ u"notes" ][ 0 ].contents - assert u"upgrade" in contents - assert u"Super" in contents - assert u"Extra super" in contents - - # since the user is logged in, subscription buttons should be shown - assert u"button" in contents + assert result[ u"redirect" ] == u"/pricing" def test_next_id( self ): result = self.http_get( "/next_id" ) diff --git a/static/css/note.css b/static/css/note.css index aa9a497..2f34936 100644 --- a/static/css/note.css +++ b/static/css/note.css @@ -89,81 +89,6 @@ ol li { padding-right: 1em; } -#upgrade_table_area { - text-align: center; -} - -#upgrade_login_text { - font-weight: bold; - text-align: center; -} - -#upgrade_table { - border-collapse: collapse; - border: 1px solid #999999; - margin-left: auto; - margin-right: auto; -} - -#upgrade_table th { - padding: 0.5em; -} - -#upgrade_table td { - text-align: center; - background-color: #fafafa; - padding: 0.5em; -} - -#upgrade_table .plan_name { - width: 16%; - text-align: center; - background-color: #d0e0f0; -} - -#upgrade_table .feature_name { - width: 36%; - text-align: left; - background-color: #fafafa; -} - -#upgrade_table_small { - border-collapse: collapse; - border: 1px solid #999999; - margin-left: auto; - margin-right: auto; -} - -#upgrade_table_small th { - padding: 0.5em; -} - -#upgrade_table_small td { - text-align: center; - background-color: #fafafa; - padding: 0.5em; -} - -#upgrade_table_small .plan_name { - width: 33%; - text-align: center; - background-color: #d0e0f0; -} - -.price_text { - color: #ff6600; -} - -.month_text { - padding-top: 0.5em; - font-size: 75%; -} - -.subscribe_form { - margin-top: 0.5em; - margin-bottom: 0; -} - .thumbnail_left { float: left; margin: 0.5em; diff --git a/static/css/product.css b/static/css/product.css index ea764a4..192e096 100644 --- a/static/css/product.css +++ b/static/css/product.css @@ -105,10 +105,6 @@ margin-right: 20px; } -.hook_bullet_list { - list-style-type: none; -} - .hook_action_area { background-color: #ffff99; font-weight: bold; @@ -178,6 +174,10 @@ padding-bottom: 0.5em; } +.compact_list { + line-height: 100%; +} + .quotes_area { float: right; width: 400px; @@ -207,10 +207,12 @@ } .footer { + clear: both; background-color: #b0d0ff; height: 2em; margin-left: 0; margin-right: 0; + margin-top: 1em; border-top: 1px solid #999999; } @@ -247,3 +249,127 @@ .tour_screenshot_wrapper { padding: 1em; } + +.upgrade_subtitle { + text-align: center; + font-weight: bold; + padding-bottom: 0.5em; +} + +.upgrade_text { + text-align: left; +} + +.upgrade_area { + text-align: center; + padding-top: 1em; + padding-bottom: 1em; + background-color: #ffffff; + border-bottom: 1px solid #cccccc; + margin: 0 auto; + margin-bottom: 1em; +} + +.upgrade_table_area { + text-align: center; +} + +#upgrade_table { + border-collapse: collapse; + border: 1px solid #999999; + margin-left: auto; + margin-right: auto; + margin-bottom: 1em; +} + +#upgrade_table th { + padding: 0.5em; +} + +#upgrade_table td { + text-align: center; + background-color: #fafafa; + padding: 0.5em; +} + +#upgrade_table .plan_name { + width: 16%; + text-align: center; + background-color: #d0e0f0; +} + +#upgrade_table .feature_name { + width: 36%; + text-align: left; + background-color: #fafafa; +} + +#upgrade_table_small { + clear: both; + border-collapse: collapse; + border: 1px solid #999999; + margin-left: auto; + margin-right: auto; +} + +#upgrade_table_small th { + padding: 0.5em; +} + +#upgrade_table_small td { + text-align: center; + background-color: #fafafa; + padding: 0.5em; +} + +#upgrade_table_small .plan_name { + width: 33%; + text-align: center; + background-color: #d0e0f0; +} + +.price_text { + color: #ff6600; +} + +.month_text { + padding-top: 0.5em; + font-size: 75%; +} + +.subscribe_form { + margin-top: 0.5em; + margin-bottom: 0; +} + +.sign_up_button_area { + margin-top: 0.5em; +} + +.upgrade_left_area { + width: 400px; + margin-bottom: 1em; +} + +.upgrade_right_area { + float: right; + width: 400px; + margin-left: 20px; + margin-bottom: 1em; +} + +.thumbnail_left { + float: left; + margin: 0.5em; + margin-right: 1em; + margin-bottom: 0.5em; + border: 1px solid #999999; +} + +.thumbnail_right { + float: right; + margin: 0.5em; + margin-left: 1em; + margin-bottom: 0.5em; + border: 1px solid #999999; +} diff --git a/static/html/sign up.html b/static/html/sign up.html index 9469b5f..de0d15e 100644 --- a/static/html/sign up.html +++ b/static/html/sign up.html @@ -1,20 +1,15 @@

sign up

-To get started with your own personal wiki, all you need to do is sign up for -an account. There's nothing to download or install. +There's nothing to download or install.

-If you haven't seen it already, try the -demo first! The Luminotes demo doesn't require any sort of sign up. +If you're not ready to sign up +yet, try the demo first!

-Providing your email address is completely optional. I only ask for it -in case you ever need your password reset. Your email address will absolutely -not be given out or used for spam. -

@@ -28,12 +23,12 @@ not be given out or used for spam.

-password (again)
+password (again)

-email address (optional)
+email address (optional and never shared)

diff --git a/static/images/more_collaboration.png b/static/images/more_collaboration.png new file mode 100644 index 0000000..2519586 Binary files /dev/null and b/static/images/more_collaboration.png differ diff --git a/static/images/more_collaboration.xcf b/static/images/more_collaboration.xcf new file mode 100644 index 0000000..49b7b2b Binary files /dev/null and b/static/images/more_collaboration.xcf differ diff --git a/static/images/more_room_to_stretch_out.png b/static/images/more_room_to_stretch_out.png new file mode 100644 index 0000000..e64a185 Binary files /dev/null and b/static/images/more_room_to_stretch_out.png differ diff --git a/static/images/more_room_to_stretch_out.xcf b/static/images/more_room_to_stretch_out.xcf new file mode 100644 index 0000000..2650457 Binary files /dev/null and b/static/images/more_room_to_stretch_out.xcf differ diff --git a/static/images/sign_up.png b/static/images/sign_up.png new file mode 100644 index 0000000..1cd64e2 Binary files /dev/null and b/static/images/sign_up.png differ diff --git a/static/images/sign_up.xcf b/static/images/sign_up.xcf new file mode 100644 index 0000000..b686d11 Binary files /dev/null and b/static/images/sign_up.xcf differ diff --git a/static/images/sign_up_button.png b/static/images/sign_up_button.png new file mode 100644 index 0000000..c1c7250 Binary files /dev/null and b/static/images/sign_up_button.png differ diff --git a/static/images/sign_up_button.xcf b/static/images/sign_up_button.xcf new file mode 100644 index 0000000..54c2d7c Binary files /dev/null and b/static/images/sign_up_button.xcf differ diff --git a/static/images/subscribe_button.png b/static/images/subscribe_button.png new file mode 100644 index 0000000..8b325d9 Binary files /dev/null and b/static/images/subscribe_button.png differ diff --git a/static/images/subscribe_button.xcf b/static/images/subscribe_button.xcf new file mode 100644 index 0000000..af0bb3e Binary files /dev/null and b/static/images/subscribe_button.xcf differ diff --git a/static/images/unsubscribe_button.png b/static/images/unsubscribe_button.png new file mode 100644 index 0000000..2e9fa54 Binary files /dev/null and b/static/images/unsubscribe_button.png differ diff --git a/static/images/unsubscribe_button.xcf b/static/images/unsubscribe_button.xcf new file mode 100644 index 0000000..964dc5b Binary files /dev/null and b/static/images/unsubscribe_button.xcf differ diff --git a/static/images/upgrade.png b/static/images/upgrade.png new file mode 100644 index 0000000..86f3bb7 Binary files /dev/null and b/static/images/upgrade.png differ diff --git a/static/images/upgrade.xcf b/static/images/upgrade.xcf new file mode 100644 index 0000000..1e1c484 Binary files /dev/null and b/static/images/upgrade.xcf differ diff --git a/static/images/zero_hassle.png b/static/images/zero_hassle.png new file mode 100644 index 0000000..84d492a Binary files /dev/null and b/static/images/zero_hassle.png differ diff --git a/static/images/zero_hassle.xcf b/static/images/zero_hassle.xcf new file mode 100644 index 0000000..dbcfbe8 Binary files /dev/null and b/static/images/zero_hassle.xcf differ diff --git a/view/Front_page.py b/view/Front_page.py index 2893158..6fc2c81 100644 --- a/view/Front_page.py +++ b/view/Front_page.py @@ -1,5 +1,5 @@ from Product_page import Product_page -from Tags import Div, Img, A, P, Table, Tr, Td, Li, Span, I, Br +from Tags import Div, Img, A, P, Table, Tr, Td, Li, Span, I, Br, Ul, Li class Front_page( Product_page ): @@ -49,7 +49,7 @@ class Front_page( Product_page ): A( u"Take a tour", href = u"/tour", class_ = u"hook_action" ), u", ", A( u"Try the demo", href = u"/users/demo", class_ = u"hook_action" ), u", ", Span( u" or ", class_ = u"hook_action_or" ), - A( u"Sign up", href = u"/sign_up", class_ = u"hook_action" ), + A( u"Sign up", href = u"/pricing", class_ = u"hook_action" ), class_ = u"hook_action_area", separator = u"", ), @@ -70,6 +70,27 @@ class Front_page( Product_page ): ), ), + Div( + Div( + u'"', + Span( + u"As soon as I saw Luminotes I knew it was what I and my students needed.", + class_ = u"quote_title", + separator = u"", + ), + u""" + Clear, easy to use and beautifully simple. + """, + class_ = u"quote_text", + separator = u"", + ), + Div( + u"-Jonathan Lecun, Director, ", A( u"UK Teachers Online", href = u"http://www.ukteachersonline.co.uk/" ), + class_ = u"quote_signature" + ), + class_ = u"quote", + ), + Div( Div( u'"', @@ -94,6 +115,29 @@ class Front_page( Product_page ): class_ = u"quote", ), + Div( + Div( + u'"', + Span( + u"I'm a wiki addict, so I've tried most of them, desktop and web-based.", + class_ = u"quote_title", + separator = u"", + ), + u""" + What I like about your excellent product is the modeless editing (no edit + and save buttons). This makes Luminotes the fastest web-based wiki I have + used. + """, + class_ = u"quote_text", + separator = u"", + ), + Div( + u"-Scott Tiner", + class_ = u"quote_signature" + ), + class_ = u"quote", + ), + Div( Div( u'"', @@ -194,6 +238,17 @@ class Front_page( Product_page ): ), class_ = u"thumbnail_area", ), + P( + u"What can you do with Luminotes?", + ), + Ul( + Li( u"Plan a story" ), + Li( u"Collect recipes" ), + Li( u"Record your ideas" ), + Li( u"Keep track of your tasks" ), + Li( u"Take notes" ), + class_ = u"compact_list", + ), P( u""" Luminotes is open source / free software and licensed under the terms of the @@ -202,24 +257,23 @@ class Front_page( Product_page ): ), class_ = u"what_is_luminotes_text", ), + Div( + P( + Span( u"Sound interesting?", class_ = u"hook_action_question" ), Br(), + A( u"Take a tour", href = u"/tour", class_ = u"hook_action" ), u", ", + A( u"Try the demo", href = u"/users/demo", class_ = u"hook_action" ), u", ", + Span( u" or ", class_ = u"hook_action_or" ), + A( u"Sign up", href = u"/pricing", class_ = u"hook_action" ), + class_ = u"hook_action_area", + separator = u"", + ), + ), class_ = u"what_is_luminotes_area", ), class_ = u"wide_center_area", ), - Div( - P( - Span( u"Sound interesting?", class_ = u"hook_action_question" ), Br(), - A( u"Take a tour", href = u"/tour", class_ = u"hook_action" ), u", ", - A( u"Try the demo", href = u"/users/demo", class_ = u"hook_action" ), u", ", - Span( u" or ", class_ = u"hook_action_or" ), - A( u"Sign up", href = u"/sign_up", class_ = u"hook_action" ), - class_ = u"hook_action_area", - separator = u"", - ), - class_ = u"center_area", - ), P( Span( id = u"new_note_button_preload" ), Span( id = u"link_button_preload" ), diff --git a/view/Product_page.py b/view/Product_page.py index 790e8df..d234b9f 100644 --- a/view/Product_page.py +++ b/view/Product_page.py @@ -18,7 +18,8 @@ class Product_page( Page ): Div( ( note_title == u"home" ) and title_image or A( title_image, href = u"/" ), ( login_url and user.username == u"anonymous" ) and Div( - A( u"sign up", href = u"/sign_up", class_ = u"bold_link" ), u" | ", + ( note_title == u"pricing" ) and Span( u"pricing & sign up", class_ = u"bold_link" ) or \ + A( u"pricing & sign up", href = u"/pricing", class_ = u"bold_link" ), u" | ", A( u"login", href = login_url, @@ -39,16 +40,18 @@ class Product_page( Page ): user.username and Span( A( u"upgrade", - href = u"/upgrade", + href = u"/pricing", title = u"Upgrade your Luminotes account.", class_ = u"bold_link", ), " | ", ) or Span( + ( note_title == u"pricing" ) and Span( u"pricing & sign up", class_ = u"bold_link" ) or \ A( - u"sign up", - href = u"/sign_up", + u"pricing & sign up", + href = u"/pricing", title = u"Sign up for a real Luminotes account.", + class_ = u"bold_link", ), " | ", ) or None, @@ -64,7 +67,6 @@ class Product_page( Page ): ( note_title == u"home" ) and Span( u"home", class_ = u"bold_link" ) or A( u"home", href = u"/" ), u" | ", ( note_title == u"tour" ) and Span( u"tour", class_ = u"bold_link" ) or A( u"tour", href = u"/tour" ), u" | ", ( note_title == u"demo" ) and Span( u"demo", class_ = u"bold_link" ) or A( u"demo", href = u"/users/demo" ), u" | ", - ( note_title == u"upgrade" ) and Span( u"upgrade", class_ = u"bold_link" ) or A( u"pricing", href = u"/upgrade" ), u" | ", ( note_title == u"faq" ) and Span( u"faq", class_ = u"bold_link" ) or A( u"faq", href = u"/faq" ), u" | ", ( note_title == u"guide" ) and Span( u"guide", class_ = u"bold_link" ) or A( u"help", href = u"/guide" ), u" | ", ( note_title == u"contact" ) and Span( u"contact", class_ = u"bold_link" ) or A( u"contact", href = u"/contact_info" ), u" | ", diff --git a/view/Thanks_error_note.py b/view/Thanks_error_note.py index 5a59a52..9e85e3d 100644 --- a/view/Thanks_error_note.py +++ b/view/Thanks_error_note.py @@ -25,7 +25,7 @@ class Thanks_error_note( Span ): u""" Note: You can check the current status of your account by refreshing the """, - A( u"upgrade", href = u"/upgrade", target = "_top" ), + A( u"upgrade", href = u"/pricing", target = "_top" ), u""" page while logged in. """ diff --git a/view/Tour_page.py b/view/Tour_page.py index bd98423..37b49f9 100644 --- a/view/Tour_page.py +++ b/view/Tour_page.py @@ -74,7 +74,7 @@ class Tour_page( Product_page ): Span( u"Like what you've seen so far?", class_ = u"hook_action_question" ), Br(), A( u"Try the demo", href = u"/users/demo", class_ = u"hook_action" ), Span( u" or ", class_ = u"hook_action_or" ), - A( u"Sign up", href = u"/sign_up", class_ = u"hook_action" ), + A( u"Sign up", href = u"/pricing", class_ = u"hook_action" ), class_ = u"hook_action_area", separator = u"", ), diff --git a/view/Upgrade_page.py b/view/Upgrade_page.py new file mode 100644 index 0000000..4cc2446 --- /dev/null +++ b/view/Upgrade_page.py @@ -0,0 +1,190 @@ +from Product_page import Product_page +from Tags import Div, Img, A, P, Table, Th, Tr, Td, Li, Span, I, Br, Ul, Li + + +class Upgrade_page( Product_page ): + def __init__( self, user, notebooks, first_notebook, login_url, logout_url, rate_plan, rate_plans, unsubscribe_button ): + MEGABYTE = 1024 * 1024 + + Product_page.__init__( + self, + user, + first_notebook, + login_url, + logout_url, + u"pricing", # note title + + Div( + Div( + user and user.username not in ( None, u"anonymous" ) and Div( + Img( + src = u"/static/images/upgrade.png", + width = u"152", height = u"51", + alt = u"Upgrade", + ), + ) or Div( + Img( + src = u"/static/images/sign_up.png", + width = u"138", height = u"51", + alt = u"Sign Up", + ), + ), + P( + """ + Upgrade, downgrade, or cancel anytime. 60-day money-back guarantee. + """, + class_ = u"upgrade_subtitle", + ), + P( + Table( + self.fee_row( rate_plans, user ), + Tr( + Td( u"Included storage space", class_ = u"feature_name" ), + [ Td( + plan[ u"storage_quota_bytes" ] // MEGABYTE, " MB", + ) for plan in rate_plans ], + ), + Tr( + Td( u"Unlimited wiki notebooks", class_ = u"feature_name" ), + [ Td( + Img( src = u"/static/images/check.png", width = u"20", height = u"17" ), + ) for plan in rate_plans ], + ), + Tr( + Td( u"Friendly email support", class_ = u"feature_name" ), + [ Td( + Img( src = u"/static/images/check.png", width = u"20", height = u"17" ), + ) for plan in rate_plans ], + ), + Tr( + Td( u"Invite people to view your wiki", class_ = u"feature_name" ), + [ Td( + Img( src = u"/static/images/check.png", width = u"20", height = u"17" ), + ) for plan in rate_plans ], + ), + Tr( + Td( u"Invite people to edit your wiki", class_ = u"feature_name" ), + [ Td( + plan[ u"notebook_collaboration" ] and + Img( src = u"/static/images/check.png", width = u"20", height = u"17" ) or u" ", + ) for plan in rate_plans ], + ), + Tr( + Td( u"Wiki access control", class_ = u"feature_name" ), + [ Td( + plan[ u"notebook_collaboration" ] and + Img( src = u"/static/images/check.png", width = u"20", height = u"17" ) or u" ", + ) for plan in rate_plans ], + ), + border = u"1", + id = u"upgrade_table", + ), + class_ = u"upgrade_table_area", + ), + + user and user.username and P( + u"You're currently subscribed to Luminotes %s." % + rate_plans[ user.rate_plan ][ u"name" ].capitalize(), + ( user.rate_plan > 0 ) and unsubscribe_button or None, + ) or None, + class_ = u"upgrade_area", + ), + + Div( + Div( + Img( + src = u"/static/images/more_room_to_stretch_out.png", + width = u"280", height = u"29", + alt = u"More room to stretch out", + ), + Ul( + Li( u"More room for your wiki notes." ), + Li( u"More room for your documents and files." ), + class_ = u"upgrade_text", + ), + Img( + src = u"/static/images/zero_hassle.png", + width = u"122", height = u"29", + alt = u"Zero hassle", + ), + Ul( + Li( u"Cancel online anytime without losing access to your wiki." ), + Li( u"60-day money-back guarantee. No questions asked." ), + Li( u"No lock-in: Download your entire wiki anytime." ), + class_ = u"upgrade_text", + ), + class_= u"upgrade_right_area", + ), + + Div( + Img( + src = u"/static/images/more_collaboration.png", + width = u"204", height = u"29", + alt = u"More collaboration", + ), + P( + Ul( + Li( u"Invite specific people to collaborate on your wiki." ), + Li( u"Decide who can edit and who can only view." ), + Li( u"Invite as many people as you want. They only need free Luminotes accounts." ), + Li( u"Revoke access with a single click." ), + Li( u"Share only the notebooks you want to share. Keep the others private." ), + class_ = u"upgrade_text", + ), + ), + class_= u"upgrade_left_area", + ), + + P( + Table( + self.fee_row( rate_plans, user, include_blank = False ), + Tr( + [ Td( + plan[ u"storage_quota_bytes" ] // MEGABYTE, " MB", + ) for plan in rate_plans ], + ), + border = u"1", + id = u"upgrade_table_small", + ), + class_= u"upgrade_table_area", + ), + + Div( + P( + Span( u"Have a question before you sign up?", class_ = u"hook_action_question" ), Br(), + A( u"Contact support", href = u"/contact_info", class_ = u"hook_action" ), + class_ = u"hook_action_area", + separator = u"", + ), + class_ = u"center_area", + ), + + class_ = u"wide_center_area", + ), + ), + ) + + def fee_row( self, rate_plans, user, include_blank = True ): + return Tr( + include_blank and Th( u" " ) or None, + [ Th( + plan[ u"name" ].capitalize(), + plan[ u"fee" ] and Div( + Span( + u"$%s" % plan[ u"fee" ], + Span( u"/month", class_ = u"month_text" ), + class_ = u"price_text", + separator = u"", + ), + user and user.username and user.rate_plan != index and plan.get( u"button" ).strip() and plan.get( u"button" ) % user.object_id, + ) or None, + ( not user or user.username in ( u"anonymous", None ) ) and Div( + A( + Img( src = u"/static/images/sign_up_button.png", width = "76", height = "23" ), + href = u"/sign_up?plan=%s" % index, + ), + class_ = u"sign_up_button_area", + ) or None, + class_ = u"plan_name", + ) for ( index, plan ) in enumerate( rate_plans ) ], + ) diff --git a/view/User_area.py b/view/User_area.py index 5dd0cb4..90947dc 100644 --- a/view/User_area.py +++ b/view/User_area.py @@ -17,14 +17,14 @@ class User_area( Div ): user.username and Span( A( u"upgrade", - href = u"/upgrade", + href = u"/pricing", title = u"Upgrade your Luminotes account.", ), " | ", ) or Span( A( u"sign up", - href = u"/sign_up", + href = u"/pricing", title = u"Sign up for a real Luminotes account.", ), " | ",