Feature to preview notebook as viewer or collaborator, so you can see what it
will look like to people you share it with. Hopefully fixed broken demo conversion detection.
This commit is contained in:
parent
0d9ceeef10
commit
2bcbc17172
2
NEWS
2
NEWS
|
@ -1,5 +1,7 @@
|
|||
1.1.0: January ??, 2007
|
||||
* Ability to invite people to your notebook as a collaborator or owner.
|
||||
* Feature to preview a notebook as a viewer would see it.
|
||||
* Note revisions list now include username of the user who made that revision.
|
||||
* Fixed bug where passwords with special characters broke password hashing.
|
||||
* Fixed bug where link info box summaries sometimes contained HTML tags.
|
||||
|
||||
|
|
|
@ -61,10 +61,11 @@ class Notebooks( object ):
|
|||
revision = Valid_revision(),
|
||||
rename = Valid_bool(),
|
||||
deleted_id = Valid_id(),
|
||||
preview = Valid_string(),
|
||||
user_id = Valid_id( none_okay = True ),
|
||||
)
|
||||
def default( self, notebook_id, note_id = None, parent_id = None, revision = None, rename = False,
|
||||
deleted_id = None, user_id = None ):
|
||||
deleted_id = None, preview = None, user_id = None ):
|
||||
"""
|
||||
Provide the information necessary to display the page for a particular notebook. If a
|
||||
particular note id is given without a revision, then the most recent version of that note is
|
||||
|
@ -82,13 +83,39 @@ class Notebooks( object ):
|
|||
@param rename: whether this is a new notebook and should be renamed (optional, defaults to False)
|
||||
@type deleted_id: unicode or NoneType
|
||||
@param deleted_id: id of the notebook that was just deleted, if any (optional)
|
||||
@type preview: unicode
|
||||
@param preview: type of access with which to preview this notebook, either "collaborator",
|
||||
"viewer", "owner", or "default" (optional, defaults to "default"). access must
|
||||
be equal to or lower than user's own access level to this notebook
|
||||
@type user_id: unicode or NoneType
|
||||
@param user_id: id of current logged-in user (if any)
|
||||
@rtype: unicode
|
||||
@return: rendered HTML page
|
||||
"""
|
||||
result = self.__users.current( user_id )
|
||||
result.update( self.contents( notebook_id, note_id, revision, user_id ) )
|
||||
|
||||
if preview == u"collaborator":
|
||||
read_write = True
|
||||
owner = False
|
||||
result[ u"notebooks" ] = [
|
||||
notebook for notebook in result[ "notebooks" ] if notebook.object_id == notebook_id
|
||||
]
|
||||
result[ u"notebooks" ][ 0 ].owner = False
|
||||
elif preview == u"viewer":
|
||||
read_write = False
|
||||
owner = False
|
||||
result[ u"notebooks" ] = [
|
||||
notebook for notebook in result[ "notebooks" ] if notebook.object_id == notebook_id
|
||||
]
|
||||
result[ u"notebooks" ][ 0 ].read_write = False
|
||||
result[ u"notebooks" ][ 0 ].owner = False
|
||||
elif preview in ( u"owner", u"default", None ):
|
||||
read_write = True
|
||||
owner = True
|
||||
else:
|
||||
raise Access_error()
|
||||
|
||||
result.update( self.contents( notebook_id, note_id, revision, read_write, owner, user_id ) )
|
||||
result[ "parent_id" ] = parent_id
|
||||
if revision:
|
||||
result[ "note_read_write" ] = False
|
||||
|
@ -96,7 +123,7 @@ class Notebooks( object ):
|
|||
# if the user doesn't have any storage bytes yet, they're a new user, so see what type of
|
||||
# conversion this is (demo or signup)
|
||||
if result[ "user" ].storage_bytes == 0:
|
||||
if u"demo" in [ note.title for note in result[ "startup_notes" ] ]:
|
||||
if u"this is a demo" in [ note.title for note in result[ "startup_notes" ] ]:
|
||||
result[ "conversion" ] = u"demo"
|
||||
else:
|
||||
result[ "conversion" ] = u"signup"
|
||||
|
@ -105,7 +132,7 @@ class Notebooks( object ):
|
|||
|
||||
return result
|
||||
|
||||
def contents( self, notebook_id, note_id = None, revision = None, user_id = None ):
|
||||
def contents( self, notebook_id, note_id = None, revision = None, read_write = True, owner = True, user_id = None ):
|
||||
"""
|
||||
Return the startup notes for the given notebook. Optionally include a single requested note as
|
||||
well.
|
||||
|
@ -116,6 +143,10 @@ class Notebooks( object ):
|
|||
@param note_id: id of single note in this notebook to return (optional)
|
||||
@type revision: unicode or NoneType
|
||||
@param revision: revision timestamp of the provided note (optional)
|
||||
@type read_write: bool or NoneType
|
||||
@param read_write: whether the notebook should be returned as read-write (optional, defaults to True)
|
||||
@type owner: bool or NoneType
|
||||
@param owner: whether the notebook should be returned as owner-level access (optional, defaults to True)
|
||||
@type user_id: unicode or NoneType
|
||||
@param user_id: id of current logged-in user (if any)
|
||||
@rtype: dict
|
||||
|
@ -136,10 +167,14 @@ class Notebooks( object ):
|
|||
if notebook is None:
|
||||
raise Access_error()
|
||||
|
||||
if not self.__users.check_access( user_id, notebook_id, read_write = True ):
|
||||
if read_write is False:
|
||||
notebook.read_write = False
|
||||
elif not self.__users.check_access( user_id, notebook_id, read_write = True ):
|
||||
notebook.read_write = False
|
||||
|
||||
if not self.__users.check_access( user_id, notebook_id, owner = True ):
|
||||
if owner is False:
|
||||
notebook.owner = False
|
||||
elif not self.__users.check_access( user_id, notebook_id, owner = True ):
|
||||
notebook.owner = False
|
||||
|
||||
if note_id:
|
||||
|
|
|
@ -97,10 +97,15 @@ class Test_notebooks( Test_controller ):
|
|||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 3
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == True
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == True
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == True
|
||||
assert result.get( u"notebook" ).owner == True
|
||||
assert len( result.get( u"startup_notes" ) ) == 1
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
assert result.get( u"notes" ) == []
|
||||
|
@ -115,6 +120,194 @@ class Test_notebooks( Test_controller ):
|
|||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_default_as_preview_viewer( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_get(
|
||||
"/notebooks/%s?preview=viewer" % self.notebook.object_id,
|
||||
session_id = self.session_id,
|
||||
)
|
||||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 1
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == False
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == False
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == False
|
||||
assert result.get( u"notebook" ).owner == False
|
||||
assert len( result.get( u"startup_notes" ) ) == 1
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
assert result.get( u"notes" ) == []
|
||||
assert result.get( u"parent_id" ) == None
|
||||
assert result.get( u"note_read_write" ) in ( None, True )
|
||||
|
||||
invites = result[ "invites" ]
|
||||
assert len( invites ) == 1
|
||||
invite = invites[ 0 ]
|
||||
assert invite.object_id == self.invite.object_id
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_default_as_preview_collaborator( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_get(
|
||||
"/notebooks/%s?preview=collaborator" % self.notebook.object_id,
|
||||
session_id = self.session_id,
|
||||
)
|
||||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 1
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == True
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == False
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == True
|
||||
assert result.get( u"notebook" ).owner == False
|
||||
assert len( result.get( u"startup_notes" ) ) == 1
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
assert result.get( u"notes" ) == []
|
||||
assert result.get( u"parent_id" ) == None
|
||||
assert result.get( u"note_read_write" ) in ( None, True )
|
||||
|
||||
invites = result[ "invites" ]
|
||||
assert len( invites ) == 1
|
||||
invite = invites[ 0 ]
|
||||
assert invite.object_id == self.invite.object_id
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_default_as_preview_owner( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_get(
|
||||
"/notebooks/%s?preview=owner" % self.notebook.object_id,
|
||||
session_id = self.session_id,
|
||||
)
|
||||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 3
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == True
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == True
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == True
|
||||
assert result.get( u"notebook" ).owner == True
|
||||
assert len( result.get( u"startup_notes" ) ) == 1
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
assert result.get( u"notes" ) == []
|
||||
assert result.get( u"parent_id" ) == None
|
||||
assert result.get( u"note_read_write" ) in ( None, True )
|
||||
|
||||
invites = result[ "invites" ]
|
||||
assert len( invites ) == 1
|
||||
invite = invites[ 0 ]
|
||||
assert invite.object_id == self.invite.object_id
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_default_as_preview_viewer_with_viewer_access( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_get(
|
||||
"/notebooks/%s?preview=viewer" % self.anon_notebook.object_id,
|
||||
session_id = self.session_id,
|
||||
)
|
||||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 1
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == False
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == False
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.anon_notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == False
|
||||
assert result.get( u"notebook" ).owner == False
|
||||
assert len( result.get( u"startup_notes" ) ) == 0
|
||||
assert result[ "total_notes_count" ] == 0
|
||||
assert result.get( u"notes" ) == []
|
||||
assert result.get( u"parent_id" ) == None
|
||||
assert result.get( u"note_read_write" ) in ( None, True )
|
||||
assert len( result[ "invites" ] ) == 0
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_default_as_preview_collaborator_with_viewer_access( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_get(
|
||||
"/notebooks/%s?preview=collaborator" % self.anon_notebook.object_id,
|
||||
session_id = self.session_id,
|
||||
)
|
||||
|
||||
# even though a collaborator preview is being requested, this user only has preview-level
|
||||
# access. so read_write should be False on the returned notebook
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 1
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.anon_notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == False
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == False
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.anon_notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == False
|
||||
assert result.get( u"notebook" ).owner == False
|
||||
assert len( result.get( u"startup_notes" ) ) == 0
|
||||
assert result[ "total_notes_count" ] == 0
|
||||
assert result.get( u"notes" ) == []
|
||||
assert result.get( u"parent_id" ) == None
|
||||
assert result.get( u"note_read_write" ) in ( None, True )
|
||||
assert len( result[ "invites" ] ) == 0
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_default_as_preview_owner_with_viewer_access( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_get(
|
||||
"/notebooks/%s?preview=owner" % self.anon_notebook.object_id,
|
||||
session_id = self.session_id,
|
||||
)
|
||||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 3
|
||||
assert result.get( u"notebooks" )[ 2 ].object_id == self.anon_notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 2 ].read_write == False
|
||||
assert result.get( u"notebooks" )[ 2 ].owner == False
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.anon_notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == False
|
||||
assert result.get( u"notebook" ).owner == False
|
||||
assert len( result.get( u"startup_notes" ) ) == 0
|
||||
assert result[ "total_notes_count" ] == 0
|
||||
assert result.get( u"notes" ) == []
|
||||
assert result.get( u"parent_id" ) == None
|
||||
assert result.get( u"note_read_write" ) in ( None, True )
|
||||
assert len( result[ "invites" ] ) == 0
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_default_with_note( self ):
|
||||
self.login()
|
||||
|
||||
|
@ -125,10 +318,15 @@ class Test_notebooks( Test_controller ):
|
|||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 3
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == True
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == True
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == True
|
||||
assert result.get( u"notebook" ).owner == True
|
||||
assert len( result.get( u"startup_notes" ) ) == 1
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
|
||||
|
@ -160,10 +358,15 @@ class Test_notebooks( Test_controller ):
|
|||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 3
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == True
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == True
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == True
|
||||
assert result.get( u"notebook" ).owner == True
|
||||
assert len( result.get( u"startup_notes" ) ) == 1
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
|
||||
|
@ -193,10 +396,15 @@ class Test_notebooks( Test_controller ):
|
|||
|
||||
assert result.get( u"user" ).object_id == self.user.object_id
|
||||
assert len( result.get( u"notebooks" ) ) == 3
|
||||
assert result.get( u"notebooks" )[ 0 ].object_id == self.notebook.object_id
|
||||
assert result.get( u"notebooks" )[ 0 ].read_write == True
|
||||
assert result.get( u"notebooks" )[ 0 ].owner == True
|
||||
assert result.get( u"login_url" ) is None
|
||||
assert result.get( u"logout_url" )
|
||||
assert result.get( u"rate_plan" )
|
||||
assert result.get( u"notebook" ).object_id == self.notebook.object_id
|
||||
assert result.get( u"notebook" ).read_write == True
|
||||
assert result.get( u"notebook" ).owner == True
|
||||
assert len( result.get( u"startup_notes" ) ) == 1
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
assert result.get( u"notes" ) == []
|
||||
|
@ -235,6 +443,56 @@ class Test_notebooks( Test_controller ):
|
|||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_contents_with_read_write_false( self ):
|
||||
result = cherrypy.root.notebooks.contents(
|
||||
notebook_id = self.notebook.object_id,
|
||||
read_write = False,
|
||||
user_id = self.user.object_id,
|
||||
)
|
||||
|
||||
notebook = result[ "notebook" ]
|
||||
startup_notes = result[ "startup_notes" ]
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
assert result[ "notes" ] == []
|
||||
|
||||
invites = result[ "invites" ]
|
||||
assert len( invites ) == 1
|
||||
invite = invites[ 0 ]
|
||||
assert invite.object_id == self.invite.object_id
|
||||
|
||||
assert notebook.object_id == self.notebook.object_id
|
||||
assert notebook.read_write == False
|
||||
assert notebook.owner == True
|
||||
assert len( startup_notes ) == 1
|
||||
assert startup_notes[ 0 ].object_id == self.note.object_id
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_contents_with_owner_false( self ):
|
||||
result = cherrypy.root.notebooks.contents(
|
||||
notebook_id = self.notebook.object_id,
|
||||
owner = False,
|
||||
user_id = self.user.object_id,
|
||||
)
|
||||
|
||||
notebook = result[ "notebook" ]
|
||||
startup_notes = result[ "startup_notes" ]
|
||||
assert result[ "total_notes_count" ] == 2
|
||||
assert result[ "notes" ] == []
|
||||
|
||||
invites = result[ "invites" ]
|
||||
assert len( invites ) == 1
|
||||
invite = invites[ 0 ]
|
||||
assert invite.object_id == self.invite.object_id
|
||||
|
||||
assert notebook.object_id == self.notebook.object_id
|
||||
assert notebook.read_write == True
|
||||
assert notebook.owner == False
|
||||
assert len( startup_notes ) == 1
|
||||
assert startup_notes[ 0 ].object_id == self.note.object_id
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.storage_bytes == 0
|
||||
|
||||
def test_contents_with_note( self ):
|
||||
result = cherrypy.root.notebooks.contents(
|
||||
notebook_id = self.notebook.object_id,
|
||||
|
|
|
@ -1330,7 +1330,19 @@ Wiki.prototype.share_notebook = function () {
|
|||
)
|
||||
),
|
||||
invite_area
|
||||
),
|
||||
createDOM( "div", {},
|
||||
createDOM(
|
||||
"a", { "href": "/notebooks/" + this.notebook_id + "?preview=viewer", "target": "_new" },
|
||||
"Preview this notebook as a viewer."
|
||||
)
|
||||
),
|
||||
this.rate_plan.notebook_collaboration ? createDOM( "div", {},
|
||||
createDOM(
|
||||
"a", { "href": "/notebooks/" + this.notebook_id + "?preview=collaborator", "target": "_new" },
|
||||
"Preview this notebook as a collaborator."
|
||||
)
|
||||
) : null
|
||||
);
|
||||
|
||||
this.create_editor( "share_notebook", "<h3>share this notebook</h3>" + div.innerHTML, undefined, undefined, undefined, false, true, true, getElement( "notes_top" ) );
|
||||
|
|
Reference in New Issue