Browse Source

View groups that you're a member of, with an indicatation if you're an admin of that group.

  - modify controller.Users.current() to return the user's groups
    - update test_current() unit tests to expect empty groups list in results
  - modify Main_page, Notebook_rss, Front_page, Tour_page, and Upgrade_page to accept a new groups parameter
    - Main_page should add it as a hidden HTML variable
  - update Wiki.js to read the hidden groups variable and display the groups in account settings
Dan Helfman 10 years ago
parent
commit
df3d170362

+ 3
- 0
NEWS View File

@@ -1,3 +1,6 @@
1
+1.4.0: ??
2
+ * 
3
+
1 4
 1.3.40: May 27, 2008
2 5
  * Added some minor product page tweaks like meta description tags.
3 6
 

+ 5
- 0
controller/Users.py View File

@@ -5,6 +5,7 @@ import cherrypy
5 5
 from pytz import utc
6 6
 from datetime import datetime, timedelta
7 7
 from model.User import User
8
+from model.Group import Group
8 9
 from model.Notebook import Notebook
9 10
 from model.Note import Note
10 11
 from model.Password_reset import Password_reset
@@ -494,6 +495,7 @@ class Users( object ):
494 495
       'login_url': url,
495 496
       'logout_url': url,
496 497
       'rate_plan': rateplandict,
498
+      'groups': groups,
497 499
     }
498 500
     @raise Validation_error: one of the arguments is invalid
499 501
     @raise Access_error: user_id or anonymous user unknown
@@ -514,9 +516,11 @@ class Users( object ):
514 516
 
515 517
     if user_id and user_id != anonymous.object_id:
516 518
       notebooks = self.__database.select_many( Notebook, user.sql_load_notebooks() )
519
+      groups = self.__database.select_many( Group, user.sql_load_groups() )
517 520
     # if the user is not logged in, return a login URL
518 521
     else:
519 522
       notebooks = []
523
+      groups = []
520 524
       if len( anon_notebooks ) > 0 and anon_notebooks[ 0 ]:
521 525
         main_notebook = anon_notebooks[ 0 ]
522 526
         login_note = self.__database.select_one( Note, main_notebook.sql_load_note_by_title( u"login" ) )
@@ -529,6 +533,7 @@ class Users( object ):
529 533
       login_url = login_url,
530 534
       logout_url = self.__https_url + u"/users/logout",
531 535
       rate_plan = ( user.rate_plan < len( self.__rate_plans ) ) and self.__rate_plans[ user.rate_plan ] or {},
536
+      groups = groups,
532 537
     )
533 538
 
534 539
   def calculate_storage( self, user ):

+ 1
- 0
controller/test/Stub_database.py View File

@@ -7,6 +7,7 @@ class Stub_database( object ):
7 7
     # map of object id to list of saved objects (presumably in increasing order of revisions)
8 8
     self.objects = {}
9 9
     self.user_notebook = {} # map of user_id to ( notebook_id, read_write, owner )
10
+    self.user_group = {}    # map of user_id to ( group_id, admin )
10 11
     self.last_saved_obj = None
11 12
     self.last_saved_user = None
12 13
     self.__next_id = 0

+ 19
- 0
controller/test/Test_controller.py View File

@@ -179,6 +179,25 @@ class Test_controller( object ):
179 179
     User.sql_highest_notebook_rank = lambda self: \
180 180
       lambda database: sql_highest_notebook_rank( self, database )
181 181
 
182
+    def sql_load_groups( self, database ):
183
+      groups = []
184
+      group_infos = database.user_group.get( self.object_id )
185
+
186
+      if not group_infos: return []
187
+
188
+      for group_info in group_infos:
189
+        ( group_id, admin ) = group_info
190
+        group = database.objects.get( group_id )[ -1 ]
191
+        group.admin = admin
192
+        groups.append( group )
193
+
194
+      groups.sort( lambda a, b: cmp( a.name, b.name ) )
195
+
196
+      return groups
197
+
198
+    User.sql_load_groups = lambda self: \
199
+      lambda database: sql_load_groups( self, database )
200
+
182 201
     def sql_revoke_invite_access( notebook_id, trash_id, email_address, database ):
183 202
       invites = []
184 203
 

