You can now print an individual note.
This commit is contained in:
parent
c262ad7b00
commit
7def0fe58c
2
NEWS
2
NEWS
|
@ -1,6 +1,8 @@
|
|||
1.6.8: ?
|
||||
* You can now print your entire notebook. Just click the "print" link on the
|
||||
left side of the page.
|
||||
* You can now print an individual note. Just click the "options" tab on a
|
||||
note and then "print this note".
|
||||
* Changed the order of exported HTML and CSV notebooks so that after all the
|
||||
"startup" notes are included, the remaining notes are included in
|
||||
alphabetical order (instead of reverse chronological order).
|
||||
|
|
|
@ -1196,16 +1196,19 @@ class Notebooks( object ):
|
|||
@validate(
|
||||
notebook_id = Valid_id(),
|
||||
format = Valid_string( min = 1, max = 100 ),
|
||||
note_id = Valid_id( none_okay = True ),
|
||||
user_id = Valid_id( none_okay = True ),
|
||||
)
|
||||
def export( self, notebook_id, format, user_id ):
|
||||
def export( self, notebook_id, format, note_id = None, user_id = None ):
|
||||
"""
|
||||
Download the entire contents of the given notebook as a stand-alone file.
|
||||
|
||||
@type notebook_id: unicode
|
||||
@param notebook_id: id of notebook to download
|
||||
@param notebook_id: id of notebook to export
|
||||
@type format: unicode
|
||||
@param format: string indicating the export plugin to use, currently one of: "html", "csv"
|
||||
@type notebook_id: unicode
|
||||
@param note_id: id of single note within the notebook to export (optional)
|
||||
@type user_id: unicode
|
||||
@param user_id: id of current logged-in user (if any), determined by @grab_user_id
|
||||
@rtype: unicode or generator (for streaming files)
|
||||
|
@ -1221,9 +1224,16 @@ class Notebooks( object ):
|
|||
if not notebook:
|
||||
raise Access_error()
|
||||
|
||||
startup_notes = self.__database.select_many( Note, notebook.sql_load_startup_notes() )
|
||||
other_notes = self.__database.select_many( Note, notebook.sql_load_non_startup_notes() )
|
||||
notes = startup_notes + other_notes
|
||||
if note_id:
|
||||
note = self.__database.load( Note, note_id )
|
||||
if not note:
|
||||
raise Access_error()
|
||||
notes = [ note ]
|
||||
notebook = None
|
||||
else:
|
||||
startup_notes = self.__database.select_many( Note, notebook.sql_load_startup_notes() )
|
||||
other_notes = self.__database.select_many( Note, notebook.sql_load_non_startup_notes() )
|
||||
notes = startup_notes + other_notes
|
||||
|
||||
from plugins.Invoke import invoke
|
||||
|
||||
|
@ -1233,7 +1243,7 @@ class Notebooks( object ):
|
|||
plugin_name = format,
|
||||
database = self.__database,
|
||||
notebook = notebook,
|
||||
notes = startup_notes + other_notes,
|
||||
notes = notes,
|
||||
response_headers = cherrypy.response.headerMap,
|
||||
)
|
||||
except ( ImportError, AttributeError ):
|
||||
|
|
|
@ -4801,6 +4801,45 @@ class Test_notebooks( Test_controller ):
|
|||
|
||||
assert u"access" in result[ "body" ][ 0 ]
|
||||
|
||||
def test_export_print_with_note_id( self ):
|
||||
self.login()
|
||||
|
||||
note3 = Note.create( "55", u"<h3>blah</h3>foo", notebook_id = self.notebook.object_id )
|
||||
self.database.save( note3 )
|
||||
|
||||
result = self.http_get(
|
||||
"/notebooks/export?notebook_id=%s&format=print¬e_id=%s" % ( self.notebook.object_id, note3.object_id ),
|
||||
session_id = self.session_id,
|
||||
)
|
||||
|
||||
assert result.get( "notebook" ) == None
|
||||
assert result.get( "view" )
|
||||
|
||||
notes = result.get( "notes" )
|
||||
assert len( notes ) == 1
|
||||
note = notes[ 0 ]
|
||||
|
||||
assert note.object_id == note3.object_id
|
||||
assert note.revision == note3.revision
|
||||
assert note.title == note3.title
|
||||
assert note.contents == note3.contents
|
||||
assert note.notebook_id == note3.notebook_id
|
||||
assert note.startup == note3.startup
|
||||
assert note.deleted_from_id == note3.deleted_from_id
|
||||
assert note.rank == note3.rank
|
||||
assert note.user_id == note3.user_id
|
||||
assert note.creation == note3.creation
|
||||
|
||||
def test_export_print_with_unknown_note_id( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_get(
|
||||
"/notebooks/export?notebook_id=%s&format=print¬e_id=%s" % ( self.notebook.object_id, self.unknown_note_id ),
|
||||
session_id = self.session_id,
|
||||
)
|
||||
|
||||
assert u"access" in result[ "body" ][ 0 ]
|
||||
|
||||
def test_create( self ):
|
||||
self.login()
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class Html_file( Html ):
|
|||
contents = self.IMAGE_PATTERN.sub( '', contents )
|
||||
relinked_notes[ note.object_id ] = contents
|
||||
|
||||
response_headers[ u"Content-Disposition" ] = u"attachment; filename=%s.html" % notebook.friendly_id
|
||||
response_headers[ u"Content-Disposition" ] = u"attachment; filename=%s.html" % notebook and notebook.friendly_id
|
||||
|
||||
Html.__init__(
|
||||
self,
|
||||
|
|
|
@ -19,11 +19,11 @@ class Print_notes( Html ):
|
|||
Style( file( u"static/css/download.css" ).read(), type = u"text/css" ),
|
||||
Style( file( u"static/css/print.css" ).read(), type = u"text/css" ),
|
||||
Meta( content = u"text/html; charset=UTF-8", http_equiv = u"content-type" ),
|
||||
Title( notebook.name ),
|
||||
Title( notebook and notebook.name or notes[ 0 ].title ),
|
||||
),
|
||||
Body(
|
||||
Div(
|
||||
H1( notebook.name ),
|
||||
notebook and H1( notebook.name ) or None,
|
||||
[ Span(
|
||||
A( name = u"note_%s" % note.object_id ),
|
||||
Div(
|
||||
|
|
|
@ -73,3 +73,37 @@ class Test_export_html( object ):
|
|||
assert note.rank == expected_note.rank
|
||||
assert note.user_id == expected_note.user_id
|
||||
assert note.creation == expected_note.creation
|
||||
|
||||
def test_export_print_without_notebook( self ):
|
||||
note3 = Note.create( "55", u"<h3>blah</h3>foo", notebook_id = self.notebook.object_id )
|
||||
self.database.save( note3 )
|
||||
response_headers = {}
|
||||
expected_notes = ( self.note1, self.note2, note3 )
|
||||
|
||||
result = invoke(
|
||||
"export",
|
||||
"print",
|
||||
self.database,
|
||||
None,
|
||||
expected_notes,
|
||||
response_headers,
|
||||
)
|
||||
|
||||
# response headers should be unchanged
|
||||
assert response_headers == {}
|
||||
|
||||
notes = result.get( "notes" )
|
||||
assert len( notes ) == len( expected_notes )
|
||||
|
||||
# assert that the notes are in the expected order
|
||||
for ( note, expected_note ) in zip( notes, expected_notes ):
|
||||
assert note.object_id == expected_note.object_id
|
||||
assert note.revision == expected_note.revision
|
||||
assert note.title == expected_note.title
|
||||
assert note.contents == expected_note.contents
|
||||
assert note.notebook_id == expected_note.notebook_id
|
||||
assert note.startup == expected_note.startup
|
||||
assert note.deleted_from_id == expected_note.deleted_from_id
|
||||
assert note.rank == expected_note.rank
|
||||
assert note.user_id == expected_note.user_id
|
||||
assert note.creation == expected_note.creation
|
||||
|
|
|
@ -3217,9 +3217,19 @@ function Options_pulldown( wiki, notebook_id, invoker, editor ) {
|
|||
this.startup_label = createDOM( "label", { "for": "startup_checkbox", "class": "pulldown_label", "title": "Display this note whenever the notebook is loaded." },
|
||||
"show on startup"
|
||||
);
|
||||
this.print_checkbox = createDOM( "input", { "type": "checkbox", "class": "pulldown_checkbox invisible" } );
|
||||
this.print_link = createDOM( "a",
|
||||
{
|
||||
"href": "/notebooks/export?notebook_id=" + notebook_id + "¬e_id=" + editor.id + "&format=print",
|
||||
"target": "_new",
|
||||
"class": "pulldown_link",
|
||||
"title": "Print this note by itself."
|
||||
},
|
||||
"print this note"
|
||||
);
|
||||
|
||||
appendChildNodes( this.div, this.startup_checkbox );
|
||||
appendChildNodes( this.div, this.startup_label );
|
||||
appendChildNodes( this.div, createDOM( "div", {}, this.startup_checkbox, this.startup_label ) );
|
||||
appendChildNodes( this.div, createDOM( "div", {}, this.print_checkbox, this.print_link ) );
|
||||
this.startup_checkbox.checked = editor.startup;
|
||||
|
||||
var self = this;
|
||||
|
|
Reference in New Issue