Added ability to reorder notebooks on the right side of the page.
Need to complete unit tests for controller.Notebooks.move_up() and move_down().
This commit is contained in:
parent
68fe84b707
commit
94a51889f9
3
NEWS
3
NEWS
|
@ -1,3 +1,6 @@
|
|||
1.2.14: March ??, 2008
|
||||
* Added ability to reorder notebooks on the right side of the page.
|
||||
|
||||
1.2.13: March 11, 2008
|
||||
* When the "all notes" note is the only note open, it now actually hides when
|
||||
the "hide" button is clicked.
|
||||
|
|
|
@ -505,7 +505,7 @@ class Notebooks( object ):
|
|||
note.startup = startup
|
||||
if startup:
|
||||
if note.rank is None:
|
||||
note.rank = self.__database.select_one( float, notebook.sql_highest_rank() ) + 1
|
||||
note.rank = self.__database.select_one( float, notebook.sql_highest_note_rank() ) + 1
|
||||
else:
|
||||
note.rank = None
|
||||
note.user_id = user.object_id
|
||||
|
@ -538,7 +538,7 @@ class Notebooks( object ):
|
|||
# otherwise, create a new note
|
||||
else:
|
||||
if startup:
|
||||
rank = self.__database.select_one( float, notebook.sql_highest_rank() ) + 1
|
||||
rank = self.__database.select_one( float, notebook.sql_highest_note_rank() ) + 1
|
||||
else:
|
||||
rank = None
|
||||
|
||||
|
@ -875,7 +875,8 @@ class Notebooks( object ):
|
|||
self.__database.save( notebook, commit = False )
|
||||
|
||||
# record the fact that the user has access to their new notebook
|
||||
self.__database.execute( user.sql_save_notebook( notebook_id, read_write = True, owner = True ), commit = False )
|
||||
rank = self.__database.select_one( float, user.sql_highest_notebook_rank() ) + 1
|
||||
self.__database.execute( user.sql_save_notebook( notebook_id, read_write = True, owner = True, rank = rank ), commit = False )
|
||||
self.__database.execute( user.sql_save_notebook( trash_id, read_write = True, owner = True ), commit = False )
|
||||
|
||||
if commit:
|
||||
|
@ -1071,6 +1072,149 @@ class Notebooks( object ):
|
|||
redirect = u"/notebooks/%s" % notebook.object_id,
|
||||
)
|
||||
|
||||
@expose( view = Json )
|
||||
@grab_user_id
|
||||
@validate(
|
||||
notebook_id = Valid_id(),
|
||||
user_id = Valid_id( none_okay = True ),
|
||||
)
|
||||
def move_up( self, notebook_id, user_id ):
|
||||
"""
|
||||
Reorder the user's notebooks by moving the given notebook up by one. If the notebook is already
|
||||
first, then wrap it around to be the last notebook.
|
||||
|
||||
@type notebook_id: unicode
|
||||
@param notebook_id: id of notebook to move up
|
||||
@type user_id: unicode or NoneType
|
||||
@param user_id: id of current logged-in user (if any)
|
||||
@rtype json dict
|
||||
@return {}
|
||||
@raise Access_error: the current user doesn't have access to the given notebook
|
||||
@raise Validation_error: one of the arguments is invalid
|
||||
"""
|
||||
if not self.__users.check_access( user_id, notebook_id ):
|
||||
raise Access_error()
|
||||
|
||||
user = self.__database.load( User, user_id )
|
||||
if not user:
|
||||
raise Access_error()
|
||||
|
||||
# load the notebooks to which this user has access
|
||||
notebooks = self.__database.select_many(
|
||||
Notebook,
|
||||
user.sql_load_notebooks( parents_only = True, undeleted_only = True ),
|
||||
)
|
||||
if not notebooks:
|
||||
raise Access_error()
|
||||
|
||||
# find the given notebook and the one previous to it
|
||||
previous_notebook = None
|
||||
current_notebook = None
|
||||
|
||||
for notebook in notebooks:
|
||||
if notebook.object_id == notebook_id:
|
||||
current_notebook = notebook
|
||||
break
|
||||
previous_notebook = notebook
|
||||
|
||||
if current_notebook is None:
|
||||
raise Access_error()
|
||||
|
||||
# if there is no previous notebook, then the current notebook is first. so, move it after the
|
||||
# last notebook
|
||||
if previous_notebook is None:
|
||||
last_notebook = notebooks[ -1 ]
|
||||
self.__database.execute(
|
||||
user.sql_update_notebook_rank( current_notebook.object_id, last_notebook.rank + 1 ),
|
||||
commit = False,
|
||||
)
|
||||
# otherwise, save the current and previous notebooks back to the database with swapped ranks
|
||||
else:
|
||||
self.__database.execute(
|
||||
user.sql_update_notebook_rank( current_notebook.object_id, previous_notebook.rank ),
|
||||
commit = False,
|
||||
)
|
||||
self.__database.execute(
|
||||
user.sql_update_notebook_rank( previous_notebook.object_id, current_notebook.rank ),
|
||||
commit = False,
|
||||
)
|
||||
|
||||
self.__database.commit()
|
||||
|
||||
return dict()
|
||||
|
||||
@expose( view = Json )
|
||||
@grab_user_id
|
||||
@validate(
|
||||
notebook_id = Valid_id(),
|
||||
user_id = Valid_id( none_okay = True ),
|
||||
)
|
||||
def move_down( self, notebook_id, user_id ):
|
||||
"""
|
||||
Reorder the user's notebooks by moving the given notebook down by one. If the notebook is
|
||||
already last, then wrap it around to be the first notebook.
|
||||
|
||||
@type notebook_id: unicode
|
||||
@param notebook_id: id of notebook to move down
|
||||
@type user_id: unicode or NoneType
|
||||
@param user_id: id of current logged-in user (if any)
|
||||
@rtype json dict
|
||||
@return {}
|
||||
@raise Access_error: the current user doesn't have access to the given notebook
|
||||
@raise Validation_error: one of the arguments is invalid
|
||||
"""
|
||||
if not self.__users.check_access( user_id, notebook_id ):
|
||||
raise Access_error()
|
||||
|
||||
user = self.__database.load( User, user_id )
|
||||
if not user:
|
||||
raise Access_error()
|
||||
|
||||
# load the notebooks to which this user has access
|
||||
notebooks = self.__database.select_many(
|
||||
Notebook,
|
||||
user.sql_load_notebooks( parents_only = True, undeleted_only = True ),
|
||||
)
|
||||
if not notebooks:
|
||||
raise Access_error()
|
||||
|
||||
# find the given notebook and the one after it
|
||||
current_notebook = None
|
||||
next_notebook = None
|
||||
|
||||
for notebook in notebooks:
|
||||
if notebook.object_id == notebook_id:
|
||||
current_notebook = notebook
|
||||
elif current_notebook:
|
||||
next_notebook = notebook
|
||||
break
|
||||
|
||||
if current_notebook is None:
|
||||
raise Access_error()
|
||||
|
||||
# if there is no next notebook, then the current notebook is last. so, move it before the
|
||||
# first notebook
|
||||
if next_notebook is None:
|
||||
first_notebook = notebooks[ 0 ]
|
||||
self.__database.execute(
|
||||
user.sql_update_notebook_rank( current_notebook.object_id, first_notebook.rank - 1 ),
|
||||
commit = False,
|
||||
)
|
||||
# otherwise, save the current and next notebooks back to the database with swapped ranks
|
||||
else:
|
||||
self.__database.execute(
|
||||
user.sql_update_notebook_rank( current_notebook.object_id, next_notebook.rank ),
|
||||
commit = False,
|
||||
)
|
||||
self.__database.execute(
|
||||
user.sql_update_notebook_rank( next_notebook.object_id, current_notebook.rank ),
|
||||
commit = False,
|
||||
)
|
||||
|
||||
self.__database.commit()
|
||||
|
||||
return dict()
|
||||
|
||||
def load_recent_notes( self, notebook_id, start = 0, count = 10, user_id = None ):
|
||||
"""
|
||||
Provide the information necessary to display the page for a particular notebook's most recent
|
||||
|
|
|
@ -262,7 +262,7 @@ class Users( object ):
|
|||
self.__database.save( user, commit = False )
|
||||
|
||||
# record the fact that the new user has access to their new notebook
|
||||
self.__database.execute( user.sql_save_notebook( notebook_id, read_write = True, owner = True ), commit = False )
|
||||
self.__database.execute( user.sql_save_notebook( notebook_id, read_write = True, owner = True, rank = 0 ), commit = False )
|
||||
self.__database.execute( user.sql_save_notebook( trash_id, read_write = True, owner = True ), commit = False )
|
||||
self.__database.commit()
|
||||
|
||||
|
@ -335,7 +335,7 @@ class Users( object ):
|
|||
self.__database.save( user, commit = False )
|
||||
|
||||
# record the fact that the new user has access to their new notebook
|
||||
self.__database.execute( user.sql_save_notebook( notebook_id, read_write = True, owner = True ), commit = False )
|
||||
self.__database.execute( user.sql_save_notebook( notebook_id, read_write = True, owner = True, rank = 0 ), commit = False )
|
||||
self.__database.execute( user.sql_save_notebook( trash_id, read_write = True, owner = True ), commit = False )
|
||||
self.__database.commit()
|
||||
|
||||
|
@ -966,7 +966,8 @@ class Users( object ):
|
|||
|
||||
# if the user doesn't already have access to this notebook, then grant access
|
||||
if not self.__database.select_one( bool, user.sql_has_access( notebook.object_id ) ):
|
||||
self.__database.execute( user.sql_save_notebook( notebook.object_id, invite.read_write, invite.owner ), commit = False )
|
||||
rank = self.__database.select_one( float, user.sql_highest_notebook_rank() ) + 1
|
||||
self.__database.execute( user.sql_save_notebook( notebook.object_id, invite.read_write, invite.owner, rank = rank ), commit = False )
|
||||
|
||||
# the same goes for the trash notebook
|
||||
if not self.__database.select_one( bool, user.sql_has_access( notebook.trash_id ) ):
|
||||
|
|
|
@ -41,14 +41,14 @@ class Test_controller( object ):
|
|||
# SQL-returning methods in User, Note, and Notebook to return functions that manipulate data in
|
||||
# Stub_database directly instead. This is all a little fragile, but it's better than relying on
|
||||
# the presence of a real database for unit tests.
|
||||
def sql_save_notebook( self, notebook_id, read_write, owner, database ):
|
||||
def sql_save_notebook( self, notebook_id, read_write, owner, rank, database ):
|
||||
if self.object_id in database.user_notebook:
|
||||
database.user_notebook[ self.object_id ].append( ( notebook_id, read_write, owner ) )
|
||||
database.user_notebook[ self.object_id ].append( ( notebook_id, read_write, owner, rank ) )
|
||||
else:
|
||||
database.user_notebook[ self.object_id ] = [ ( notebook_id, read_write, owner ) ]
|
||||
database.user_notebook[ self.object_id ] = [ ( notebook_id, read_write, owner, rank ) ]
|
||||
|
||||
User.sql_save_notebook = lambda self, notebook_id, read_write = False, owner = False: \
|
||||
lambda database: sql_save_notebook( self, notebook_id, read_write, owner, database )
|
||||
User.sql_save_notebook = lambda self, notebook_id, read_write = False, owner = False, rank = None: \
|
||||
lambda database: sql_save_notebook( self, notebook_id, read_write, owner, rank, database )
|
||||
|
||||
def sql_remove_notebook( self, notebook_id, database ):
|
||||
if self.object_id in database.user_notebook:
|
||||
|
@ -66,10 +66,11 @@ class Test_controller( object ):
|
|||
if not notebook_infos: return []
|
||||
|
||||
for notebook_info in notebook_infos:
|
||||
( notebook_id, notebook_read_write, owner ) = notebook_info
|
||||
( notebook_id, notebook_read_write, owner, rank ) = notebook_info
|
||||
notebook = database.objects.get( notebook_id )[ -1 ]
|
||||
notebook.read_write = notebook_read_write
|
||||
notebook.owner = owner
|
||||
notebook.rank = rank
|
||||
if parents_only and notebook.trash_id is None:
|
||||
continue
|
||||
if undeleted_only and notebook.deleted is True:
|
||||
|
@ -118,7 +119,7 @@ class Test_controller( object ):
|
|||
def sql_has_access( self, notebook_id, read_write, owner, database ):
|
||||
for ( user_id, notebook_infos ) in database.user_notebook.items():
|
||||
for notebook_info in notebook_infos:
|
||||
( db_notebook_id, db_read_write, db_owner ) = notebook_info
|
||||
( db_notebook_id, db_read_write, db_owner, rank ) = notebook_info
|
||||
|
||||
if self.object_id == user_id and notebook_id == db_notebook_id:
|
||||
if read_write is True and db_read_write is False:
|
||||
|
@ -135,23 +136,53 @@ class Test_controller( object ):
|
|||
def sql_update_access( self, notebook_id, read_write, owner, database ):
|
||||
for ( user_id, notebook_infos ) in database.user_notebook.items():
|
||||
for notebook_info in notebook_infos:
|
||||
( db_notebook_id, db_read_write, db_owner ) = notebook_info
|
||||
( db_notebook_id, db_read_write, db_owner, rank ) = notebook_info
|
||||
|
||||
if self.object_id == user_id and notebook_id == db_notebook_id:
|
||||
notebook_infos_copy = list( notebook_infos )
|
||||
notebook_infos_copy.remove( notebook_info )
|
||||
notebook_infos_copy.append( ( notebook_id, read_write, owner ) )
|
||||
notebook_infos_copy.append( ( notebook_id, read_write, owner, rank ) )
|
||||
database.user_notebook[ user_id ] = notebook_infos_copy
|
||||
|
||||
User.sql_update_access = lambda self, notebook_id, read_write = False, owner = False: \
|
||||
lambda database: sql_update_access( self, notebook_id, read_write, owner, database )
|
||||
|
||||
def sql_update_notebook_rank( self, notebook_id, rank, database ):
|
||||
max_rank = -1
|
||||
|
||||
for ( user_id, notebook_infos ) in database.user_notebook.items():
|
||||
for notebook_info in notebook_infos:
|
||||
( db_notebook_id, db_read_write, db_owner, db_rank ) = notebook_info
|
||||
|
||||
if self.object_id == user_id and notebook_id == db_notebook_id:
|
||||
notebook_infos_copy = list( notebook_infos )
|
||||
notebook_infos_copy.remove( notebook_info )
|
||||
notebook_infos_copy.append( ( db_notebook_id, db_read_write, db_owner, rank ) )
|
||||
database.user_notebook[ user_id ] = notebook_infos_copy
|
||||
|
||||
User.sql_update_notebook_rank = lambda self, notebook_id, rank: \
|
||||
lambda database: sql_update_notebook_rank( self, notebook_id, rank, database )
|
||||
|
||||
def sql_highest_notebook_rank( self, database ):
|
||||
max_rank = -1
|
||||
|
||||
for ( user_id, notebook_infos ) in database.user_notebook.items():
|
||||
for notebook_info in notebook_infos:
|
||||
( db_notebook_id, db_read_write, db_owner, db_rank ) = notebook_info
|
||||
if self.object_id == user_id and db_rank > max_rank:
|
||||
max_rank = db_rank
|
||||
|
||||
return max_rank
|
||||
|
||||
User.sql_highest_notebook_rank = lambda self: \
|
||||
lambda database: sql_highest_notebook_rank( self, database )
|
||||
|
||||
def sql_revoke_invite_access( notebook_id, trash_id, email_address, database ):
|
||||
invites = []
|
||||
|
||||
for ( user_id, notebook_infos ) in database.user_notebook.items():
|
||||
for notebook_info in list( notebook_infos ):
|
||||
( db_notebook_id, read_write, owner ) = notebook_info
|
||||
( db_notebook_id, read_write, owner, rank ) = notebook_info
|
||||
if db_notebook_id not in ( notebook_id, trash_id ): continue
|
||||
for ( object_id, obj_list ) in database.objects.items():
|
||||
obj = obj_list[ -1 ]
|
||||
|
@ -255,7 +286,7 @@ class Test_controller( object ):
|
|||
Notebook.sql_search_notes = lambda self, search_text: \
|
||||
lambda database: sql_search_notes( self, search_text, database )
|
||||
|
||||
def sql_highest_rank( self, database ):
|
||||
def sql_highest_note_rank( self, database ):
|
||||
max_rank = -1
|
||||
|
||||
for ( object_id, obj_list ) in database.objects.items():
|
||||
|
@ -265,8 +296,8 @@ class Test_controller( object ):
|
|||
|
||||
return max_rank
|
||||
|
||||
Notebook.sql_highest_rank = lambda self: \
|
||||
lambda database: sql_highest_rank( self, database )
|
||||
Notebook.sql_highest_note_rank = lambda self: \
|
||||
lambda database: sql_highest_note_rank( self, database )
|
||||
|
||||
def sql_count_notes( self, database ):
|
||||
count = 0
|
||||
|
|
|
@ -54,12 +54,12 @@ class Test_notebooks( Test_controller ):
|
|||
self.anon_notebook = Notebook.create( self.database.next_id( Notebook ), u"anon_notebook", user_id = user_id )
|
||||
self.database.save( self.anon_notebook, commit = False )
|
||||
|
||||
self.database.execute( self.user.sql_save_notebook( self.notebook.object_id, read_write = True, owner = True ) )
|
||||
self.database.execute( self.user.sql_save_notebook( self.notebook.trash_id, read_write = True, owner = True ) )
|
||||
self.database.execute( self.user.sql_save_notebook( self.notebook.object_id, read_write = True, owner = True, rank = 0 ) )
|
||||
self.database.execute( self.user.sql_save_notebook( self.notebook.trash_id, read_write = True, owner = True, rank = 0 ) )
|
||||
self.database.execute( self.user.sql_save_notebook( self.anon_notebook.object_id, read_write = False, owner = False ) )
|
||||
|
||||
self.database.execute( self.user2.sql_save_notebook( self.notebook.object_id, read_write = True, owner = False ) )
|
||||
self.database.execute( self.user2.sql_save_notebook( self.notebook.trash_id, read_write = True, owner = False ) )
|
||||
self.database.execute( self.user2.sql_save_notebook( self.notebook.object_id, read_write = True, owner = False, rank = 0 ) )
|
||||
self.database.execute( self.user2.sql_save_notebook( self.notebook.trash_id, read_write = True, owner = False, rank = 0 ) )
|
||||
|
||||
def make_users( self ):
|
||||
self.user = User.create( self.database.next_id( User ), self.username, self.password, self.email_address )
|
||||
|
@ -2299,6 +2299,11 @@ class Test_notebooks( Test_controller ):
|
|||
assert notebook.owner == True
|
||||
assert notebook.trash_id
|
||||
|
||||
self.user.sql_load_notebooks()
|
||||
notebooks = self.database.select_many( Notebook, self.user.sql_load_notebooks() )
|
||||
new_notebook = [ notebook for notebook in notebooks if notebook.object_id == new_notebook_id ][ 0 ]
|
||||
assert new_notebook.rank == 1
|
||||
|
||||
def test_contents_after_create( self ):
|
||||
self.login()
|
||||
|
||||
|
@ -2423,8 +2428,8 @@ class Test_notebooks( Test_controller ):
|
|||
self.database.save( trash, commit = False )
|
||||
notebook = Notebook.create( self.database.next_id( Notebook ), u"notebook", trash.object_id )
|
||||
self.database.save( notebook, commit = False )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook.object_id, read_write = True, owner = True ) )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook.trash_id, read_write = True, owner = True ) )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook.object_id, read_write = True, owner = True, rank = 1 ) )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook.trash_id, read_write = True, owner = True, rank = 1 ) )
|
||||
self.database.commit()
|
||||
|
||||
self.login()
|
||||
|
@ -2447,8 +2452,8 @@ class Test_notebooks( Test_controller ):
|
|||
self.database.save( trash, commit = False )
|
||||
notebook = Notebook.create( self.database.next_id( Notebook ), u"notebook", trash.object_id )
|
||||
self.database.save( notebook, commit = False )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook.object_id, read_write = False, owner = False ) )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook.trash_id, read_write = False, owner = False ) )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook.object_id, read_write = False, owner = False, rank = 1 ) )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook.trash_id, read_write = False, owner = False, rank = 1 ) )
|
||||
self.database.commit()
|
||||
|
||||
self.login()
|
||||
|
|
|
@ -68,9 +68,9 @@ class Test_users( Test_controller ):
|
|||
|
||||
self.user = User.create( self.database.next_id( User ), self.username, self.password, self.email_address )
|
||||
self.database.save( self.user, commit = False )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook_id1, read_write = True, owner = True ), commit = False )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook_id1, read_write = True, owner = True, rank = 0 ), commit = False )
|
||||
self.database.execute( self.user.sql_save_notebook( trash_id1, read_write = True, owner = True ), commit = False )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook_id2, read_write = True, owner = True ), commit = False )
|
||||
self.database.execute( self.user.sql_save_notebook( notebook_id2, read_write = True, owner = True, rank = 1 ), commit = False )
|
||||
self.database.execute( self.user.sql_save_notebook( trash_id2, read_write = True, owner = True ), commit = False )
|
||||
|
||||
self.user2 = User.create( self.database.next_id( User ), self.username2, self.password2, self.email_address2 )
|
||||
|
@ -143,6 +143,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id
|
||||
assert notebook.read_write == True
|
||||
assert notebook.owner == True
|
||||
assert notebook.rank == 0
|
||||
|
||||
notebook = notebooks[ 1 ]
|
||||
assert notebook.object_id == notebooks[ 0 ].trash_id
|
||||
|
@ -151,6 +152,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id == None
|
||||
assert notebook.read_write == True
|
||||
assert notebook.owner == True
|
||||
assert notebook.rank == None
|
||||
|
||||
notebook = notebooks[ 2 ]
|
||||
assert notebook.object_id == self.anon_notebook.object_id
|
||||
|
@ -159,6 +161,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id == None
|
||||
assert notebook.read_write == False
|
||||
assert notebook.owner == False
|
||||
assert notebook.rank == None
|
||||
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
@ -222,6 +225,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id
|
||||
assert notebook.read_write == False
|
||||
assert notebook.owner == False
|
||||
assert notebook.rank == 1
|
||||
|
||||
notebook = notebooks.get( self.notebooks[ 0 ].trash_id )
|
||||
assert notebook.revision
|
||||
|
@ -229,6 +233,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id == None
|
||||
assert notebook.read_write == False
|
||||
assert notebook.owner == False
|
||||
assert notebook.rank == None
|
||||
|
||||
notebook = notebooks.get( self.anon_notebook.object_id )
|
||||
assert notebook.revision == self.anon_notebook.revision
|
||||
|
@ -236,6 +241,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id == None
|
||||
assert notebook.read_write == False
|
||||
assert notebook.owner == False
|
||||
assert notebook.rank == None
|
||||
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
@ -283,6 +289,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id
|
||||
assert notebook.read_write == True
|
||||
assert notebook.owner == True
|
||||
assert notebook.rank == 0
|
||||
|
||||
notebook = notebooks[ 1 ]
|
||||
assert notebook.object_id == notebooks[ 0 ].trash_id
|
||||
|
@ -291,6 +298,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id == None
|
||||
assert notebook.read_write == True
|
||||
assert notebook.owner == True
|
||||
assert notebook.rank == None
|
||||
|
||||
notebook = notebooks[ 2 ]
|
||||
assert notebook.object_id == self.anon_notebook.object_id
|
||||
|
@ -299,6 +307,7 @@ class Test_users( Test_controller ):
|
|||
assert notebook.trash_id == None
|
||||
assert notebook.read_write == False
|
||||
assert notebook.owner == False
|
||||
assert notebook.rank == None
|
||||
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
@ -379,22 +388,27 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"notebooks" ][ 0 ].name == self.notebooks[ 0 ].name
|
||||
assert result[ u"notebooks" ][ 0 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 0 ].owner == True
|
||||
assert result[ u"notebooks" ][ 0 ].rank == 0
|
||||
assert result[ u"notebooks" ][ 1 ].object_id
|
||||
assert result[ u"notebooks" ][ 1 ].name == u"trash"
|
||||
assert result[ u"notebooks" ][ 1 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 1 ].owner == True
|
||||
assert result[ u"notebooks" ][ 1 ].rank == None
|
||||
assert result[ u"notebooks" ][ 2 ].object_id == self.notebooks[ 1 ].object_id
|
||||
assert result[ u"notebooks" ][ 2 ].name == self.notebooks[ 1 ].name
|
||||
assert result[ u"notebooks" ][ 2 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 2 ].owner == True
|
||||
assert result[ u"notebooks" ][ 2 ].rank == 1
|
||||
assert result[ u"notebooks" ][ 3 ].object_id
|
||||
assert result[ u"notebooks" ][ 3 ].name == u"trash"
|
||||
assert result[ u"notebooks" ][ 3 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 3 ].owner == True
|
||||
assert result[ u"notebooks" ][ 3 ].rank == None
|
||||
assert result[ u"notebooks" ][ 4 ].object_id == self.anon_notebook.object_id
|
||||
assert result[ u"notebooks" ][ 4 ].name == self.anon_notebook.name
|
||||
assert result[ u"notebooks" ][ 4 ].read_write == False
|
||||
assert result[ u"notebooks" ][ 4 ].owner == False
|
||||
assert result[ u"notebooks" ][ 4 ].rank == None
|
||||
assert result[ u"login_url" ] is None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
||||
|
@ -412,6 +426,7 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"notebooks" ][ 0 ].name == self.anon_notebook.name
|
||||
assert result[ u"notebooks" ][ 0 ].read_write == False
|
||||
assert result[ u"notebooks" ][ 0 ].owner == False
|
||||
assert result[ u"notebooks" ][ 0 ].rank == None
|
||||
|
||||
login_note = self.database.select_one( Note, self.anon_notebook.sql_load_note_by_title( u"login" ) )
|
||||
assert result[ u"login_url" ] == u"%s/notebooks/%s?note_id=%s" % (
|
||||
|
@ -426,7 +441,7 @@ class Test_users( Test_controller ):
|
|||
assert rate_plan[ u"name" ] == u"super"
|
||||
assert rate_plan[ u"storage_quota_bytes" ] == 1337 * 10
|
||||
|
||||
def test_current_after_login_with_invite_id( self ):
|
||||
def test_login_with_invite_id( self ):
|
||||
# trick send_invites() into using a fake SMTP server
|
||||
Stub_smtp.reset()
|
||||
smtplib.SMTP = Stub_smtp
|
||||
|
@ -461,7 +476,7 @@ class Test_users( Test_controller ):
|
|||
assert cherrypy.root.users.check_access( self.user2.object_id, self.notebooks[ 0 ].object_id )
|
||||
assert cherrypy.root.users.check_access( self.user2.object_id, self.notebooks[ 0 ].trash_id )
|
||||
|
||||
def test_current_after_login_with_after_login( self ):
|
||||
def test_login_with_after_login( self ):
|
||||
after_login = u"/foo/bar"
|
||||
|
||||
result = self.http_post( "/users/login", dict(
|
||||
|
@ -473,7 +488,7 @@ class Test_users( Test_controller ):
|
|||
|
||||
assert result[ u"redirect" ] == after_login
|
||||
|
||||
def test_current_after_login_with_after_login_with_full_url( self ):
|
||||
def test_login_with_after_login_with_full_url( self ):
|
||||
after_login = u"http://this_url/does/not/start/with/a/slash"
|
||||
|
||||
result = self.http_post( "/users/login", dict(
|
||||
|
@ -601,6 +616,7 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"notebooks" ][ 0 ].name == self.anon_notebook.name
|
||||
assert result[ u"notebooks" ][ 0 ].read_write == False
|
||||
assert result[ u"notebooks" ][ 0 ].owner == False
|
||||
assert result[ u"notebooks" ][ 0 ].rank == None
|
||||
|
||||
login_note = self.database.select_one( Note, self.anon_notebook.sql_load_note_by_title( u"login" ) )
|
||||
assert result[ u"login_url" ] == u"%s/notebooks/%s?note_id=%s" % (
|
||||
|
@ -2104,6 +2120,9 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"error" ]
|
||||
|
||||
def test_convert_invite_to_access( self ):
|
||||
# start the invitee out with access to one notebook
|
||||
self.database.execute( self.user2.sql_save_notebook( self.notebooks[ 1 ].object_id, read_write = True, owner = False, rank = 7 ), commit = False )
|
||||
|
||||
# trick send_invites() into using a fake SMTP server
|
||||
Stub_smtp.reset()
|
||||
smtplib.SMTP = Stub_smtp
|
||||
|
@ -2144,6 +2163,12 @@ class Test_users( Test_controller ):
|
|||
) )
|
||||
assert access is True
|
||||
|
||||
self.user.sql_load_notebooks()
|
||||
notebooks = self.database.select_many( Notebook, self.user2.sql_load_notebooks() )
|
||||
new_notebook = [ notebook for notebook in notebooks if notebook.object_id == invite.notebook_id ][ 0 ]
|
||||
print new_notebook.rank
|
||||
assert new_notebook.rank == 8 # one higher than the other notebook this user has access to
|
||||
|
||||
assert invite.redeemed_user_id == self.user2.object_id
|
||||
|
||||
def test_convert_invite_to_access_same_user( self ):
|
||||
|
@ -3245,6 +3270,7 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"notebooks" ][ 0 ].name == self.notebooks[ 0 ].name
|
||||
assert result[ u"notebooks" ][ 0 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 0 ].owner == True
|
||||
assert result[ u"notebooks" ][ 0 ].rank == 0
|
||||
|
||||
assert result[ u"login_url" ] == None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
@ -3284,6 +3310,7 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"notebooks" ][ 0 ].name == self.notebooks[ 0 ].name
|
||||
assert result[ u"notebooks" ][ 0 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 0 ].owner == True
|
||||
assert result[ u"notebooks" ][ 0 ].rank == 0
|
||||
|
||||
assert result[ u"login_url" ] == None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
@ -3322,6 +3349,7 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"notebooks" ][ 0 ].name == self.notebooks[ 0 ].name
|
||||
assert result[ u"notebooks" ][ 0 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 0 ].owner == True
|
||||
assert result[ u"notebooks" ][ 0 ].rank == 0
|
||||
|
||||
assert result[ u"login_url" ] == None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
@ -3360,6 +3388,7 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"notebooks" ][ 0 ].name == self.notebooks[ 0 ].name
|
||||
assert result[ u"notebooks" ][ 0 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 0 ].owner == True
|
||||
assert result[ u"notebooks" ][ 0 ].rank == 0
|
||||
|
||||
assert result[ u"login_url" ] == None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
@ -3396,6 +3425,7 @@ class Test_users( Test_controller ):
|
|||
assert result[ u"notebooks" ][ 0 ].name == self.notebooks[ 0 ].name
|
||||
assert result[ u"notebooks" ][ 0 ].read_write == True
|
||||
assert result[ u"notebooks" ][ 0 ].owner == True
|
||||
assert result[ u"notebooks" ][ 0 ].rank == 0
|
||||
|
||||
assert result[ u"login_url" ] == None
|
||||
assert result[ u"logout_url" ] == self.settings[ u"global" ][ u"luminotes.https_url" ] + u"/users/logout"
|
||||
|
|
|
@ -12,7 +12,8 @@ class Notebook( Persistent ):
|
|||
WHITESPACE_PATTERN = re.compile( r"\s+" )
|
||||
SEARCH_OPERATORS = re.compile( r"[&|!()'\\:]" )
|
||||
|
||||
def __init__( self, object_id, revision = None, name = None, trash_id = None, deleted = False, user_id = None, read_write = True, owner = True ):
|
||||
def __init__( self, object_id, revision = None, name = None, trash_id = None, deleted = False,
|
||||
user_id = None, read_write = True, owner = True, rank = None ):
|
||||
"""
|
||||
Create a new notebook with the given id and name.
|
||||
|
||||
|
@ -32,6 +33,8 @@ class Notebook( Persistent ):
|
|||
@param read_write: whether this view of the notebook is currently read-write (optional, defaults to True)
|
||||
@type owner: bool or NoneType
|
||||
@param owner: whether this view of the notebook currently has owner-level access (optional, defaults to True)
|
||||
@type rank: float or NoneType
|
||||
@param rank: indicates numeric ordering of this note in relation to other notebooks
|
||||
@rtype: Notebook
|
||||
@return: newly constructed notebook
|
||||
"""
|
||||
|
@ -42,9 +45,10 @@ class Notebook( Persistent ):
|
|||
self.__user_id = user_id
|
||||
self.__read_write = read_write
|
||||
self.__owner = owner
|
||||
self.__rank = rank
|
||||
|
||||
@staticmethod
|
||||
def create( object_id, name = None, trash_id = None, deleted = False, user_id = None, read_write = True, owner = True ):
|
||||
def create( object_id, name = None, trash_id = None, deleted = False, user_id = None, read_write = True, owner = True, rank = None ):
|
||||
"""
|
||||
Convenience constructor for creating a new notebook.
|
||||
|
||||
|
@ -62,10 +66,12 @@ class Notebook( Persistent ):
|
|||
@param read_write: whether this view of the notebook is currently read-write (optional, defaults to True)
|
||||
@type owner: bool or NoneType
|
||||
@param owner: whether this view of the notebook currently has owner-level access (optional, defaults to True)
|
||||
@type rank: float or NoneType
|
||||
@param rank: indicates numeric ordering of this note in relation to other notebooks
|
||||
@rtype: Notebook
|
||||
@return: newly constructed notebook
|
||||
"""
|
||||
return Notebook( object_id, name = name, trash_id = trash_id, user_id = user_id, read_write = read_write, owner = owner )
|
||||
return Notebook( object_id, name = name, trash_id = trash_id, user_id = user_id, read_write = read_write, owner = owner, rank = rank )
|
||||
|
||||
@staticmethod
|
||||
def sql_load( object_id, revision = None ):
|
||||
|
@ -182,7 +188,7 @@ class Notebook( Persistent ):
|
|||
) as sub;
|
||||
""" % ( quote( search_text ), quote( self.object_id ) )
|
||||
|
||||
def sql_highest_rank( self ):
|
||||
def sql_highest_note_rank( self ):
|
||||
"""
|
||||
Return a SQL string to determine the highest numbered rank of all notes in this notebook."
|
||||
"""
|
||||
|
@ -232,9 +238,15 @@ class Notebook( Persistent ):
|
|||
self.__user_id = user_id
|
||||
self.update_revision()
|
||||
|
||||
def __set_rank( self, rank ):
|
||||
# The rank member isn't actually saved to the database, so setting it doesn't need to
|
||||
# call update_revision().
|
||||
self.__rank = rank
|
||||
|
||||
name = property( lambda self: self.__name, __set_name )
|
||||
trash_id = property( lambda self: self.__trash_id )
|
||||
read_write = property( lambda self: self.__read_write, __set_read_write )
|
||||
owner = property( lambda self: self.__owner, __set_owner )
|
||||
deleted = property( lambda self: self.__deleted, __set_deleted )
|
||||
user_id = property( lambda self: self.__user_id, __set_user_id )
|
||||
rank = property( lambda self: self.__rank, __set_rank )
|
||||
|
|
|
@ -149,18 +149,27 @@ class User( Persistent ):
|
|||
read_write_clause = ""
|
||||
|
||||
return \
|
||||
"select notebook_current.*, user_notebook.read_write, user_notebook.owner from user_notebook, notebook_current " + \
|
||||
"where user_notebook.user_id = %s%s%s%s and user_notebook.notebook_id = notebook_current.id order by revision;" % \
|
||||
( quote( self.object_id ), parents_only_clause, undeleted_only_clause, read_write_clause )
|
||||
"""
|
||||
select
|
||||
notebook_current.*, user_notebook.read_write, user_notebook.owner, user_notebook.rank
|
||||
from
|
||||
user_notebook, notebook_current
|
||||
where
|
||||
user_notebook.user_id = %s%s%s%s and
|
||||
user_notebook.notebook_id = notebook_current.id
|
||||
order by user_notebook.rank;
|
||||
""" % ( quote( self.object_id ), parents_only_clause, undeleted_only_clause, read_write_clause )
|
||||
|
||||
def sql_save_notebook( self, notebook_id, read_write = True, owner = True ):
|
||||
def sql_save_notebook( self, notebook_id, read_write = True, owner = True, rank = None ):
|
||||
"""
|
||||
Return a SQL string to save the id of a notebook to which this user has access.
|
||||
"""
|
||||
if rank is None: rank = quote( None )
|
||||
|
||||
return \
|
||||
"insert into user_notebook ( user_id, notebook_id, read_write, owner ) values " + \
|
||||
"insert into user_notebook ( user_id, notebook_id, read_write, owner, rank ) values " + \
|
||||
"( %s, %s, %s, %s );" % ( quote( self.object_id ), quote( notebook_id ), quote( read_write and 't' or 'f' ),
|
||||
quote( owner and 't' or 'f' ) )
|
||||
quote( owner and 't' or 'f' ), rank )
|
||||
|
||||
def sql_remove_notebook( self, notebook_id ):
|
||||
"""
|
||||
|
@ -199,6 +208,20 @@ class User( Persistent ):
|
|||
( quote( read_write and 't' or 'f' ), quote( owner and 't' or 'f' ), quote( self.object_id ),
|
||||
quote( notebook_id ) )
|
||||
|
||||
def sql_update_notebook_rank( self, notebook_id, rank ):
|
||||
"""
|
||||
Return a SQL string to update the user's rank for the given notebook.
|
||||
"""
|
||||
return \
|
||||
"update user_notebook set rank = %s where user_id = %s and notebook_id = %s;" % \
|
||||
( quote( rank ), quote( self.object_id ), quote( notebook_id ) )
|
||||
|
||||
def sql_highest_notebook_rank( self ):
|
||||
"""
|
||||
Return a SQL string to determine the highest numbered rank of all notebooks the user has access to."
|
||||
"""
|
||||
return "select coalesce( max( rank ), -1 ) from user_notebook where user_id = %s;" % quote( self.object_id )
|
||||
|
||||
@staticmethod
|
||||
def sql_revoke_invite_access( notebook_id, trash_id, email_address ):
|
||||
return \
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
alter table user_notebook add column rank numeric;
|
|
@ -165,7 +165,8 @@ CREATE TABLE user_notebook (
|
|||
user_id text NOT NULL,
|
||||
notebook_id text NOT NULL,
|
||||
read_write boolean DEFAULT false,
|
||||
"owner" boolean DEFAULT false
|
||||
"owner" boolean DEFAULT false,
|
||||
rank numeric
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -12,9 +12,12 @@ class Test_notebook( object ):
|
|||
self.trash_name = u"trash"
|
||||
self.user_id = u"me"
|
||||
self.delta = timedelta( seconds = 1 )
|
||||
self.read_write = True
|
||||
self.owner = False
|
||||
self.rank = 17.5
|
||||
|
||||
self.trash = Notebook.create( self.trash_id, self.trash_name, read_write = False, deleted = False, user_id = self.user_id )
|
||||
self.notebook = Notebook.create( self.object_id, self.name, trash_id = self.trash.object_id, deleted = False, user_id = self.user_id )
|
||||
self.notebook = Notebook.create( self.object_id, self.name, trash_id = self.trash.object_id, deleted = False, user_id = self.user_id, read_write = self.read_write, owner = self.owner, rank = self.rank )
|
||||
self.note = Note.create( "19", u"<h3>title</h3>blah" )
|
||||
|
||||
def test_create( self ):
|
||||
|
@ -25,6 +28,9 @@ class Test_notebook( object ):
|
|||
assert self.notebook.trash_id == self.trash_id
|
||||
assert self.notebook.deleted == False
|
||||
assert self.notebook.user_id == self.user_id
|
||||
assert self.notebook.read_write == self.read_write
|
||||
assert self.notebook.owner == self.owner
|
||||
assert self.notebook.rank == self.rank
|
||||
|
||||
assert self.trash.object_id == self.trash_id
|
||||
assert datetime.now( tz = utc ) - self.trash.revision < self.delta
|
||||
|
@ -33,6 +39,9 @@ class Test_notebook( object ):
|
|||
assert self.trash.trash_id == None
|
||||
assert self.trash.deleted == False
|
||||
assert self.trash.user_id == self.user_id
|
||||
assert self.trash.read_write == False
|
||||
assert self.trash.owner == True
|
||||
assert self.trash.rank == None
|
||||
|
||||
def test_set_name( self ):
|
||||
new_name = u"my new notebook"
|
||||
|
@ -63,6 +72,13 @@ class Test_notebook( object ):
|
|||
assert self.notebook.user_id == u"5"
|
||||
assert self.notebook.revision > previous_revision
|
||||
|
||||
def test_set_rank( self ):
|
||||
original_revision = self.notebook.revision
|
||||
self.notebook.rank = 17.7
|
||||
|
||||
assert self.notebook.rank == 17.7
|
||||
assert self.notebook.revision == original_revision
|
||||
|
||||
def test_to_dict( self ):
|
||||
d = self.notebook.to_dict()
|
||||
|
||||
|
|
|
@ -221,6 +221,18 @@ img {
|
|||
background-image: url(/static/images/numbered_list_button_down.png);
|
||||
}
|
||||
|
||||
#current_notebook_up_hover_preload {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
background-image: url(/static/images/arrow_up_hover.png);
|
||||
}
|
||||
|
||||
#current_notebook_down_hover_preload {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
background-image: url(/static/images/arrow_down_hover.png);
|
||||
}
|
||||
|
||||
#link_area {
|
||||
float: right;
|
||||
text-align: left;
|
||||
|
@ -564,6 +576,16 @@ img {
|
|||
background: url(/static/images/current_notebook_inner_tl.png) no-repeat top left;
|
||||
}
|
||||
|
||||
#current_notebook_up {
|
||||
cursor: pointer;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
#current_notebook_down {
|
||||
cursor: pointer;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.trash_notebook_color {
|
||||
background-color: #d0d0d0;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
IMAGE_DIR = "/static/images/";
|
||||
|
||||
function Wiki( invoker ) {
|
||||
this.next_id = null;
|
||||
this.focused_editor = null;
|
||||
|
@ -105,9 +107,28 @@ function Wiki( invoker ) {
|
|||
"href": "/notebooks/" + this.notebook.trash_id + "?parent_id=" + this.notebook.object_id
|
||||
}, "trash" );
|
||||
var message_div = this.display_message( "The notebook has been moved to the", [ trash_link, ". ", undo_button ], "notes_top" );
|
||||
var self = this;
|
||||
connect( undo_button, "onclick", function ( event ) { self.undelete_notebook( event, deleted_id ); } );
|
||||
}
|
||||
|
||||
var current_notebook_up = getElement( "current_notebook_up" );
|
||||
if ( current_notebook_up ) {
|
||||
connect( current_notebook_up, "onmouseover", function ( event ) { current_notebook_up.src = IMAGE_DIR + "up_arrow_hover.png"; } );
|
||||
connect( current_notebook_up, "onmouseout", function ( event ) { current_notebook_up.src = IMAGE_DIR + "up_arrow.png"; } );
|
||||
connect( current_notebook_up, "onclick", function ( event ) {
|
||||
current_notebook_up.src = IMAGE_DIR + "up_arrow.png";
|
||||
self.move_current_notebook_up( event );
|
||||
} );
|
||||
}
|
||||
|
||||
var current_notebook_down = getElement( "current_notebook_down" );
|
||||
if ( current_notebook_down ) {
|
||||
connect( current_notebook_down, "onmouseover", function ( event ) { current_notebook_down.src = IMAGE_DIR + "down_arrow_hover.png"; } );
|
||||
connect( current_notebook_down, "onmouseout", function ( event ) { current_notebook_down.src = IMAGE_DIR + "down_arrow.png"; } );
|
||||
connect( current_notebook_down, "onclick", function ( event ) {
|
||||
current_notebook_down.src = IMAGE_DIR + "down_arrow.png";
|
||||
self.move_current_notebook_down( event );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
Wiki.prototype.update_next_id = function ( result ) {
|
||||
|
@ -851,8 +872,6 @@ Wiki.prototype.editor_key_pressed = function ( editor, event ) {
|
|||
}
|
||||
}
|
||||
|
||||
IMAGE_DIR = "/static/images/";
|
||||
|
||||
Wiki.prototype.make_image_button = function ( name, filename_prefix, handle_mouse_up_and_down ) {
|
||||
var button = getElement( name );
|
||||
|
||||
|
@ -1530,6 +1549,56 @@ Wiki.prototype.display_invites = function ( invite_area ) {
|
|||
replaceChildNodes( invite_area, div );
|
||||
}
|
||||
|
||||
Wiki.prototype.move_current_notebook_up = function ( event ) {
|
||||
var current_notebook = getElement( "current_notebook_wrapper" );
|
||||
var sibling_notebook = current_notebook;
|
||||
|
||||
// find the previous sibling notebook node
|
||||
do {
|
||||
var sibling_notebook = sibling_notebook.previousSibling;
|
||||
} while ( sibling_notebook && sibling_notebook.className != "link_area_item" );
|
||||
|
||||
removeElement( current_notebook );
|
||||
if ( sibling_notebook )
|
||||
// move the current notebook up before the previous notebook node
|
||||
insertSiblingNodesBefore( sibling_notebook, current_notebook );
|
||||
// if the current notebook is the first one, wrap it around to the bottom of the list
|
||||
else {
|
||||
var notebooks_area = getElement( "notebooks_area" );
|
||||
appendChildNodes( notebooks_area, current_notebook );
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.invoker.invoke( "/notebooks/move_up", "POST", {
|
||||
"notebook_id": this.notebook_id
|
||||
} );
|
||||
}
|
||||
|
||||
Wiki.prototype.move_current_notebook_down = function ( event ) {
|
||||
var current_notebook = getElement( "current_notebook_wrapper" );
|
||||
var sibling_notebook = current_notebook;
|
||||
|
||||
// find the next sibling notebook node
|
||||
do {
|
||||
var sibling_notebook = sibling_notebook.nextSibling;
|
||||
} while ( sibling_notebook && sibling_notebook.className != "link_area_item" );
|
||||
|
||||
removeElement( current_notebook );
|
||||
if ( sibling_notebook )
|
||||
// move the current notebook down after the previous notebook node
|
||||
insertSiblingNodesAfter( sibling_notebook, current_notebook );
|
||||
// if the current notebook is the last one, wrap it around to the top of the list
|
||||
else {
|
||||
var notebooks_area_title = getElement( "notebooks_area_title" );
|
||||
insertSiblingNodesAfter( notebooks_area_title, current_notebook );
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.invoker.invoke( "/notebooks/move_down", "POST", {
|
||||
"notebook_id": this.notebook_id
|
||||
} );
|
||||
}
|
||||
|
||||
Wiki.prototype.display_message = function ( text, nodes, position_after ) {
|
||||
this.clear_messages();
|
||||
this.clear_pulldowns();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from Tags import Div, Span, H4, A, Strong
|
||||
from Tags import Div, Span, H4, A, Strong, Img
|
||||
from Rounded_div import Rounded_div
|
||||
|
||||
|
||||
|
@ -115,7 +115,7 @@ class Link_area( Div ):
|
|||
),
|
||||
|
||||
Div(
|
||||
( len( linked_notebooks ) > 0 ) and H4( u"notebooks" ) or None,
|
||||
( len( linked_notebooks ) > 0 ) and H4( u"notebooks", id = u"notebooks_area_title" ) or None,
|
||||
[ ( nb.object_id == notebook.object_id ) and Rounded_div(
|
||||
u"current_notebook",
|
||||
A(
|
||||
|
@ -123,6 +123,12 @@ class Link_area( Div ):
|
|||
href = u"/notebooks/%s" % nb.object_id,
|
||||
id = u"notebook_%s" % nb.object_id,
|
||||
),
|
||||
( len( linked_notebooks ) > 1 ) and Span(
|
||||
Img( src = u"/static/images/up_arrow.png", width = u"20", height = u"17", id = u"current_notebook_up" ),
|
||||
Img( src = u"/static/images/down_arrow.png", width = u"20", height = u"17", id = u"current_notebook_down" ),
|
||||
Span( id = "current_notebook_up_hover_preload" ),
|
||||
Span( id = "current_notebook_down_hover_preload" ),
|
||||
) or None,
|
||||
class_ = u"link_area_item",
|
||||
) or
|
||||
Div(
|
||||
|
|
|
@ -22,5 +22,6 @@ class Rounded_div( Div ):
|
|||
Div.__init__(
|
||||
self,
|
||||
div,
|
||||
id = u"%s_wrapper" % image_name,
|
||||
class_ = u"%s_color" % image_name,
|
||||
)
|
||||
|
|
Reference in New Issue