From 7bd83199a10bc9e92fb1c88dc19d4b1ee7f147c0 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Sat, 17 Nov 2007 22:55:13 +0000 Subject: [PATCH] Almost done with notebook deletion/undeletion. Just need to implement delete forever. --- controller/Notebooks.py | 2 +- controller/test/Test_controller.py | 8 +-- model/User.py | 11 ++-- static/css/style.css | 14 +++++ static/js/Wiki.js | 84 ++++++++++++++++++++++++++---- view/Main_page.py | 3 ++ 6 files changed, 105 insertions(+), 17 deletions(-) diff --git a/controller/Notebooks.py b/controller/Notebooks.py index 6a3dc63..ace479d 100644 --- a/controller/Notebooks.py +++ b/controller/Notebooks.py @@ -847,7 +847,7 @@ class Notebooks( object ): self.__database.save( notebook, commit = False ) # redirect to a remaining undeleted notebook, or if there isn't one, create an empty notebook - remaining_notebook = self.__database.select_one( Notebook, user.sql_load_notebooks( parents_only = True ) ) + remaining_notebook = self.__database.select_one( Notebook, user.sql_load_notebooks( parents_only = True, undeleted_only = True ) ) if remaining_notebook is None: remaining_notebook = self.__create_notebook( u"my notebook", user, commit = False ) diff --git a/controller/test/Test_controller.py b/controller/test/Test_controller.py index de95a87..fa31514 100644 --- a/controller/test/Test_controller.py +++ b/controller/test/Test_controller.py @@ -26,7 +26,7 @@ class Test_controller( object ): User.sql_save_notebook = lambda self, notebook_id, read_write = False: \ lambda database: sql_save_notebook( self, notebook_id, read_write, database ) - def sql_load_notebooks( self, parents_only, deleted, database ): + def sql_load_notebooks( self, parents_only, undeleted_only, database ): notebooks = [] notebook_tuples = database.user_notebook.get( self.object_id ) @@ -38,14 +38,14 @@ class Test_controller( object ): notebook._Notebook__read_write = read_write if parents_only and notebook.trash_id is None: continue - if deleted != notebook.deleted: + if undeleted_only and notebook.deleted is True: continue notebooks.append( notebook ) return notebooks - User.sql_load_notebooks = lambda self, parents_only = False, deleted = False: \ - lambda database: sql_load_notebooks( self, parents_only, deleted, database ) + User.sql_load_notebooks = lambda self, parents_only = False, undeleted_only = False: \ + lambda database: sql_load_notebooks( self, parents_only, undeleted_only, database ) def sql_load_by_username( username, database ): users = [] diff --git a/model/User.py b/model/User.py index dc4e5d7..3a91ead 100644 --- a/model/User.py +++ b/model/User.py @@ -129,7 +129,7 @@ class User( Persistent ): def sql_load_by_email_address( email_address ): return "select * from luminotes_user_current where email_address = %s;" % quote( email_address ) - def sql_load_notebooks( self, parents_only = False ): + def sql_load_notebooks( self, parents_only = False, undeleted_only = False ): """ Return a SQL string to load a list of the notebooks to which this user has access. """ @@ -138,10 +138,15 @@ class User( Persistent ): else: parents_only_clause = "" + if undeleted_only: + undeleted_only_clause = " and deleted = 'f'" + else: + undeleted_only_clause = "" + return \ "select notebook_current.*, user_notebook.read_write from user_notebook, notebook_current " + \ - "where user_id = %s%s and user_notebook.notebook_id = notebook_current.id order by revision;" % \ - ( quote( self.object_id ), parents_only_clause ) + "where user_id = %s%s%s and user_notebook.notebook_id = notebook_current.id order by revision;" % \ + ( quote( self.object_id ), parents_only_clause, undeleted_only_clause ) def sql_save_notebook( self, notebook_id, read_write = True ): """ diff --git a/static/css/style.css b/static/css/style.css index 1bb866b..79f5dad 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -282,6 +282,20 @@ ol li { padding: 0.25em 0.5em 0 1em; } +#deleted_notebooks { + text-align: left; + margin: 1em; + line-height: 140%; +} + +#deleted_notebooks div { + margin-left: 0.75em; +} + +#deleted_notebooks span { + margin: 0.25em; +} + #static_notes { text-align: left; margin: 1em; diff --git a/static/js/Wiki.js b/static/js/Wiki.js index 1871468..52c63aa 100644 --- a/static/js/Wiki.js +++ b/static/js/Wiki.js @@ -20,10 +20,10 @@ function Wiki( invoker ) { this.total_notes_count = null; // grab the current notebook from the list of available notebooks - var notebooks = evalJSON( getElement( "notebooks" ).value ); - for ( var i in notebooks ) { - if ( notebooks[ i ].object_id == this.notebook_id ) { - this.notebook = notebooks[ i ] + this.notebooks = evalJSON( getElement( "notebooks" ).value ); + for ( var i in this.notebooks ) { + if ( this.notebooks[ i ].object_id == this.notebook_id ) { + this.notebook = this.notebooks[ i ] break; } } @@ -98,7 +98,7 @@ function Wiki( invoker ) { }, "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_via_undo( event, deleted_id, message_div ); } ); + connect( undo_button, "onclick", function ( event ) { self.undelete_notebook( event, deleted_id ); } ); } } @@ -143,6 +143,56 @@ Wiki.prototype.display_storage_usage = function( storage_bytes ) { } Wiki.prototype.populate = function ( startup_notes, current_notes, note_read_write, skip_empty_message ) { + var self = this; + + // if this is the trash, display a list of all deleted notebooks + if ( this.notebook.name == "trash" ) { + var heading_shown = false; + var deleted_notebooks = getElement( "deleted_notebooks" ); + + for ( var i in this.notebooks ) { + var notebook = this.notebooks[ i ]; + if ( !notebook.deleted ) + continue; + + if ( !heading_shown ) { + appendChildNodes( deleted_notebooks, createDOM( "h4", {}, "deleted notebooks" ) ); + heading_shown = true; + } + + delete_button = createDOM( "input", { + "type": "button", + "class": "note_button", + "id": "delete_notebook_" + notebook.object_id, + "value": "delete forever", + "title": "delete notebook" + } ); + function connect_delete( notebook_id ) { + connect( delete_button, "onclick", function ( event ) { self.delete_notebook_forever( event, notebook_id ); } ); + } + connect_delete( notebook.object_id ); + + undelete_button = createDOM( "input", { + "type": "button", + "class": "note_button", + "id": "undelete_notebook_" + notebook.object_id, + "value": "undelete", + "title": "undelete notebook" + } ); + function connect_undelete( notebook_id ) { + connect( undelete_button, "onclick", function ( event ) { self.undelete_notebook( event, notebook_id ); } ); + } + connect_undelete( notebook.object_id ); + + appendChildNodes( deleted_notebooks, createDOM( "div", + { "id": "deleted_notebook_" + notebook.object_id }, + createDOM( "span", {}, delete_button ), + createDOM( "span", {}, undelete_button ), + createDOM( "span", {}, notebook.name ) + ) ); + } + } + // create an editor for each startup note in the received notebook, focusing the first one var focus = true; for ( var i in startup_notes ) { @@ -185,8 +235,6 @@ Wiki.prototype.populate = function ( startup_notes, current_notes, note_read_wri if ( startup_notes.length == 0 && current_notes.length == 0 && !skip_empty_message ) this.display_empty_message(); - var self = this; - var empty_trash_link = getElement( "empty_trash_link" ); if ( empty_trash_link ) connect( empty_trash_link, "onclick", function ( event ) { self.delete_all_editors( event ); } ); @@ -973,7 +1021,7 @@ Wiki.prototype.undelete_editor_via_undelete = function( event, note_id, position event.stop(); } -Wiki.prototype.undelete_notebook_via_undo = function( event, notebook_id, position_after ) { +Wiki.prototype.undelete_notebook = function( event, notebook_id ) { this.invoker.invoke( "/notebooks/undelete", "POST", { "notebook_id": notebook_id } ); @@ -1284,7 +1332,7 @@ Wiki.prototype.display_empty_message = function () { if ( !this.total_notes_count ) { if ( this.parent_id ) - this.display_message( "The trash is empty." ) + this.display_message( "There are no notes in the trash." ) else this.display_message( "This notebook is empty." ); return true; @@ -1480,6 +1528,24 @@ Wiki.prototype.delete_notebook = function () { } ); } +Wiki.prototype.delete_notebook_forever = function ( event, notebook_id ) { + var deleted_notebook_node = getElement( "deleted_notebook_" + notebook_id ); + if ( !deleted_notebook_node ) return; + + for ( var i in deleted_notebook_node.childNodes ) { + var child = deleted_notebook_node.childNodes[ i ]; + disconnectAll( child ); + } + + removeElement( deleted_notebook_node ); + + this.invoker.invoke( "/notebooks/delete", "POST", { + "notebook_id": notebook_id + } ); + + event.stop(); +} + Wiki.prototype.toggle_editor_changes = function ( event, editor ) { // if the pulldown is already open, then just close it var pulldown_id = "changes_" + editor.id; diff --git a/view/Main_page.py b/view/Main_page.py index 4b2a513..e1da579 100644 --- a/view/Main_page.py +++ b/view/Main_page.py @@ -144,6 +144,9 @@ class Main_page( Page ): Div( Rounded_div( ( notebook.name == u"trash" ) and u"trash_notebook_inner" or u"current_notebook_inner", + Div( + id = u"deleted_notebooks", + ), Div( Span( id = u"notes_top" ), id = u"notes",