From 68de634b382b99860509123cc6701dfea35ec9c1 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Fri, 14 Nov 2008 12:34:06 -0800 Subject: [PATCH] Rearranged the links on the left and right side of the wiki editing page. Added an "add note to note tree" button that's not quite complete. --- NEWS | 5 +- static/css/style.css | 23 ++++--- static/js/Wiki.js | 146 +++++++++++++++++++++++++++++++++-------- view/Link_area.py | 46 ++++--------- view/Main_page.py | 15 +++-- view/Note_tree_area.py | 46 ++++++++++--- 6 files changed, 197 insertions(+), 84 deletions(-) diff --git a/NEWS b/NEWS index d809f03..a3488e0 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ 1.5.7: - * + * Rearranged the links on the left and right side of the wiki editing page + so the note title links have a little more horizontal breathing room. + * Fixed a bug in which search result note summaries were not showing the + portion of the note that matched the search term. (Luminotes Server) 1.5.6: November 12, 2008 * Greatly improved the speed of wiki searching for Luminotes Server and diff --git a/static/css/style.css b/static/css/style.css index 67570df..86874a7 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -277,7 +277,7 @@ h1 { #note_tree_area { position: fixed; - width: 15em; + width: 20em; max-width: 20%; text-align: left; line-height: 140%; @@ -289,7 +289,8 @@ h1 { #note_tree_area_holder { max-height: 100%; overflow: auto; - margin-left: 0.5em; + margin-left: 1em; + margin-right: 1em; } #note_tree_root_table { @@ -298,7 +299,6 @@ h1 { } #recent_notes_table { - margin-bottom: 1em; font-size: 72%; } @@ -359,15 +359,14 @@ h1 { line-height: 140%; top: 80px; bottom: 1em; - width: 20em; + width: 15em; max-width: 20%; } #link_area_holder { max-height: 100%; overflow: auto; - margin-left: 1em; - margin-right: 1em; + margin-left: 0.5em; } #this_notebook_area_title { @@ -411,6 +410,7 @@ h1 { padding: 0.25em; border: #999999 1px solid; width: 95%; + max-width: 15em; } #clutter_link { @@ -660,6 +660,10 @@ h1 { border: #999999 1px solid; } +.inline { + display: inline; +} + .link_area_item { font-size: 75%; padding: 0.25em 0.25em 0.25em 0.5em; @@ -815,10 +819,6 @@ h1 { font-weight: normal; } -#note_tree_instructions { - line-height: 140%; -} - .new_feature_text { font-size: 90%; font-weight: bold; @@ -842,6 +842,9 @@ h1 { .middle_image { vertical-align: middle; border: 0; +} + +.padding_left { padding-left: 0.5em; } diff --git a/static/js/Wiki.js b/static/js/Wiki.js index 2c51d6e..d1fb67e 100644 --- a/static/js/Wiki.js +++ b/static/js/Wiki.js @@ -436,6 +436,17 @@ Wiki.prototype.populate = function ( startup_notes, current_notes, note_read_wri this.make_image_button( "new_notebook", "new_note", true ); } + + var new_note_tree_link_button = getElement( "new_note_tree_link" ); + if ( new_note_tree_link_button ) { + connect( new_note_tree_link_button, "onclick", function ( event ) { + if ( self.note_tree ) + self.note_tree.start_link_add(); + event.stop(); + } ); + + this.make_image_button( "new_note_tree_link", "new_note", true ); + } } Wiki.prototype.background_clicked = function ( event ) { @@ -1206,7 +1217,7 @@ Wiki.prototype.connect_image_button = function ( button, filename_prefix ) { button.src = toolbar_image_dir + button.filename_prefix + "_button.png"; } ); - if ( button.name == "newNote" || button.name == "new_notebook" ) { + if ( button.name == "newNote" || button.name == "new_notebook" || button.name == "new_note_tree_link" ) { connect( button, "onmousedown", function ( event ) { var toolbar_image_dir = self.get_toolbar_image_dir( button.always_small ); if ( /_hover/.test( button.src ) ) @@ -2760,8 +2771,8 @@ Wiki.prototype.start_notebook_rename = function () { "input", { "type": "button", "class": "message_button", - "value": "ok", - "title": "dismiss this message" + "value": "rename", + "title": "rename this notebook" } ); @@ -4162,11 +4173,11 @@ Suggest_pulldown.prototype.shutdown = function () { } - function Note_tree( wiki, notebook_id, invoker ) { this.wiki = wiki; this.notebook_id = notebook_id; this.invoker = invoker; + this.suggest_pulldown = null; // add onclick handlers to the initial note links within the tree var links = getElementsByTagAndClassName( "a", "note_tree_link", "note_tree_area" ); @@ -4189,7 +4200,7 @@ function Note_tree( wiki, notebook_id, invoker ) { // connect to the wiki note events connect( wiki, "note_renamed", function ( editor, new_title ) { self.rename_link( editor, new_title ); } ); - connect( wiki, "note_added", function ( editor ) { self.add_root_link( editor ); } ); + connect( wiki, "note_added", function ( editor ) { self.add_root_link( editor.id, editor.title, editor.contents(), editor.startup ); } ); connect( wiki, "note_removed", function ( id ) { self.remove_link( id ); } ); connect( wiki, "note_saved", function ( editor ) { self.update_link( editor ); } ); } @@ -4209,41 +4220,40 @@ Note_tree.prototype.link_clicked = function ( event ) { LINK_PATTERN = /]+\s)?href="[^"]+"[^>]*>/i; -Note_tree.prototype.add_root_link = function ( editor ) { +Note_tree.prototype.add_root_link = function ( note_id, title, contents, startup ) { // for now, only add startup notes to the note tree - if ( !editor.startup ) + if ( !startup ) return; // if the root note is already present in the tree, no need to add it again - if ( getElement( "note_tree_item_" + editor.id ) ) + var item = getElement( "note_tree_item_" + note_id ); + if ( item ) { + new Highlight( item, { "endcolor": "#fafafa" } ); return; + } - // display the tree expander arrow if the given note's editor contains any outgoing links - if ( LINK_PATTERN.exec( editor.contents() ) ) - var expander = createDOM( "div", { "class": "tree_expander", "id": "note_tree_expander_" + editor.id } ); + // display the tree expander arrow if the given note's contents contains any outgoing links + if ( LINK_PATTERN.exec( contents ) ) + var expander = createDOM( "div", { "class": "tree_expander", "id": "note_tree_expander_" + note_id } ); else - var expander = createDOM( "div", { "class": "tree_expander_empty", "id": "note_tree_expander_" + editor.id } ); + var expander = createDOM( "div", { "class": "tree_expander_empty", "id": "note_tree_expander_" + note_id } ); var link = createDOM( "a", { - "href": "/notebooks/" + this.notebook_id + "?note_id=" + editor.id, - "id": "note_tree_link_" + editor.id, + "href": "/notebooks/" + this.notebook_id + "?note_id=" + note_id, + "id": "note_tree_link_" + note_id, "class": "note_tree_link" - }, editor.title || "untitled note" ); + }, title || "untitled note" ); - appendChildNodes( "note_tree_root_table_body", createDOM( + insertSiblingNodesBefore( "new_note_tree_link_row", createDOM( "tr", - { "id": "note_tree_item_" + editor.id, "class": "note_tree_item" }, + { "id": "note_tree_item_" + note_id, "class": "note_tree_item" }, createDOM( "td", {}, expander ), createDOM( "td", {}, link ) ) ); var self = this; - connect( expander, "onclick", function ( event ) { self.expand_collapse_link( event, editor.id ); } ); + connect( expander, "onclick", function ( event ) { self.expand_collapse_link( event, note_id ); } ); connect( link, "onclick", function ( event ) { self.link_clicked( event ); } ); - - var instructions = getElement( "note_tree_instructions" ); - if ( instructions ) - addElementClass( instructions, "undisplayed" ); } Note_tree.prototype.remove_link = function ( note_id ) { @@ -4254,10 +4264,6 @@ Note_tree.prototype.remove_link = function ( note_id ) { if ( getFirstElementByTagAndClassName( "a", null, "note_tree_root_table" ) ) return; - - var instructions = getElement( "note_tree_instructions" ); - if ( instructions ) - removeElementClass( instructions, "undisplayed" ); } Note_tree.prototype.rename_link = function ( editor, new_title ) { @@ -4270,7 +4276,7 @@ Note_tree.prototype.update_link = function ( editor ) { var link = getElement( "note_tree_link_" + editor.id ); if ( !link && editor.startup ) { - this.add_root_link( editor ); + this.add_root_link( editor.id, editor.title, editor.contents(), editor.startup ); return; } @@ -4418,6 +4424,92 @@ Note_tree.prototype.display_child_links = function ( result, link, children_area connect_expander( expander, note_id ); } +Note_tree.prototype.start_link_add = function () { + // if the add is already in progress, end the add instead of starting one + var new_note_tree_link_field = getElement( "new_note_tree_link_field" ); + if ( new_note_tree_link_field ) { + this.end_link_add(); + return; + } + + link_field = createDOM( + "input", { + "type": "text", + "value": "", + "id": "new_note_tree_link_field", + "name": "new_note_tree_link_field", + "size": "10", + "class": "text_field" + } + ); + + var ok_button = createDOM( + "input", { + "type": "button", + "class": "message_button", + "value": "add", + "title": "add the note" + } + ); + + var form = createDOM( + "form", { "id": "new_note_tree_link_form", "class": "inline" }, link_field, ok_button + ); + + replaceChildNodes( "new_note_tree_link_area", form ); + + // add a suggest pulldown beneath the link name text field + var self = this; + this.suggest_pulldown = new Suggest_pulldown( + this.wiki, this.notebook_id, this.invoker, link_field, null, "", link_field + ); + connect( this.suggest_pulldown, "suggestion_selected", function ( note ) { + replaceChildNodes( "new_note_tree_link_area", "" ); + self.suggest_pulldown.shutdown(); + // TODO: actually set the startup flag on the note (on the server) + self.add_root_link( note.object_id, note.title, note.contents, true ); + } ); + + connect( form, "onsubmit", function ( event ) { + self.end_link_add(); + event.stop(); + } ); + connect( form, "onkeyup", function ( event ) { + self.suggest_pulldown.update_suggestions( link_field.value ); + } ); + connect( ok_button, "onclick", function ( event ) { + self.end_link_add(); + event.stop(); + } ); + + link_field.focus(); + link_field.select(); +} + +Note_tree.prototype.end_link_add = function () { + var note_name = getElement( "new_note_tree_link_field" ).value; + this.suggest_pulldown.shutdown(); + replaceChildNodes( "new_note_tree_link_area", "" ); + + // if the new name is blank, bail + if ( /^\s*$/.test( note_name ) ) + return; + + // load the requested note by title and add it as a root link + var self = this; + this.invoker.invoke( "/notebooks/load_note_by_title", "GET", { + "notebook_id": this.notebook_id, + "note_title": note_name + }, function ( result ) { + // TODO: actually set the startup flag on the note (on the server) + var note = result.note; + if ( note ) + self.add_root_link( note.object_id, note.title, note.contents, true ); + else + self.wiki.display_message( "Sorry, a note by that title doesn't exist. (If you're trying to create a new note, then simply click that large \"+\" button on the left.)" ); + } ); +} + function Recent_notes( wiki, notebook_id, invoker ) { this.wiki = wiki; this.notebook_id = notebook_id; diff --git a/view/Link_area.py b/view/Link_area.py index 2144311..5a6ffc9 100644 --- a/view/Link_area.py +++ b/view/Link_area.py @@ -1,11 +1,10 @@ -from Tags import Div, P, Span, H4, A, Strong, Img, Input, Br +from Tags import Div, P, Span, H4, A, Strong, Img, Br from Rounded_div import Rounded_div -from Search_form import Search_form from model.Notebook import Notebook class Link_area( Div ): - def __init__( self, notebooks, notebook, parent_id, notebook_path, updates_path, user, rate_plan ): + def __init__( self, toolbar, notebooks, notebook, parent_id, notebook_path, updates_path, user, rate_plan ): linked_notebooks = [ nb for nb in notebooks if ( nb.read_write == Notebook.READ_WRITE or @@ -26,24 +25,13 @@ class Link_area( Div ): Div.__init__( self, + toolbar, Div( Div( H4( u"this %s" % notebook_word, - notebook.read_write != Notebook.READ_ONLY and Input( - type = u"button", - class_ = u"note_button small_text", - id = u"save_button", - value = u"saved", - disabled = u"true", - title = u"save your work", - ) or None, id = u"this_notebook_area_title", ), - Div( - Search_form(), - class_ = u"link_area_item", - ), ( rate_plan.get( u"notebook_sharing" ) and notebook.name == u"Luminotes blog" ) and Div( A( @@ -53,7 +41,7 @@ class Link_area( Div ): title = u"Subscribe to the RSS feed for the Luminotes blog.", ), A( - Img( src = u"/static/images/rss.png", width = u"14", height = u"14", class_ = u"middle_image" ), + Img( src = u"/static/images/rss.png", width = u"14", height = u"14", class_ = u"middle_image padding_left" ), href = u"%s?rss" % notebook_path, title = u"Subscribe to the RSS feed for the Luminotes blog.", ), @@ -66,7 +54,7 @@ class Link_area( Div ): title = u"Subscribe to the RSS feed for this %s." % notebook_word, ), A( - Img( src = u"/static/images/rss.png", width = u"14", height = u"14", class_ = u"middle_image" ), + Img( src = u"/static/images/rss.png", width = u"14", height = u"14", class_ = u"middle_image padding_left" ), href = updates_path, title = u"Subscribe to the RSS feed for this %s." % notebook_word, ), @@ -169,13 +157,6 @@ class Link_area( Div ): ( not forum_tag ) and Div( ( len( linked_notebooks ) > 0 ) and H4( u"notebooks", - Img( - src = u"/static/images/toolbar/small/new_note_button.png", - width = u"20", height = u"20", - id = "new_notebook", - class_ = u"middle_image", - title = u"Create a new wiki notebook." - ), id = u"notebooks_area_title", ) or None, [ ( nb.object_id == notebook.object_id ) and Rounded_div( @@ -203,14 +184,15 @@ class Link_area( Div ): ) for nb in linked_notebooks ], id = u"notebooks_area" ) or None, - - ( user.username is None and notebook_path != "/" ) and P( - A( u"Download", href = u"/download", class_ = u"hook_action" ), - Span( u" or ", class_ = u"hook_action_or" ), - A( u"Sign up", href = u"/pricing", class_ = u"hook_action" ), Br(), - Span( "Get started in seconds.", class_ = u"hook_action_detail" ), - class_ = u"hook_action_area", - separator = u"", + ( not forum_tag ) and Div( + Img( + src = u"/static/images/toolbar/small/new_note_button.png", + width = u"20", height = u"20", + id = "new_notebook", + class_ = u"middle_image", + title = u"Create a new wiki notebook." + ), + class_ = u"link_area_item", ) or None, Div( diff --git a/view/Main_page.py b/view/Main_page.py index c8bd2ca..451481b 100644 --- a/view/Main_page.py +++ b/view/Main_page.py @@ -166,16 +166,13 @@ class Main_page( Page ): Header( user, header_notebook, login_url, logout_url, header_note_title, rate_plan ), Div( Div( - Note_tree_area( + Link_area( Toolbar( notebook, hide_toolbar = parent_id or notebook.read_write == Notebook.READ_ONLY, note_word = ( notebook.read_write == Notebook.READ_WRITE_FOR_OWN_NOTES ) and u"post" or u"note", ), - notebook, - root_notes, - recent_notes, - total_notes_count, + notebooks, notebook, parent_id, notebook_path, updates_path, user, rate_plan, ), id = u"left_area", ), @@ -247,7 +244,13 @@ class Main_page( Page ): id = u"center_content_area", ), Div( - Link_area( notebooks, notebook, parent_id, notebook_path, updates_path, user, rate_plan ), + Note_tree_area( + notebook, + root_notes, + recent_notes, + total_notes_count, + user, + ), id = u"right_area", ), id = u"everything_area", diff --git a/view/Note_tree_area.py b/view/Note_tree_area.py index c035cd6..e49d912 100644 --- a/view/Note_tree_area.py +++ b/view/Note_tree_area.py @@ -1,11 +1,13 @@ import re -from Tags import Div, Span, H4, A, Table, Tbody, Tr, Td +from model.Notebook import Notebook +from Tags import Div, Span, H4, A, Table, Tbody, Tr, Td, Img, P, Br, Input +from Search_form import Search_form class Note_tree_area( Div ): LINK_PATTERN = re.compile( u']+\s)?href="[^"]+"[^>]*>', re.IGNORECASE ) - def __init__( self, toolbar, notebook, root_notes, recent_notes, total_notes_count ): + def __init__( self, notebook, root_notes, recent_notes, total_notes_count, user ): tags = [ tag for tag in notebook.tags if tag.name == u"forum" ] if tags: @@ -17,7 +19,6 @@ class Note_tree_area( Div ): Div.__init__( self, - toolbar, Div( H4( forum_tag and u"posts" or u"notes", @@ -25,8 +26,20 @@ class Note_tree_area( Div ): Span( total_notes_count, id = u"total_notes_count" ), u"total", class_ = u"small_text link_area_item", ), + notebook.read_write != Notebook.READ_ONLY and Input( + type = u"button", + class_ = u"note_button small_text", + id = u"save_button", + value = u"saved", + disabled = u"true", + title = u"save your work", + ) or None, id = u"note_tree_area_title", ) or None, + Div( + Search_form(), + class_ = u"link_area_item", + ), forum_tag and Div( A( u"%s forum" % forum_name, href = "/forums/%s" % forum_name ), class_ = u"link_area_item", @@ -39,11 +52,20 @@ class Note_tree_area( Div ): has_children = ( notebook.name != u"trash" ) and self.LINK_PATTERN.search( note.contents ) or False, root_note_id = note.object_id, ) for note in root_notes ], - Tr( Td( - ( notebook.name != u"trash" ) and u'To add a note here, click the "options" tab on a note, then "show on startup".' or None, - id = "note_tree_instructions", - class_ = ( ( len( root_notes ) > 0 ) and u"undisplayed" or u"" ), - ) ) or None, + Tr( + Td(), + ( notebook.name != u"trash" and notebook.read_write == Notebook.READ_WRITE ) and Td( + Img( + src = u"/static/images/toolbar/small/new_note_button.png", + width = u"20", height = u"20", + id = u"new_note_tree_link", + class_ = u"middle_image", + title = u"Add a note to this note tree." + ), + Span( id = u"new_note_tree_link_area" ), + ) or None, + id = u"new_note_tree_link_row", + ) or None, tree_id = "note_tree_root_table", ) or None, ( not forum_tag and recent_notes is not None and notebook.name != u"trash" ) and Span( @@ -70,6 +92,14 @@ class Note_tree_area( Div ): tree_id = "recent_notes_table", ), ) or None, + ( user.username is None ) and P( + A( u"Download", href = u"/download", class_ = u"hook_action" ), + Span( u" or ", class_ = u"hook_action_or" ), + A( u"Sign up", href = u"/pricing", class_ = u"hook_action" ), Br(), + Span( "Get started in seconds.", class_ = u"hook_action_detail" ), + class_ = u"hook_action_area", + separator = u"", + ) or None, id = u"note_tree_area_holder", ), Span( id = "tree_arrow_hover_preload" ),