+ 12
- 0
controller/test/Test_users.py View File

@@ -195,6 +195,8 @@ class Test_users( Test_controller ):
195 195
     assert rate_plan[ u"name" ] == u"super"
196 196
     assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10
197 197
 
198
+    assert result[ u"groups" ] == []
199
+
198 200
   def test_current_after_signup_with_invite_id( self ):
199 201
     # trick send_invites() into using a fake SMTP server
200 202
     Stub_smtp.reset()
@@ -275,6 +277,8 @@ class Test_users( Test_controller ):
275 277
     assert rate_plan[ u"name" ] == u"super"
276 278
     assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10
277 279
 
280
+    assert result[ u"groups" ] == []
281
+
278 282
   def test_current_after_signup_with_rate_plan( self ):
279 283
     result = self.http_post( "/users/signup", dict(
280 284
       username = self.new_username,
@@ -331,6 +335,8 @@ class Test_users( Test_controller ):
331 335
     assert rate_plan[ u"name" ] == u"super"
332 336
     assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10
333 337
 
338
+    assert result[ u"groups" ] == []
339
+
334 340
   def test_signup_with_different_passwords( self ):
335 341
     result = self.http_post( "/users/signup", dict(
336 342
       username = self.new_username,
@@ -461,6 +467,8 @@ class Test_users( Test_controller ):
461 467
     assert rate_plan[ u"name" ] == u"super"
462 468
     assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10
463 469
 
470
+    assert result[ u"groups" ] == []
471
+
464 472
   def test_current_after_demo_twice( self ):
465 473
     result = self.http_post( "/users/demo", dict() )
466 474
     session_id = result[ u"session_id" ]
@@ -562,6 +570,8 @@ class Test_users( Test_controller ):
562 570
     assert rate_plan[ u"name" ] == u"super"
563 571
     assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10
564 572
 
573
+    assert result[ u"groups" ] == []
574
+
565 575
   def test_current_anonymous( self ):
566 576
     result = cherrypy.root.users.current( self.anonymous.object_id )
567 577
 
@@ -586,6 +596,8 @@ class Test_users( Test_controller ):
586 596
     assert rate_plan[ u"name" ] == u"super"
587 597
     assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10
588 598
 
599
+    assert result[ u"groups" ] == []
600
+
589 601
   def test_login_with_invite_id( self ):
590 602
     # trick send_invites() into using a fake SMTP server
591 603
     Stub_smtp.reset()

+ 1
- 1
model/User.py View File

@@ -229,7 +229,7 @@ class User( Persistent ):
229 229
     return \
230 230
       """
231 231
       select
232
-        luminiotes_group_current.*, user_group.admin
232
+        luminotes_group_current.*, user_group.admin
233 233
       from
234 234
         user_group, luminotes_group_current
235 235
       where

+ 22
- 1
static/js/Wiki.js View File

@@ -19,6 +19,7 @@ function Wiki( invoker ) {
19 19
   this.after_login = getElement( "after_login" ).value;
20 20
   this.signup_plan = getElement( "signup_plan" ).value;
21 21
   this.email_address = getElement( "email_address" ).value || "";
22
+  this.groups = evalJSON( getElement( "groups" ).value );
22 23
   this.font_size = null;
23 24
   this.small_toolbar = false;
24 25
   this.large_toolbar_bottom = 0;
@@ -1704,8 +1705,28 @@ Wiki.prototype.display_settings = function () {
1704 1705
     return;
1705 1706
   }
1706 1707
 
1708
+  var group_list = createDOM( "ul" );
1709
+  for ( var i in this.groups ) {
1710
+    var group = this.groups[ i ];
1711
+    var item = createDOM( "li", {} );
1712
+    appendChildNodes( item, group.name + " " );
1713
+    if ( group.admin )
1714
+      appendChildNodes( item, "(admin)" );
1715
+    appendChildNodes( group_list, item );
1716
+  }
1717
+
1718
+  if ( this.groups.length == 0 ) {
1719
+    var item = createDOM( "li", {}, "You're not a member of any groups." );
1720
+    appendChildNodes( group_list, item );
1721
+  }
1722
+
1707 1723
   var div = createDOM( "div", {}, 
1708 1724
     createDOM( "form", { "id": "settings_form" },
1725
+      createDOM( "p", {},
1726
+        createDOM( "b", {}, "group membership" ),
1727
+        createDOM( "br", {} ),
1728
+        group_list
1729
+      ),
1709 1730
       createDOM( "p", {},
1710 1731
         createDOM( "b", {}, "email address" ),
1711 1732
         createDOM( "br", {} ),
@@ -1719,7 +1740,7 @@ Wiki.prototype.display_settings = function () {
1719 1740
           { "type": "submit", "name": "settings_button", "id": "settings_button", "class": "button", "value": "save settings" }
1720 1741
         )
1721 1742
       ),
1722
-      createDOM( "p", {},
1743
+      createDOM( "p", { "class": "small_text" },
1723 1744
         "Your email address will ",
1724 1745
         createDOM( "a", { "href": "/privacy", "target": "_new" }, "never be shared" ),
1725 1746
         ". It will only be used for password resets, contacting you about account problems, and the from address in any invite emails you send."

+ 1
- 1
view/Front_page.py View File

@@ -3,7 +3,7 @@ from Tags import Div, Img, A, P, Table, Tr, Td, Li, Span, I, Br, Ul, Li
3 3
 
4 4
 
5 5
 class Front_page( Product_page ):
6
-  def __init__( self, user, notebooks, first_notebook, login_url, logout_url, rate_plan ):
6
+  def __init__( self, user, notebooks, first_notebook, login_url, logout_url, rate_plan, groups ):
7 7
     Product_page.__init__(
8 8
       self,
9 9
       user,

+ 2
- 0
view/Main_page.py View File

@@ -36,6 +36,7 @@ class Main_page( Page ):
36 36
     signup_plan = None,
37 37
     signup_yearly = None,
38 38
     recent_notes = None,
39
+    groups = None,
39 40
   ):
40 41
     startup_note_ids = [ startup_note.object_id for startup_note in startup_notes ]
41 42
 
@@ -144,6 +145,7 @@ class Main_page( Page ):
144 145
       Input( type = u"hidden", name = u"after_login", id = u"after_login", value = after_login ),
145 146
       Input( type = u"hidden", name = u"signup_plan", id = u"signup_plan", value = signup_plan ),
146 147
       Input( type = u"hidden", name = u"email_address", id = u"email_address", value = user.email_address ),
148
+      Input( type = u"hidden", name = u"groups", id = u"groups", value = json( groups ) ),
147 149
       Div(
148 150
         id = u"status_area",
149 151
       ),

+ 1
- 0
view/Notebook_rss.py View File

@@ -29,6 +29,7 @@ class Notebook_rss( Rss_channel ):
29 29
     signup_plan = None,
30 30
     signup_yearly = None,
31 31
     recent_notes = None,
32
+    groups = None,
32 33
   ):
33 34
     if notebook.name == u"Luminotes":
34 35
       notebook_path = u"/"

+ 1
- 1
view/Tour_page.py View File

@@ -3,7 +3,7 @@ from Tags import Div, H1, Img, A, Ol, Li, P, Span, I, Br
3 3
 
4 4
 
5 5
 class Tour_page( Product_page ):
6
-  def __init__( self, user, notebooks, first_notebook, login_url, logout_url, rate_plan ):
6
+  def __init__( self, user, notebooks, first_notebook, login_url, logout_url, rate_plan, groups ):
7 7
     Product_page.__init__(
8 8
       self,
9 9
       user,

+ 1
- 1
view/Upgrade_page.py View File

@@ -3,7 +3,7 @@ from Tags import Div, H1, Img, A, P, Table, Th, Tr, Td, Li, Span, I, Br, Ul, Li,
3 3
 
4 4
 
5 5
 class Upgrade_page( Product_page ):
6
-  def __init__( self, user, notebooks, first_notebook, login_url, logout_url, rate_plan, rate_plans, unsubscribe_button ):
6
+  def __init__( self, user, notebooks, first_notebook, login_url, logout_url, rate_plan, groups, rate_plans, unsubscribe_button ):
7 7
     MEGABYTE = 1024 * 1024
8 8
     rate_plans = list( rate_plans )
9 9
     rate_plans.reverse() # show rate plans highest to lowest