witten
/
luminotes
Archived
1
0
Fork 0

Renaming all entries to notes to fit better with the name "Luminotes".

This commit is contained in:
Dan Helfman 2007-07-17 01:21:31 +00:00
parent 35481a9cba
commit 0976fdf8c6
29 changed files with 768 additions and 713 deletions

View File

@ -9,10 +9,10 @@ from Expire import strongly_expire
from Html_nuker import Html_nuker
from Async import async
from model.Notebook import Notebook
from model.Entry import Entry
from model.Note import Note
from view.Main_page import Main_page
from view.Json import Json
from view.Entry_page import Entry_page
from view.Note_page import Note_page
from view.Html_file import Html_file
@ -74,10 +74,10 @@ class Notebooks( object ):
@update_client
@validate(
notebook_id = Valid_id(),
entry_id = Valid_id(),
note_id = Valid_id(),
user_id = Valid_id( none_okay = True ),
)
def load_entry( self, notebook_id, entry_id, user_id ):
def load_note( self, notebook_id, note_id, user_id ):
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
raise Access_error()
@ -86,12 +86,12 @@ class Notebooks( object ):
notebook = ( yield Scheduler.SLEEP )
if notebook is None:
entry = None
note = None
else:
entry = notebook.lookup_entry( entry_id )
note = notebook.lookup_note( note_id )
yield dict(
entry = entry,
note = note,
)
@expose( view = Json )
@ -102,10 +102,10 @@ class Notebooks( object ):
@update_client
@validate(
notebook_id = Valid_id(),
entry_title = Valid_string( min = 1, max = 500 ),
note_title = Valid_string( min = 1, max = 500 ),
user_id = Valid_id( none_okay = True ),
)
def load_entry_by_title( self, notebook_id, entry_title, user_id ):
def load_note_by_title( self, notebook_id, note_title, user_id ):
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
raise Access_error()
@ -114,12 +114,12 @@ class Notebooks( object ):
notebook = ( yield Scheduler.SLEEP )
if notebook is None:
entry = None
note = None
else:
entry = notebook.lookup_entry_by_title( entry_title )
note = notebook.lookup_note_by_title( note_title )
yield dict(
entry = entry,
note = note,
)
@expose( view = Json )
@ -129,12 +129,12 @@ class Notebooks( object ):
@update_client
@validate(
notebook_id = Valid_id(),
entry_id = Valid_id(),
note_id = Valid_id(),
contents = Valid_string( min = 1, max = 25000, escape_html = False ),
startup = Valid_bool(),
user_id = Valid_id( none_okay = True ),
)
def save_entry( self, notebook_id, entry_id, contents, startup, user_id ):
def save_note( self, notebook_id, note_id, contents, startup, user_id ):
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
raise Access_error()
@ -148,20 +148,20 @@ class Notebooks( object ):
)
return
self.__database.load( entry_id, self.__scheduler.thread )
entry = ( yield Scheduler.SLEEP )
self.__database.load( note_id, self.__scheduler.thread )
note = ( yield Scheduler.SLEEP )
# if the entry is already in the database, load it and update it. otherwise, create it
if entry and entry in notebook.entries:
notebook.update_entry( entry, contents )
# if the note is already in the database, load it and update it. otherwise, create it
if note and note in notebook.notes:
notebook.update_note( note, contents )
else:
entry = Entry( entry_id, contents )
notebook.add_entry( entry )
note = Note( note_id, contents )
notebook.add_note( note )
if startup:
notebook.add_startup_entry( entry )
notebook.add_startup_note( note )
else:
notebook.remove_startup_entry( entry )
notebook.remove_startup_note( note )
self.__database.save( notebook )
@ -176,10 +176,10 @@ class Notebooks( object ):
@update_client
@validate(
notebook_id = Valid_id(),
entry_id = Valid_id(),
note_id = Valid_id(),
user_id = Valid_id( none_okay = True ),
)
def add_startup_entry( self, notebook_id, entry_id, user_id ):
def add_startup_note( self, notebook_id, note_id, user_id ):
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
raise Access_error()
@ -191,11 +191,11 @@ class Notebooks( object ):
yield dict()
return # TODO: raising an exception here would be nice
self.__database.load( entry_id, self.__scheduler.thread )
entry = ( yield Scheduler.SLEEP )
self.__database.load( note_id, self.__scheduler.thread )
note = ( yield Scheduler.SLEEP )
if entry:
notebook.add_startup_entry( entry )
if note:
notebook.add_startup_note( note )
self.__database.save( notebook )
yield dict()
@ -207,10 +207,10 @@ class Notebooks( object ):
@update_client
@validate(
notebook_id = Valid_id(),
entry_id = Valid_id(),
note_id = Valid_id(),
user_id = Valid_id( none_okay = True ),
)
def remove_startup_entry( self, notebook_id, entry_id, user_id ):
def remove_startup_note( self, notebook_id, note_id, user_id ):
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
raise Access_error()
@ -222,11 +222,11 @@ class Notebooks( object ):
yield dict()
return # TODO: raising an exception here would be nice
self.__database.load( entry_id, self.__scheduler.thread )
entry = ( yield Scheduler.SLEEP )
self.__database.load( note_id, self.__scheduler.thread )
note = ( yield Scheduler.SLEEP )
if entry:
notebook.remove_startup_entry( entry )
if note:
notebook.remove_startup_note( note )
self.__database.save( notebook )
yield dict()
@ -238,10 +238,10 @@ class Notebooks( object ):
@update_client
@validate(
notebook_id = Valid_id(),
entry_id = Valid_id(),
note_id = Valid_id(),
user_id = Valid_id( none_okay = True ),
)
def delete_entry( self, notebook_id, entry_id, user_id ):
def delete_note( self, notebook_id, note_id, user_id ):
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
raise Access_error()
@ -253,18 +253,18 @@ class Notebooks( object ):
yield dict()
return # TODO: raising an exception here would be nice
self.__database.load( entry_id, self.__scheduler.thread )
entry = ( yield Scheduler.SLEEP )
self.__database.load( note_id, self.__scheduler.thread )
note = ( yield Scheduler.SLEEP )
if entry:
notebook.remove_entry( entry )
if note:
notebook.remove_note( note )
self.__database.save( notebook )
yield dict()
@expose( view = Entry_page )
@expose( view = Note_page )
@validate( id = Valid_id() )
def blank_entry( self, id ):
def blank_note( self, id ):
return dict( id = id )
@expose( view = Json )
@ -288,7 +288,7 @@ class Notebooks( object ):
if not notebook:
yield dict(
entries = [],
notes = [],
)
return
@ -298,16 +298,16 @@ class Notebooks( object ):
nuker = Html_nuker()
if len( search_text ) > 0:
for entry in notebook.entries:
if search_text in nuker.nuke( entry.title ).lower():
title_matches.append( entry )
elif search_text in nuker.nuke( entry.contents ).lower():
content_matches.append( entry )
for note in notebook.notes:
if search_text in nuker.nuke( note.title ).lower():
title_matches.append( note )
elif search_text in nuker.nuke( note.contents ).lower():
content_matches.append( note )
entries = title_matches + content_matches
notes = title_matches + content_matches
yield dict(
entries = entries,
notes = notes,
)
@expose( view = Json )
@ -320,7 +320,7 @@ class Notebooks( object ):
notebook_id = Valid_id(),
user_id = Valid_id( none_okay = True ),
)
def recent_entries( self, notebook_id, user_id ):
def recent_notes( self, notebook_id, user_id ):
self.check_access( notebook_id, user_id, self.__scheduler.thread )
if not ( yield Scheduler.SLEEP ):
raise Access_error()
@ -330,16 +330,16 @@ class Notebooks( object ):
if not notebook:
yield dict(
entries = [],
notes = [],
)
return
RECENT_COUNT = 10
entries = notebook.entries
entries.sort( lambda a, b: cmp( b.revision, a.revision ) )
notes = notebook.notes
notes.sort( lambda a, b: cmp( b.revision, a.revision ) )
yield dict(
entries = entries[ :RECENT_COUNT ],
notes = notes[ :RECENT_COUNT ],
)
@expose( view = Html_file )
@ -363,16 +363,16 @@ class Notebooks( object ):
if not notebook:
yield dict(
notebook_name = None,
entries = [],
notes = [],
)
return
normal_entries = list( set( notebook.entries ) - set( notebook.startup_entries ) )
normal_entries.sort( lambda a, b: -cmp( a.revision, b.revision ) )
normal_notes = list( set( notebook.notes ) - set( notebook.startup_notes ) )
normal_notes.sort( lambda a, b: -cmp( a.revision, b.revision ) )
yield dict(
notebook_name = notebook.name,
entries = notebook.startup_entries + normal_entries,
notes = notebook.startup_notes + normal_notes,
)
@async

View File

@ -2,7 +2,7 @@ import re
import cherrypy
from model.User import User
from model.Notebook import Notebook
from model.Entry import Entry
from model.Note import Note
from Scheduler import Scheduler
from Expose import expose
from Validate import validate, Valid_string, Validation_error
@ -134,12 +134,12 @@ class Users( object ):
notebook_id = ( yield Scheduler.SLEEP )
notebook = Notebook( notebook_id, u"my notebook" )
# create a startup entry for this user's notebook
# create a startup note for this user's notebook
self.__database.next_id( self.__scheduler.thread )
entry_id = ( yield Scheduler.SLEEP )
entry = Entry( entry_id, file( u"static/html/welcome to your wiki.html" ).read() )
notebook.add_entry( entry )
notebook.add_startup_entry( entry )
note_id = ( yield Scheduler.SLEEP )
note = Note( note_id, file( u"static/html/welcome to your wiki.html" ).read() )
notebook.add_note( note )
notebook.add_startup_note( note )
# actually create the new user
self.__database.next_id( self.__scheduler.thread )

View File

@ -3,7 +3,7 @@ import cgi
from Test_controller import Test_controller
from controller.Scheduler import Scheduler
from model.Notebook import Notebook
from model.Entry import Entry
from model.Note import Note
from model.User import User
@ -14,7 +14,7 @@ class Test_notebooks( Test_controller ):
self.notebook = None
self.anon_notebook = None
self.unknown_notebook_id = "17"
self.unknown_entry_id = "42"
self.unknown_note_id = "42"
self.username = u"mulder"
self.password = u"trustno1"
self.email_address = u"outthere@example.com"
@ -35,13 +35,13 @@ class Test_notebooks( Test_controller ):
self.notebook = Notebook( ( yield Scheduler.SLEEP ), u"notebook" )
self.database.next_id( self.scheduler.thread )
self.entry = Entry( ( yield Scheduler.SLEEP ), u"<h3>my title</h3>blah" )
self.notebook.add_entry( self.entry )
self.notebook.add_startup_entry( self.entry )
self.note = Note( ( yield Scheduler.SLEEP ), u"<h3>my title</h3>blah" )
self.notebook.add_note( self.note )
self.notebook.add_startup_note( self.note )
self.database.next_id( self.scheduler.thread )
self.entry2 = Entry( ( yield Scheduler.SLEEP ), u"<h3>other title</h3>whee" )
self.notebook.add_entry( self.entry2 )
self.note2 = Note( ( yield Scheduler.SLEEP ), u"<h3>other title</h3>whee" )
self.notebook.add_note( self.note2 )
self.database.save( self.notebook )
self.database.next_id( self.scheduler.thread )
@ -73,8 +73,8 @@ class Test_notebooks( Test_controller ):
notebook = result[ "notebook" ]
assert notebook.object_id == self.notebook.object_id
assert len( notebook.startup_entries ) == 1
assert notebook.startup_entries[ 0 ] == self.entry
assert len( notebook.startup_notes ) == 1
assert notebook.startup_notes[ 0 ] == self.note
def test_contents_without_login( self ):
result = self.http_get(
@ -84,269 +84,269 @@ class Test_notebooks( Test_controller ):
assert result.get( "error" )
def test_load_entry( self ):
def test_load_note( self ):
self.login()
result = self.http_post( "/notebooks/load_entry/", dict(
result = self.http_post( "/notebooks/load_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
entry = result[ "entry" ]
note = result[ "note" ]
assert entry.object_id == self.entry.object_id
assert entry.title == self.entry.title
assert entry.contents == self.entry.contents
assert note.object_id == self.note.object_id
assert note.title == self.note.title
assert note.contents == self.note.contents
def test_load_entry_without_login( self ):
result = self.http_post( "/notebooks/load_entry/", dict(
def test_load_note_without_login( self ):
result = self.http_post( "/notebooks/load_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
assert result.get( "error" )
def test_load_entry_with_unknown_notebook( self ):
def test_load_note_with_unknown_notebook( self ):
self.login()
result = self.http_post( "/notebooks/load_entry/", dict(
result = self.http_post( "/notebooks/load_note/", dict(
notebook_id = self.unknown_notebook_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
assert result.get( "error" )
def test_load_unknown_entry( self ):
def test_load_unknown_note( self ):
self.login()
result = self.http_post( "/notebooks/load_entry/", dict(
result = self.http_post( "/notebooks/load_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.unknown_entry_id,
note_id = self.unknown_note_id,
), session_id = self.session_id )
entry = result[ "entry" ]
assert entry == None
note = result[ "note" ]
assert note == None
def test_load_entry_by_title( self ):
def test_load_note_by_title( self ):
self.login()
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.notebook.object_id,
entry_title = self.entry.title,
note_title = self.note.title,
), session_id = self.session_id )
entry = result[ "entry" ]
note = result[ "note" ]
assert entry.object_id == self.entry.object_id
assert entry.title == self.entry.title
assert entry.contents == self.entry.contents
assert note.object_id == self.note.object_id
assert note.title == self.note.title
assert note.contents == self.note.contents
def test_load_entry_by_title_without_login( self ):
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
def test_load_note_by_title_without_login( self ):
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.notebook.object_id,
entry_title = self.entry.title,
note_title = self.note.title,
), session_id = self.session_id )
assert result.get( "error" )
def test_load_entry_by_title_with_unknown_notebook( self ):
def test_load_note_by_title_with_unknown_notebook( self ):
self.login()
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.unknown_notebook_id,
entry_title = self.entry.title,
note_title = self.note.title,
), session_id = self.session_id )
assert result.get( "error" )
def test_load_unknown_entry_by_title( self ):
def test_load_unknown_note_by_title( self ):
self.login()
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.notebook.object_id,
entry_title = "unknown title",
note_title = "unknown title",
), session_id = self.session_id )
entry = result[ "entry" ]
assert entry == None
note = result[ "note" ]
assert note == None
def test_save_entry( self, startup = False ):
def test_save_note( self, startup = False ):
self.login()
# save over an existing entry supplying new contents and a new title
new_entry_contents = u"<h3>new title</h3>new blah"
result = self.http_post( "/notebooks/save_entry/", dict(
# save over an existing note supplying new contents and a new title
new_note_contents = u"<h3>new title</h3>new blah"
result = self.http_post( "/notebooks/save_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
contents = new_entry_contents,
note_id = self.note.object_id,
contents = new_note_contents,
startup = startup,
), session_id = self.session_id )
assert result[ "saved" ] == True
# make sure the old title can no longer be loaded
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.notebook.object_id,
entry_title = "my title",
note_title = "my title",
), session_id = self.session_id )
entry = result[ "entry" ]
assert entry == None
note = result[ "note" ]
assert note == None
# make sure the new title is now loadable
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.notebook.object_id,
entry_title = "new title",
note_title = "new title",
), session_id = self.session_id )
entry = result[ "entry" ]
note = result[ "note" ]
assert entry.object_id == self.entry.object_id
assert entry.title == self.entry.title
assert entry.contents == self.entry.contents
assert note.object_id == self.note.object_id
assert note.title == self.note.title
assert note.contents == self.note.contents
# check that the entry is / is not a startup entry
# check that the note is / is not a startup note
if startup:
assert entry in self.notebook.startup_entries
assert note in self.notebook.startup_notes
else:
assert not entry in self.notebook.startup_entries
assert not note in self.notebook.startup_notes
def test_save_startup_entry( self ):
self.test_save_entry( startup = True )
def test_save_startup_note( self ):
self.test_save_note( startup = True )
def test_save_entry_without_login( self, startup = False ):
# save over an existing entry supplying new contents and a new title
new_entry_contents = u"<h3>new title</h3>new blah"
result = self.http_post( "/notebooks/save_entry/", dict(
def test_save_note_without_login( self, startup = False ):
# save over an existing note supplying new contents and a new title
new_note_contents = u"<h3>new title</h3>new blah"
result = self.http_post( "/notebooks/save_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
contents = new_entry_contents,
note_id = self.note.object_id,
contents = new_note_contents,
startup = startup,
), session_id = self.session_id )
assert result.get( "error" )
def test_save_startup_entry_without_login( self ):
self.test_save_entry_without_login( startup = True )
def test_save_startup_note_without_login( self ):
self.test_save_note_without_login( startup = True )
def test_save_entry_with_unknown_notebook( self ):
def test_save_note_with_unknown_notebook( self ):
self.login()
# save over an existing entry supplying new contents and a new title
new_entry_contents = u"<h3>new title</h3>new blah"
result = self.http_post( "/notebooks/save_entry/", dict(
# save over an existing note supplying new contents and a new title
new_note_contents = u"<h3>new title</h3>new blah"
result = self.http_post( "/notebooks/save_note/", dict(
notebook_id = self.unknown_notebook_id,
entry_id = self.entry.object_id,
contents = new_entry_contents,
note_id = self.note.object_id,
contents = new_note_contents,
startup = False,
), session_id = self.session_id )
assert result.get( "error" )
def test_save_new_entry( self, startup = False ):
def test_save_new_note( self, startup = False ):
self.login()
# save a completely new entry
new_entry = Entry( "55", u"<h3>newest title</h3>foo" )
result = self.http_post( "/notebooks/save_entry/", dict(
# save a completely new note
new_note = Note( "55", u"<h3>newest title</h3>foo" )
result = self.http_post( "/notebooks/save_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = new_entry.object_id,
contents = new_entry.contents,
note_id = new_note.object_id,
contents = new_note.contents,
startup = startup,
), session_id = self.session_id )
assert result[ "saved" ] == True
# make sure the new title is now loadable
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.notebook.object_id,
entry_title = new_entry.title,
note_title = new_note.title,
), session_id = self.session_id )
entry = result[ "entry" ]
note = result[ "note" ]
assert entry.object_id == new_entry.object_id
assert entry.title == new_entry.title
assert entry.contents == new_entry.contents
assert note.object_id == new_note.object_id
assert note.title == new_note.title
assert note.contents == new_note.contents
# check that the entry is / is not a startup entry
# check that the note is / is not a startup note
if startup:
assert entry in self.notebook.startup_entries
assert note in self.notebook.startup_notes
else:
assert not entry in self.notebook.startup_entries
assert not note in self.notebook.startup_notes
def test_save_new_startup_entry( self ):
self.test_save_new_entry( startup = True )
def test_save_new_startup_note( self ):
self.test_save_new_note( startup = True )
def test_save_new_entry_with_disallowed_tags( self ):
def test_save_new_note_with_disallowed_tags( self ):
self.login()
# save a completely new entry
# save a completely new note
title_with_tags = u"<h3>my title</h3>"
junk = u"foo<script>haxx0r</script>"
more_junk = u"<p style=\"evil\">blah</p>"
new_entry = Entry( "55", title_with_tags + junk + more_junk )
new_note = Note( "55", title_with_tags + junk + more_junk )
result = self.http_post( "/notebooks/save_entry/", dict(
result = self.http_post( "/notebooks/save_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = new_entry.object_id,
contents = new_entry.contents,
note_id = new_note.object_id,
contents = new_note.contents,
startup = False,
), session_id = self.session_id )
assert result[ "saved" ] == True
# make sure the new title is now loadable
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.notebook.object_id,
entry_title = new_entry.title,
note_title = new_note.title,
), session_id = self.session_id )
entry = result[ "entry" ]
note = result[ "note" ]
expected_contents = title_with_tags + cgi.escape( junk ) + u"<p>blah</p>"
assert entry.object_id == new_entry.object_id
assert entry.title == new_entry.title
assert entry.contents == expected_contents
assert note.object_id == new_note.object_id
assert note.title == new_note.title
assert note.contents == expected_contents
def test_save_new_entry_with_bad_characters( self ):
def test_save_new_note_with_bad_characters( self ):
self.login()
# save a completely new entry
# save a completely new note
contents = "<h3>newest title</h3>foo"
junk = "\xa0bar"
new_entry = Entry( "55", contents + junk )
result = self.http_post( "/notebooks/save_entry/", dict(
new_note = Note( "55", contents + junk )
result = self.http_post( "/notebooks/save_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = new_entry.object_id,
contents = new_entry.contents,
note_id = new_note.object_id,
contents = new_note.contents,
startup = False,
), session_id = self.session_id )
assert result[ "saved" ] == True
# make sure the new title is now loadable
result = self.http_post( "/notebooks/load_entry_by_title/", dict(
result = self.http_post( "/notebooks/load_note_by_title/", dict(
notebook_id = self.notebook.object_id,
entry_title = new_entry.title,
note_title = new_note.title,
), session_id = self.session_id )
entry = result[ "entry" ]
note = result[ "note" ]
assert entry.object_id == new_entry.object_id
assert entry.title == new_entry.title
assert entry.contents == contents + " bar"
assert note.object_id == new_note.object_id
assert note.title == new_note.title
assert note.contents == contents + " bar"
def test_add_startup_entry( self ):
def test_add_startup_note( self ):
self.login()
result = self.http_post( "/notebooks/add_startup_entry/", dict(
result = self.http_post( "/notebooks/add_startup_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry2.object_id,
note_id = self.note2.object_id,
), session_id = self.session_id )
# test that the added entry shows up in notebook.startup_entries
# test that the added note shows up in notebook.startup_notes
result = self.http_get(
"/notebooks/contents?notebook_id=%s" % self.notebook.object_id,
session_id = self.session_id,
@ -354,27 +354,27 @@ class Test_notebooks( Test_controller ):
notebook = result[ "notebook" ]
assert len( notebook.startup_entries ) == 2
assert notebook.startup_entries[ 0 ] == self.entry
assert notebook.startup_entries[ 1 ] == self.entry2
assert len( notebook.startup_notes ) == 2
assert notebook.startup_notes[ 0 ] == self.note
assert notebook.startup_notes[ 1 ] == self.note2
def test_add_startup_entry_without_login( self ):
result = self.http_post( "/notebooks/add_startup_entry/", dict(
def test_add_startup_note_without_login( self ):
result = self.http_post( "/notebooks/add_startup_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry2.object_id,
note_id = self.note2.object_id,
), session_id = self.session_id )
assert result.get( "error" )
def test_add_startup_entry_with_unknown_notebook( self ):
def test_add_startup_note_with_unknown_notebook( self ):
self.login()
result = self.http_post( "/notebooks/add_startup_entry/", dict(
result = self.http_post( "/notebooks/add_startup_note/", dict(
notebook_id = self.unknown_notebook_id,
entry_id = self.entry2.object_id,
note_id = self.note2.object_id,
), session_id = self.session_id )
# test that notebook.startup_entries hasn't changed
# test that notebook.startup_notes hasn't changed
result = self.http_get(
"/notebooks/contents?notebook_id=%s" % self.notebook.object_id,
session_id = self.session_id,
@ -382,18 +382,18 @@ class Test_notebooks( Test_controller ):
notebook = result[ "notebook" ]
assert len( notebook.startup_entries ) == 1
assert notebook.startup_entries[ 0 ] == self.entry
assert len( notebook.startup_notes ) == 1
assert notebook.startup_notes[ 0 ] == self.note
def test_add_startup_unknown_entry( self ):
def test_add_startup_unknown_note( self ):
self.login()
result = self.http_post( "/notebooks/add_startup_entry/", dict(
result = self.http_post( "/notebooks/add_startup_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.unknown_entry_id,
note_id = self.unknown_note_id,
), session_id = self.session_id )
# test that notebook.startup_entries hasn't changed
# test that notebook.startup_notes hasn't changed
result = self.http_get(
"/notebooks/contents?notebook_id=%s" % self.notebook.object_id,
session_id = self.session_id,
@ -401,18 +401,18 @@ class Test_notebooks( Test_controller ):
notebook = result[ "notebook" ]
assert len( notebook.startup_entries ) == 1
assert notebook.startup_entries[ 0 ] == self.entry
assert len( notebook.startup_notes ) == 1
assert notebook.startup_notes[ 0 ] == self.note
def test_remove_startup_entry( self ):
def test_remove_startup_note( self ):
self.login()
result = self.http_post( "/notebooks/remove_startup_entry/", dict(
result = self.http_post( "/notebooks/remove_startup_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
# test that the remove entry no longer shows up in notebook.startup_entries
# test that the remove note no longer shows up in notebook.startup_notes
result = self.http_get(
"/notebooks/contents?notebook_id=%s" % self.notebook.object_id,
session_id = self.session_id,
@ -420,25 +420,25 @@ class Test_notebooks( Test_controller ):
notebook = result[ "notebook" ]
assert len( notebook.startup_entries ) == 0
assert len( notebook.startup_notes ) == 0
def test_remove_startup_entry_without_login( self ):
result = self.http_post( "/notebooks/remove_startup_entry/", dict(
def test_remove_startup_note_without_login( self ):
result = self.http_post( "/notebooks/remove_startup_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
assert result.get( "error" )
def test_remove_startup_entry_with_unknown_notebook( self ):
def test_remove_startup_note_with_unknown_notebook( self ):
self.login()
result = self.http_post( "/notebooks/remove_startup_entry/", dict(
result = self.http_post( "/notebooks/remove_startup_note/", dict(
notebook_id = self.unknown_notebook_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
# test that notebook.startup_entries hasn't changed
# test that notebook.startup_notes hasn't changed
result = self.http_get(
"/notebooks/contents?notebook_id=%s" % self.notebook.object_id,
session_id = self.session_id,
@ -446,18 +446,18 @@ class Test_notebooks( Test_controller ):
notebook = result[ "notebook" ]
assert len( notebook.startup_entries ) == 1
assert notebook.startup_entries[ 0 ] == self.entry
assert len( notebook.startup_notes ) == 1
assert notebook.startup_notes[ 0 ] == self.note
def test_remove_startup_unknown_entry( self ):
def test_remove_startup_unknown_note( self ):
self.login()
result = self.http_post( "/notebooks/remove_startup_entry/", dict(
result = self.http_post( "/notebooks/remove_startup_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.unknown_entry_id,
note_id = self.unknown_note_id,
), session_id = self.session_id )
# test that notebook.startup_entries hasn't changed
# test that notebook.startup_notes hasn't changed
result = self.http_get(
"/notebooks/contents?notebook_id=%s" % self.notebook.object_id,
session_id = self.session_id,
@ -465,69 +465,69 @@ class Test_notebooks( Test_controller ):
notebook = result[ "notebook" ]
assert len( notebook.startup_entries ) == 1
assert notebook.startup_entries[ 0 ] == self.entry
assert len( notebook.startup_notes ) == 1
assert notebook.startup_notes[ 0 ] == self.note
def test_delete_entry( self ):
def test_delete_note( self ):
self.login()
result = self.http_post( "/notebooks/delete_entry/", dict(
result = self.http_post( "/notebooks/delete_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
# test that the delete entry is actually deleted
result = self.http_post( "/notebooks/load_entry/", dict(
# test that the delete note is actually deleted
result = self.http_post( "/notebooks/load_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
assert result.get( "entry" ) == None
assert result.get( "note" ) == None
def test_delete_entry_without_login( self ):
result = self.http_post( "/notebooks/delete_entry/", dict(
def test_delete_note_without_login( self ):
result = self.http_post( "/notebooks/delete_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
assert result.get( "error" )
def test_delete_entry_with_unknown_notebook( self ):
def test_delete_note_with_unknown_notebook( self ):
self.login()
result = self.http_post( "/notebooks/delete_entry/", dict(
result = self.http_post( "/notebooks/delete_note/", dict(
notebook_id = self.unknown_notebook_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
# test that the entry hasn't been deleted
result = self.http_post( "/notebooks/load_entry/", dict(
# test that the note hasn't been deleted
result = self.http_post( "/notebooks/load_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
entry = result.get( "entry" )
assert entry.object_id == self.entry.object_id
note = result.get( "note" )
assert note.object_id == self.note.object_id
def test_delete_unknown_entry( self ):
def test_delete_unknown_note( self ):
self.login()
result = self.http_post( "/notebooks/delete_entry/", dict(
result = self.http_post( "/notebooks/delete_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.unknown_entry_id,
note_id = self.unknown_note_id,
), session_id = self.session_id )
# test that the entry hasn't been deleted
result = self.http_post( "/notebooks/load_entry/", dict(
# test that the note hasn't been deleted
result = self.http_post( "/notebooks/load_note/", dict(
notebook_id = self.notebook.object_id,
entry_id = self.entry.object_id,
note_id = self.note.object_id,
), session_id = self.session_id )
entry = result.get( "entry" )
assert entry.object_id == self.entry.object_id
note = result.get( "note" )
assert note.object_id == self.note.object_id
def test_blank_entry( self ):
result = self.http_get( "/notebooks/blank_entry/5" )
def test_blank_note( self ):
result = self.http_get( "/notebooks/blank_note/5" )
assert result[ u"id" ] == u"5"
def test_search( self ):
@ -540,10 +540,10 @@ class Test_notebooks( Test_controller ):
search_text = search_text,
), session_id = self.session_id )
entries = result.get( "entries" )
notes = result.get( "notes" )
assert len( entries ) == 1
assert entries[ 0 ].object_id == self.entry.object_id
assert len( notes ) == 1
assert notes[ 0 ].object_id == self.note.object_id
def test_search_without_login( self ):
search_text = u"bla"
@ -565,10 +565,10 @@ class Test_notebooks( Test_controller ):
search_text = search_text,
), session_id = self.session_id )
entries = result.get( "entries" )
notes = result.get( "notes" )
assert len( entries ) == 1
assert entries[ 0 ].object_id == self.entry.object_id
assert len( notes ) == 1
assert notes[ 0 ].object_id == self.note.object_id
def test_empty_search( self ):
self.login()
@ -580,9 +580,9 @@ class Test_notebooks( Test_controller ):
search_text = search_text,
), session_id = self.session_id )
entries = result.get( "entries" )
notes = result.get( "notes" )
assert len( entries ) == 0
assert len( notes ) == 0
def test_search_with_no_results( self ):
self.login()
@ -594,17 +594,17 @@ class Test_notebooks( Test_controller ):
search_text = search_text,
), session_id = self.session_id )
entries = result.get( "entries" )
notes = result.get( "notes" )
assert len( entries ) == 0
assert len( notes ) == 0
def test_search_title_and_contents( self ):
self.login()
# ensure that entries with titles matching the search text show up before entries with only
# ensure that notes with titles matching the search text show up before notes with only
# contents matching the search text
entry3 = Entry( "55", u"<h3>blah</h3>foo" )
self.notebook.add_entry( entry3 )
note3 = Note( "55", u"<h3>blah</h3>foo" )
self.notebook.add_note( note3 )
self.database.save( self.notebook )
@ -615,11 +615,11 @@ class Test_notebooks( Test_controller ):
search_text = search_text,
), session_id = self.session_id )
entries = result.get( "entries" )
notes = result.get( "notes" )
assert len( entries ) == 2
assert entries[ 0 ].object_id == entry3.object_id
assert entries[ 1 ].object_id == self.entry.object_id
assert len( notes ) == 2
assert notes[ 0 ].object_id == note3.object_id
assert notes[ 1 ].object_id == self.note.object_id
def test_search_html_tags( self ):
self.login()
@ -631,25 +631,25 @@ class Test_notebooks( Test_controller ):
search_text = search_text,
), session_id = self.session_id )
entries = result.get( "entries" )
notes = result.get( "notes" )
assert len( entries ) == 0
assert len( notes ) == 0
def test_recent_entries( self ):
def test_recent_notes( self ):
self.login()
result = self.http_post( "/notebooks/recent_entries/", dict(
result = self.http_post( "/notebooks/recent_notes/", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
entries = result.get( "entries" )
notes = result.get( "notes" )
assert len( entries ) == 2
assert entries[ 0 ].object_id == self.entry2.object_id
assert entries[ 1 ].object_id == self.entry.object_id
assert len( notes ) == 2
assert notes[ 0 ].object_id == self.note2.object_id
assert notes[ 1 ].object_id == self.note.object_id
def test_recent_entries_without_login( self ):
result = self.http_post( "/notebooks/recent_entries/", dict(
def test_recent_notes_without_login( self ):
result = self.http_post( "/notebooks/recent_notes/", dict(
notebook_id = self.notebook.object_id,
), session_id = self.session_id )
@ -658,8 +658,8 @@ class Test_notebooks( Test_controller ):
def test_download_html( self ):
self.login()
entry3 = Entry( "55", u"<h3>blah</h3>foo" )
self.notebook.add_entry( entry3 )
note3 = Note( "55", u"<h3>blah</h3>foo" )
self.notebook.add_note( note3 )
result = self.http_get(
"/notebooks/download_html/%s" % self.notebook.object_id,
@ -667,26 +667,26 @@ class Test_notebooks( Test_controller ):
)
assert result.get( "notebook_name" ) == self.notebook.name
entries = result.get( "entries" )
assert len( entries ) == len( self.notebook.entries )
startup_entry_allowed = True
notes = result.get( "notes" )
assert len( notes ) == len( self.notebook.notes )
startup_note_allowed = True
previous_revision = None
# assert that startup entries come first, then normal entries in descending revision order
for entry in entries:
if entry in self.notebook.startup_entries:
assert startup_entry_allowed
# assert that startup notes come first, then normal notes in descending revision order
for note in notes:
if note in self.notebook.startup_notes:
assert startup_note_allowed
else:
startup_entry_allowed = False
assert entry in self.notebook.entries
startup_note_allowed = False
assert note in self.notebook.notes
if previous_revision:
assert entry.revision < previous_revision
assert note.revision < previous_revision
previous_revision = entry.revision
previous_revision = note.revision
def test_download_html( self ):
entry3 = Entry( "55", u"<h3>blah</h3>foo" )
self.notebook.add_entry( entry3 )
note3 = Note( "55", u"<h3>blah</h3>foo" )
self.notebook.add_note( note3 )
result = self.http_get(
"/notebooks/download_html/%s" % self.notebook.object_id,

View File

@ -77,8 +77,8 @@ class Test_users( Test_controller ):
assert notebooks[ 0 ] == self.anon_notebook
notebook = notebooks[ 1 ]
assert notebook.object_id == new_notebook_id
assert len( notebook.entries ) == 1
assert len( notebook.startup_entries ) == 1
assert len( notebook.notes ) == 1
assert len( notebook.startup_notes ) == 1
def test_signup_with_different_passwords( self ):
result = self.http_post( "/users/signup", dict(

View File

@ -3,22 +3,31 @@ from Persistent import Persistent
from controller.Html_nuker import Html_nuker
class Entry( Persistent ):
class Note( Persistent ):
def __setstate__(self, state):
if "_Entry__title" in state:
state[ "_Note__title" ] = state[ "_Entry__title" ]
del( state[ "_Entry__title" ] )
if "_Entry__contents" in state:
state[ "_Note__contents" ] = state[ "_Entry__contents" ]
del( state[ "_Entry__contents" ] )
self.__dict__ = state
"""
An single textual wiki entry.
An single textual wiki note.
"""
TITLE_PATTERN = re.compile( u"<h3>(.*)</h3>", flags = re.IGNORECASE )
def __init__( self, id, contents = None ):
"""
Create a new entry with the given id and contents.
Create a new note with the given id and contents.
@type id: unicode
@param id: id of the entry
@param id: id of the note
@type contents: unicode or NoneType
@param contents: initial contents of the entry (optional)
@rtype: Entry
@return: newly constructed entry
@param contents: initial contents of the note (optional)
@rtype: Note
@return: newly constructed note
"""
Persistent.__init__( self, id )
self.__title = None
@ -31,7 +40,7 @@ class Entry( Persistent ):
self.__contents = contents
# parse title out of the beginning of the contents
result = Entry.TITLE_PATTERN.search( contents )
result = Note.TITLE_PATTERN.search( contents )
if result:
self.__title = result.groups()[ 0 ]

View File

@ -1,23 +1,32 @@
from copy import copy
from Entry import Entry
from Note import Note
from Persistent import Persistent
class Notebook( Persistent ):
def __setstate__(self, state):
if "_Notebook__entries" in state:
state[ "_Notebook__notes" ] = state[ "_Notebook__entries" ]
del( state[ "_Notebook__entries" ] )
if "_Notebook__startup_entries" in state:
state[ "_Notebook__startup_notes" ] = state[ "_Notebook__startup_entries" ]
del( state[ "_Notebook__startup_entries" ] )
self.__dict__.update(state)
"""
A collection of wiki entries.
A collection of wiki notes.
"""
class UnknownEntryError( ValueError ):
class UnknownNoteError( ValueError ):
"""
Indicates that an accessed entry is not in this notebook.
Indicates that an accessed note is not in this notebook.
"""
def __init__( self, entry_id ):
ValueError.__init__( self, entry_id )
def __init__( self, note_id ):
ValueError.__init__( self, note_id )
def __init__( self, id, name ):
"""
Create a new entry with the given id and name.
Create a new note with the given id and name.
@type id: unicode
@param id: id of the notebook
@ -28,117 +37,117 @@ class Notebook( Persistent ):
"""
Persistent.__init__( self, id )
self.__name = name
self.__entries = {} # map of entry id to entry
self.__titles = {} # map of entry title to entry
self.__startup_entries = [] # list of entries shown on startup
self.__notes = {} # map of note id to note
self.__titles = {} # map of note title to note
self.__startup_notes = [] # list of notes shown on startup
def add_entry( self, entry ):
def add_note( self, note ):
"""
Add an entry to this notebook.
Add an note to this notebook.
@type entry: Entry
@param entry: entry to add
@type note: Note
@param note: note to add
"""
self.update_revision()
self.__entries[ entry.object_id ] = entry
self.__titles[ entry.title ] = entry
self.__notes[ note.object_id ] = note
self.__titles[ note.title ] = note
def remove_entry( self, entry ):
def remove_note( self, note ):
"""
Remove an entry from this notebook.
Remove an note from this notebook.
@type entry: Entry
@param entry: entry to remove
@type note: Note
@param note: note to remove
@rtype: bool
@return: True if the entry was removed, False if the entry wasn't in this notebook
@return: True if the note was removed, False if the note wasn't in this notebook
"""
if self.__entries.pop( entry.object_id, None ):
if self.__notes.pop( note.object_id, None ):
self.update_revision()
self.__titles.pop( entry.title, None )
if entry in self.__startup_entries:
self.__startup_entries.remove( entry )
self.__titles.pop( note.title, None )
if note in self.__startup_notes:
self.__startup_notes.remove( note )
return True
return False
def lookup_entry( self, entry_id ):
def lookup_note( self, note_id ):
"""
Return the entry in this notebook with the given id.
Return the note in this notebook with the given id.
@type entry_id: unicode
@param entry_id: id of the entry to return
@rtype: Entry or NoneType
@return: entry corresponding to the entry id or None
@type note_id: unicode
@param note_id: id of the note to return
@rtype: Note or NoneType
@return: note corresponding to the note id or None
"""
return self.__entries.get( entry_id )
return self.__notes.get( note_id )
def lookup_entry_by_title( self, title ):
def lookup_note_by_title( self, title ):
"""
Return the entry in this notebook with the given title.
Return the note in this notebook with the given title.
@type title: unicode
@param title: title of the entry to return
@rtype: Entry or NoneType
@return: entry corresponding to the title or None
@param title: title of the note to return
@rtype: Note or NoneType
@return: note corresponding to the title or None
"""
return self.__titles.get( title )
def update_entry( self, entry, contents ):
def update_note( self, note, contents ):
"""
Update the given entry with new contents. Bail if the entry's contents are unchanged.
Update the given note with new contents. Bail if the note's contents are unchanged.
@type entry: Entry
@param entry: entry to update
@type note: Note
@param note: note to update
@type contents: unicode
@param contents: new textual contents for the entry
@raises UnknownEntryError: entry to update is not in this notebook
@param contents: new textual contents for the note
@raises UnknownNoteError: note to update is not in this notebook
"""
old_entry = self.__entries.get( entry.object_id )
if old_entry is None:
raise Notebook.UnknownEntryError( entry.object_id )
old_note = self.__notes.get( note.object_id )
if old_note is None:
raise Notebook.UnknownNoteError( note.object_id )
if contents == old_entry.contents:
if contents == old_note.contents:
return
self.update_revision()
self.__titles.pop( entry.title, None )
self.__titles.pop( note.title, None )
entry.contents = contents
note.contents = contents
self.__titles[ entry.title ] = entry
self.__titles[ note.title ] = note
def add_startup_entry( self, entry ):
def add_startup_note( self, note ):
"""
Add the given entry to be shown on startup. It must already be an entry in this notebook.
Add the given note to be shown on startup. It must already be an note in this notebook.
@type entry: unicode
@param entry: entry to be added for startup
@type note: unicode
@param note: note to be added for startup
@rtype: bool
@return: True if the entry was added for startup
@raises UnknownEntryError: given entry is not in this notebook
@return: True if the note was added for startup
@raises UnknownNoteError: given note is not in this notebook
"""
if self.__entries.get( entry.object_id ) is None:
raise Notebook.UnknownEntryError( entry.object_id )
if self.__notes.get( note.object_id ) is None:
raise Notebook.UnknownNoteError( note.object_id )
if not entry in self.__startup_entries:
if not note in self.__startup_notes:
self.update_revision()
self.__startup_entries.append( entry )
self.__startup_notes.append( note )
return True
return False
def remove_startup_entry( self, entry ):
def remove_startup_note( self, note ):
"""
Remove the given entry from being shown on startup.
Remove the given note from being shown on startup.
@type entry: unicode
@param entry: entry to be removed from startup
@type note: unicode
@param note: note to be removed from startup
@rtype: bool
@return: True if the entry was removed from startup
@return: True if the note was removed from startup
"""
if entry in self.__startup_entries:
if note in self.__startup_notes:
self.update_revision()
self.__startup_entries.remove( entry )
self.__startup_notes.remove( note )
return True
return False
@ -147,7 +156,7 @@ class Notebook( Persistent ):
d = Persistent.to_dict( self )
d.update( dict(
name = self.__name,
startup_entries = copy( self.startup_entries ),
startup_notes = copy( self.startup_notes ),
read_write = True,
) )
@ -158,5 +167,5 @@ class Notebook( Persistent ):
self.update_revision()
name = property( lambda self: self.__name, __set_name )
startup_entries = property( lambda self: copy( self.__startup_entries ) )
entries = property( lambda self: self.__entries.values() )
startup_notes = property( lambda self: copy( self.__startup_notes ) )
notes = property( lambda self: self.__notes.values() )

View File

@ -9,11 +9,11 @@ class Read_only_notebook( Persistent ):
Persistent.__init__( self, id )
self.__wrapped = notebook
def lookup_entry( self, entry_id ):
return self.__wrapped.lookup_entry( entry_id )
def lookup_note( self, note_id ):
return self.__wrapped.lookup_note( note_id )
def lookup_entry_by_title( self, title ):
return self.__wrapped.lookup_entry_by_title( title )
def lookup_note_by_title( self, title ):
return self.__wrapped.lookup_note_by_title( title )
def to_dict( self ):
d = self.__wrapped.to_dict()
@ -25,5 +25,5 @@ class Read_only_notebook( Persistent ):
return d
name = property( lambda self: self.__wrapped.name )
entries = property( lambda self: self.__wrapped.entries )
startup_entries = property( lambda self: self.__wrapped.startup_entries )
notes = property( lambda self: self.__wrapped.notes )
startup_notes = property( lambda self: self.__wrapped.startup_notes )

View File

@ -1,44 +0,0 @@
from model.Entry import Entry
class Test_entry( object ):
def setUp( self ):
self.object_id = 17
self.title = u"title goes here"
self.contents = u"<h3>%s</h3>blah" % self.title
self.entry = Entry( self.object_id, self.contents )
def test_create( self ):
assert self.entry.object_id == self.object_id
assert self.entry.contents == self.contents
assert self.entry.title == self.title
def test_set_contents( self ):
new_title = u"new title"
new_contents = u"<h3>%s</h3>new blah" % new_title
previous_revision = self.entry.revision
self.entry.contents = new_contents
assert self.entry.contents == new_contents
assert self.entry.title == new_title
assert self.entry.revision > previous_revision
def test_set_contents_with_html_title( self ):
new_title = u"new title"
new_contents = u"<h3>%s<br/></h3>new blah" % new_title
previous_revision = self.entry.revision
self.entry.contents = new_contents
assert self.entry.contents == new_contents
assert self.entry.title == new_title
assert self.entry.revision > previous_revision
def test_to_dict( self ):
d = self.entry.to_dict()
assert d.get( "contents" ) == self.contents
assert d.get( "title" ) == self.title

44
model/test/Test_note.py Normal file
View File

@ -0,0 +1,44 @@
from model.Note import Note
class Test_note( object ):
def setUp( self ):
self.object_id = 17
self.title = u"title goes here"
self.contents = u"<h3>%s</h3>blah" % self.title
self.note = Note( self.object_id, self.contents )
def test_create( self ):
assert self.note.object_id == self.object_id
assert self.note.contents == self.contents
assert self.note.title == self.title
def test_set_contents( self ):
new_title = u"new title"
new_contents = u"<h3>%s</h3>new blah" % new_title
previous_revision = self.note.revision
self.note.contents = new_contents
assert self.note.contents == new_contents
assert self.note.title == new_title
assert self.note.revision > previous_revision
def test_set_contents_with_html_title( self ):
new_title = u"new title"
new_contents = u"<h3>%s<br/></h3>new blah" % new_title
previous_revision = self.note.revision
self.note.contents = new_contents
assert self.note.contents == new_contents
assert self.note.title == new_title
assert self.note.revision > previous_revision
def test_to_dict( self ):
d = self.note.to_dict()
assert d.get( "contents" ) == self.contents
assert d.get( "title" ) == self.title

View File

@ -1,6 +1,6 @@
from nose.tools import raises
from model.Notebook import Notebook
from model.Entry import Entry
from model.Note import Note
class Test_notebook( object ):
@ -9,7 +9,7 @@ class Test_notebook( object ):
self.name = u"my notebook"
self.notebook = Notebook( self.object_id, self.name )
self.entry = Entry( 18, u"<h3>title</h3>blah" )
self.note = Note( 18, u"<h3>title</h3>blah" )
def test_create( self ):
assert self.notebook.object_id == self.object_id
@ -23,154 +23,154 @@ class Test_notebook( object ):
assert self.notebook.name == new_name
assert self.notebook.revision > previous_revision
def test_add_and_lookup_entry( self ):
def test_add_and_lookup_note( self ):
previous_revision = self.notebook.revision
self.notebook.add_entry( self.entry )
self.notebook.add_note( self.note )
assert self.notebook.revision > previous_revision
entry = self.notebook.lookup_entry( self.entry.object_id )
assert entry == self.entry
note = self.notebook.lookup_note( self.note.object_id )
assert note == self.note
def test_lookup_unknown_entry( self ):
entry = self.notebook.lookup_entry( self.entry.object_id )
assert entry == None
def test_lookup_unknown_note( self ):
note = self.notebook.lookup_note( self.note.object_id )
assert note == None
def test_add_and_lookup_entry_by_title( self ):
def test_add_and_lookup_note_by_title( self ):
previous_revision = self.notebook.revision
self.notebook.add_entry( self.entry )
self.notebook.add_note( self.note )
assert self.notebook.revision > previous_revision
entry = self.notebook.lookup_entry_by_title( self.entry.title )
assert entry == self.entry
note = self.notebook.lookup_note_by_title( self.note.title )
assert note == self.note
def test_lookup_unknown_entry_by_title( self ):
entry = self.notebook.lookup_entry( self.entry.title )
assert entry == None
def test_lookup_unknown_note_by_title( self ):
note = self.notebook.lookup_note( self.note.title )
assert note == None
def test_remove_entry( self ):
def test_remove_note( self ):
previous_revision = self.notebook.revision
self.notebook.add_entry( self.entry )
result = self.notebook.remove_entry( self.entry )
self.notebook.add_note( self.note )
result = self.notebook.remove_note( self.note )
assert result == True
assert self.notebook.revision > previous_revision
entry = self.notebook.lookup_entry( self.entry.object_id )
assert entry == None
note = self.notebook.lookup_note( self.note.object_id )
assert note == None
entry = self.notebook.lookup_entry_by_title( self.entry.title )
assert entry == None
note = self.notebook.lookup_note_by_title( self.note.title )
assert note == None
assert not entry in self.notebook.startup_entries
assert not note in self.notebook.startup_notes
def test_remove_unknown_entry( self ):
def test_remove_unknown_note( self ):
revision = self.notebook.revision
result = self.notebook.remove_entry( self.entry )
result = self.notebook.remove_note( self.note )
assert result == False
assert self.notebook.revision == revision
entry = self.notebook.lookup_entry( self.entry.object_id )
assert entry == None
note = self.notebook.lookup_note( self.note.object_id )
assert note == None
def test_update_entry( self ):
self.notebook.add_entry( self.entry )
old_title = self.entry.title
def test_update_note( self ):
self.notebook.add_note( self.note )
old_title = self.note.title
new_title = u"new title"
new_contents = u"<h3>%s</h3>new blah" % new_title
previous_revision = self.notebook.revision
self.notebook.update_entry( self.entry, new_contents )
self.notebook.update_note( self.note, new_contents )
assert self.entry.contents == new_contents
assert self.entry.title == new_title
assert self.note.contents == new_contents
assert self.note.title == new_title
assert self.notebook.revision > previous_revision
entry = self.notebook.lookup_entry( self.entry.object_id )
assert entry == self.entry
note = self.notebook.lookup_note( self.note.object_id )
assert note == self.note
entry = self.notebook.lookup_entry_by_title( old_title )
assert entry == None
note = self.notebook.lookup_note_by_title( old_title )
assert note == None
entry = self.notebook.lookup_entry_by_title( new_title )
assert entry == self.entry
note = self.notebook.lookup_note_by_title( new_title )
assert note == self.note
def test_update_unrevised_entry( self ):
self.notebook.add_entry( self.entry )
old_title = self.entry.title
def test_update_unrevised_note( self ):
self.notebook.add_note( self.note )
old_title = self.note.title
revision = self.notebook.revision
self.notebook.update_entry( self.entry, self.entry.contents )
self.notebook.update_note( self.note, self.note.contents )
assert self.notebook.revision == revision
entry = self.notebook.lookup_entry( self.entry.object_id )
assert entry == self.entry
note = self.notebook.lookup_note( self.note.object_id )
assert note == self.note
@raises( Notebook.UnknownEntryError )
def test_update_unknown_entry( self ):
@raises( Notebook.UnknownNoteError )
def test_update_unknown_note( self ):
new_contents = u"<h3>new title</h3>new blah"
self.notebook.update_entry( self.entry, new_contents )
self.notebook.update_note( self.note, new_contents )
def test_add_startup_entry( self ):
self.notebook.add_entry( self.entry )
def test_add_startup_note( self ):
self.notebook.add_note( self.note )
previous_revision = self.notebook.revision
self.notebook.add_startup_entry( self.entry )
self.notebook.add_startup_note( self.note )
assert self.entry in self.notebook.startup_entries
assert self.note in self.notebook.startup_notes
assert self.notebook.revision > previous_revision
def test_add_duplicate_startup_entry( self ):
self.notebook.add_entry( self.entry )
def test_add_duplicate_startup_note( self ):
self.notebook.add_note( self.note )
previous_revision = self.notebook.revision
self.notebook.add_startup_entry( self.entry )
self.notebook.add_startup_note( self.note )
assert self.entry in self.notebook.startup_entries
assert self.note in self.notebook.startup_notes
assert self.notebook.revision > previous_revision
revision = self.notebook.revision
self.notebook.add_startup_entry( self.entry )
self.notebook.add_startup_note( self.note )
assert self.notebook.startup_entries.count( self.entry ) == 1
assert self.notebook.startup_notes.count( self.note ) == 1
assert self.notebook.revision == revision
@raises( Notebook.UnknownEntryError )
def test_add_unknown_startup_entry( self ):
self.notebook.add_startup_entry( self.entry )
@raises( Notebook.UnknownNoteError )
def test_add_unknown_startup_note( self ):
self.notebook.add_startup_note( self.note )
def test_remove_startup_entry( self ):
self.notebook.add_entry( self.entry )
self.notebook.add_startup_entry( self.entry )
def test_remove_startup_note( self ):
self.notebook.add_note( self.note )
self.notebook.add_startup_note( self.note )
previous_revision = self.notebook.revision
result = self.notebook.remove_startup_entry( self.entry )
result = self.notebook.remove_startup_note( self.note )
assert result == True
assert not self.entry in self.notebook.startup_entries
assert not self.note in self.notebook.startup_notes
assert self.notebook.revision > previous_revision
def test_remove_unknown_startup_entry( self ):
self.notebook.add_entry( self.entry )
def test_remove_unknown_startup_note( self ):
self.notebook.add_note( self.note )
revision = self.notebook.revision
result = self.notebook.remove_startup_entry( self.entry )
result = self.notebook.remove_startup_note( self.note )
assert result == False
assert not self.entry in self.notebook.startup_entries
assert not self.note in self.notebook.startup_notes
assert self.notebook.revision == revision
def test_to_dict( self ):
d = self.notebook.to_dict()
assert d.get( "name" ) == self.name
assert d.get( "startup_entries" ) == []
assert d.get( "startup_notes" ) == []
assert d.get( "read_write" ) == True
def test_to_dict_with_startup_entries( self ):
self.notebook.add_entry( self.entry )
self.notebook.add_startup_entry( self.entry )
def test_to_dict_with_startup_notes( self ):
self.notebook.add_note( self.note )
self.notebook.add_startup_note( self.note )
d = self.notebook.to_dict()
assert d.get( "name" ) == self.name
assert d.get( "startup_entries" ) == [ self.entry ]
assert d.get( "startup_notes" ) == [ self.note ]
assert d.get( "read_write" ) == True

View File

@ -1,7 +1,7 @@
from nose.tools import raises
from model.Notebook import Notebook
from model.Read_only_notebook import Read_only_notebook
from model.Entry import Entry
from model.Note import Note
class Test_read_only_notebook( object ):
@ -11,59 +11,59 @@ class Test_read_only_notebook( object ):
self.name = u"my notebook"
self.notebook = Notebook( self.object_id, self.name )
self.entry = Entry( "18", u"<h3>title</h3>blah" )
self.notebook.add_entry( self.entry )
self.notebook.add_startup_entry( self.entry )
self.note = Note( "18", u"<h3>title</h3>blah" )
self.notebook.add_note( self.note )
self.notebook.add_startup_note( self.note )
self.read_only = Read_only_notebook( self.read_only_id, self.notebook )
def test_create( self ):
assert self.read_only.object_id == self.read_only_id
assert self.read_only.name == self.name
assert self.read_only.entries == [ self.entry ]
assert self.read_only.startup_entries == [ self.entry ]
assert self.read_only.notes == [ self.note ]
assert self.read_only.startup_notes == [ self.note ]
@raises( AttributeError )
def test_set_name( self ):
self.read_only.name = u"my new notebook"
@raises( AttributeError )
def test_add_entry( self ):
self.read_only.add_entry( self.entry )
def test_add_note( self ):
self.read_only.add_note( self.note )
def test_lookup_entry( self ):
entry = self.read_only.lookup_entry( self.entry.object_id )
assert entry == self.entry
def test_lookup_note( self ):
note = self.read_only.lookup_note( self.note.object_id )
assert note == self.note
def test_lookup_unknown_entry( self ):
entry = self.read_only.lookup_entry( "55" )
assert entry == None
def test_lookup_unknown_note( self ):
note = self.read_only.lookup_note( "55" )
assert note == None
def test_lookup_entry_by_title( self ):
entry = self.read_only.lookup_entry_by_title( self.entry.title )
assert entry == self.entry
def test_lookup_note_by_title( self ):
note = self.read_only.lookup_note_by_title( self.note.title )
assert note == self.note
def test_lookup_unknown_entry_by_title( self ):
entry = self.read_only.lookup_entry( self.entry.title )
assert entry == None
def test_lookup_unknown_note_by_title( self ):
note = self.read_only.lookup_note( self.note.title )
assert note == None
@raises( AttributeError )
def test_remove_entry( self ):
self.read_only.remove_entry( self.entry )
def test_remove_note( self ):
self.read_only.remove_note( self.note )
@raises( AttributeError )
def test_update_entry( self ):
def test_update_note( self ):
new_title = u"new title"
new_contents = u"<h3>%s</h3>new blah" % new_title
self.read_only.update_entry( self.entry, new_contents )
self.read_only.update_note( self.note, new_contents )
@raises( AttributeError )
def test_add_startup_entry( self ):
self.read_only.add_startup_entry( self.entry )
def test_add_startup_note( self ):
self.read_only.add_startup_note( self.note )
@raises( AttributeError )
def test_remove_startup_entry( self ):
self.read_only.remove_startup_entry( self.entry )
def test_remove_startup_note( self ):
self.read_only.remove_startup_note( self.note )
def test_to_dict( self ):
d = self.read_only.to_dict()

View File

@ -10,7 +10,7 @@ body {
width: 50em;
}
.entry_frame {
.note_frame {
text-align: left;
margin: 0em;
padding: 1.25em;

View File

@ -133,19 +133,19 @@ a:hover {
font-size: 0.75em;
}
#entries {
#notes {
text-align: left;
margin-top: 1em;
margin-bottom: 1em;
}
.entry_controls {
.note_controls {
float: right;
margin-right: 1.5em;
font-size: 0.75em;
}
.entry_button {
.note_button {
border-style: outset;
border-width: 0px;
background-color: #d0e0f0;
@ -155,11 +155,11 @@ a:hover {
-webkit-border-radius: 0.25em;
}
.entry_button:hover {
.note_button:hover {
background-color: #ffcc66;
}
.entry_frame {
.note_frame {
margin: 0em;
padding: 0em;
overflow: hidden;
@ -172,7 +172,7 @@ a:hover {
-webkit-border-radius: 0.5em;
}
.focused_entry_frame {
.focused_note_frame {
border: 2px solid black;
}

View File

@ -8,13 +8,13 @@ Here's what makes Luminotes so great:
<li><b>viewing and editing, together at last</b><br />
With Luminotes, you can update any wiki entry without having to switch to
With Luminotes, you can update any wiki note without having to switch to
a separate edit mode. And you can forget about markup or markdown.
<li><b>big-picture browsing</b><br />
Deal with several wiki entries all at once on the same page. Perfect for notes
and brainstorming.</li>
Deal with several wiki notes all at once on the same page. Perfect for
brainstorming.</li>
<li><b>web-based goodness</b><br />
@ -24,7 +24,7 @@ wherever you go.</li>
<li><b>no FunnyLookingTitles</b><br />
You like spaces? So do we. Smashed together titles are completely unnecessary.
You're free to title your wiki entries as you see fit.</li>
You're free to title your wiki notes as you see fit.</li>
<li><b>built-in searching</b><br />
@ -33,5 +33,5 @@ A single search looks through every word in the entire wiki.</li>
</ul>
<p>
Sound interesting? Then <a href="/entries/new">take a tour</a> or <a href="/entries/new">try it out</a> for yourself!
Sound interesting? Then <a href="/notes/new">take a tour</a> or <a href="/notes/new">try it out</a> for yourself!
</p>

View File

@ -1,6 +1,6 @@
<h3>login</h3>
No account yet? Want to make a wiki? You can <a href="/entries/new">try it out</a> for free.
No account yet? Want to make a wiki? You can <a href="/notes/new">try it out</a> for free.
<form id="login_form">
<p>
@ -18,6 +18,6 @@ No account yet? Want to make a wiki? You can <a href="/entries/new">try it out</
</p>
<p>
Forgot? Need your <a href="/entries/new">password reset</a>?
Forgot? Need your <a href="/notes/new">password reset</a>?
</p>
</form>

View File

@ -1,5 +1,5 @@
<a href="/entries/new">about</a> -
<a href="/entries/new">features</a> -
<a href="/entries/new">take a tour</a> -
<a href="/entries/new">try it out</a> -
<a href="/entries/new">login</a>
<a href="/notes/new">about</a> -
<a href="/notes/new">features</a> -
<a href="/notes/new">take a tour</a> -
<a href="/notes/new">try it out</a> -
<a href="/notes/new">login</a>

View File

@ -1,7 +1,7 @@
<h3>supported browsers</h3>
<p>
Luminotes makes use of some <a href="/entries/new">advanced browser features</a>,
Luminotes makes use of some <a href="/notes/new">advanced browser features</a>,
so not all browsers will work for editing your wiki. Supported browsers include:
</p>

View File

@ -35,5 +35,5 @@ dream of giving out your email address.
<input type="submit" name="signup_button" id="signup_button" class="button" value="sign up" />
</p>
Please make sure you're using one of the <a href="/entries/new">supported browsers</a>.
Please make sure you're using one of the <a href="/notes/new">supported browsers</a>.
</form>

View File

@ -3,23 +3,23 @@
<p>Here's how to get started with your personal wiki notebook.</p>
<p><b>First, the basics.</b> A Luminotes notebook is simply a collection of
linked entries, each with a unique title. Right now you're reading an entry
titled "welcome to your wiki".</p>
linked notes, each with a unique title. Right now you're reading a note titled
"welcome to your wiki".</p>
<p><b>To make a new wiki entry</b>, hit the "+" button on the left, or click
anywhere on the page's background. Start by typing a title for your new entry,
say, "ideas", and then press enter. Next, type the contents of your new entry,
<p><b>To make a new wiki note</b>, hit the "+" button on the left, or click
anywhere on the page's background. Start by typing a title for your new note,
say, "ideas", and then press enter. Next, type the contents of your new note,
using the formatting buttons on the left for things like bold, italics, or
lists.</p>
<p><b>To link one entry to another</b>, use the entry link button with the
arrow on it. Hit the button once, type the title of an entry you want to link
to, and then hit the button again. Or, if you've already typed some text, you
can select it with your mouse and then hit the entry link button.</p>
<p><b>To link one note to another</b>, use the note link button with the arrow
on it. Hit the button once, type the title of a note you want to link to, and
then hit the button again. Or, if you've already typed some text, you can
select it with your mouse and then hit the note link button.</p>
<p><b>To follow a link to another entry</b>, just click on it and it will open
up for you to view or edit. You can switch between entries just by clicking on
them, and hide entries simply by clicking the "hide" button.</p>
<p><b>To follow a link to another note</b>, just click on it and it will open
up for you to view or edit. You can switch between notes just by clicking on
them, and hide notes simply by clicking the "hide" button.</p>
<p>That's all you need to know to get started with your personal wiki. It's
that easy. Enjoy!</p>

View File

@ -1,23 +1,23 @@
entry_titles = {} // map from entry title to the open editor for that entry
note_titles = {} // map from note title to the open editor for that note
function Editor( id, entry_text, insert_after_iframe_id, read_write, startup, highlight, focus ) {
this.initial_text = entry_text;
function Editor( id, note_text, insert_after_iframe_id, read_write, startup, highlight, focus ) {
this.initial_text = note_text;
this.id = id;
this.read_write = read_write;
this.startup = startup || false; // whether this Editor is for a startup entry
this.startup = startup || false; // whether this Editor is for a startup note
this.init_highlight = highlight || false;
this.init_focus = focus || false;
var iframe_id = "entry_" + id;
var iframe_id = "note_" + id;
var self = this;
this.document = null;
this.iframe = createDOM( "iframe", {
"src": "/notebooks/blank_entry/" + id,
"src": "/notebooks/blank_note/" + id,
"frameBorder": "0",
"scrolling": "no",
"id": iframe_id,
"name": iframe_id,
"class": "entry_frame"
"class": "note_frame"
} );
this.iframe.editor = this;
this.title = null;
@ -25,19 +25,19 @@ function Editor( id, entry_text, insert_after_iframe_id, read_write, startup, hi
if ( read_write ) {
this.delete_button = createDOM( "input", {
"type": "button",
"class": "entry_button",
"class": "note_button",
"id": "delete_" + iframe_id,
"value": "delete",
"title": "delete entry [ctrl-d]"
"title": "delete note [ctrl-d]"
} );
connect( this.delete_button, "onclick", function ( event ) { signal( self, "delete_clicked", event ); } );
this.options_button = createDOM( "input", {
"type": "button",
"class": "entry_button",
"class": "note_button",
"id": "options_" + iframe_id,
"value": "options",
"title": "entry options"
"title": "note options"
} );
connect( this.options_button, "onclick", function ( event ) { signal( self, "options_clicked", event ); } );
}
@ -45,15 +45,15 @@ function Editor( id, entry_text, insert_after_iframe_id, read_write, startup, hi
if ( read_write || !startup ) {
this.hide_button = createDOM( "input", {
"type": "button",
"class": "entry_button",
"class": "note_button",
"id": "hide_" + iframe_id,
"value": "hide",
"title": "hide entry [ctrl-h]"
"title": "hide note [ctrl-h]"
} );
connect( this.hide_button, "onclick", function ( event ) { signal( self, "hide_clicked", event ); } );
}
this.entry_controls = createDOM( "span", { "class": "entry_controls" },
this.note_controls = createDOM( "span", { "class": "note_controls" },
this.delete_button ? this.delete_button : null,
this.delete_button ? " " : null,
this.options_button ? this.options_button : null,
@ -64,18 +64,18 @@ function Editor( id, entry_text, insert_after_iframe_id, read_write, startup, hi
// if an iframe has been given to insert this new editor after, then insert the new editor's
// iframe. otherwise just append the iframe for the new editor
if ( insert_after_iframe_id ) {
insertSiblingNodesAfter( insert_after_iframe_id, this.entry_controls );
insertSiblingNodesAfter( this.entry_controls, this.iframe );
insertSiblingNodesAfter( insert_after_iframe_id, this.note_controls );
insertSiblingNodesAfter( this.note_controls, this.iframe );
} else {
appendChildNodes( "entries", this.entry_controls );
appendChildNodes( "entries", this.iframe );
appendChildNodes( "notes", this.note_controls );
appendChildNodes( "notes", this.iframe );
}
}
// second stage of construction, invoked by the iframe's body onload handler. do not call directly.
// four-stage construction is only necessary because IE is such a piece of shit
function editor_loaded( id ) {
var iframe = getElement( "entry_" + id );
var iframe = getElement( "note_" + id );
setTimeout( function () { iframe.editor.init_document(); }, 1 );
}
@ -121,7 +121,7 @@ Editor.prototype.finish_init = function () {
connect( this.document.body, "onblur", function ( event ) { self.blurred( event ); } );
connect( this.document.body, "onfocus", function ( event ) { self.focused( event ); } );
// special-case: connect any submit buttons within the contents of this entry
// special-case: connect any submit buttons within the contents of this note
var signup_button = withDocument( this.document, function () { return getElement( "signup_button" ); } );
if ( signup_button ) {
var signup_form = withDocument( this.document, function () { return getElement( "signup_form" ); } );
@ -256,24 +256,24 @@ Editor.prototype.mouse_clicked = function ( event ) {
var id;
var link_title = scrapeText( link );
var editor = entry_titles[ link_title ];
var editor = note_titles[ link_title ];
var href_leaf = link.href.split( "/" ).pop();
// if the link's title corresponds to an open entry id, set that as the link's destination
// if the link's title corresponds to an open note id, set that as the link's destination
if ( editor ) {
id = editor.id;
link.href = "/entries/" + id;
// if this is a new link, get a new entry id and set it for the link's destination
link.href = "/notes/" + id;
// if this is a new link, get a new note id and set it for the link's destination
} else if ( href_leaf == "new" ) {
signal( this, "load_editor_by_title", link_title, this.iframe.id );
return;
// otherwise, use the id from link's current destination
} else {
// the last part of the current link's href is the entry id
// the last part of the current link's href is the note id
id = href_leaf;
}
// find the entry corresponding to the linked id, or create a new entry
var iframe = getElement( "entry_" + id );
// find the note corresponding to the linked id, or create a new note
var iframe = getElement( "note_" + id );
if ( iframe ) {
iframe.editor.highlight();
return;
@ -283,18 +283,18 @@ Editor.prototype.mouse_clicked = function ( event ) {
}
Editor.prototype.scrape_title = function () {
// scrape the entry title out of the editor
// scrape the note title out of the editor
var heading = getFirstElementByTagAndClassName( "h3", null, this.document );
if ( !heading ) return;
var title = scrapeText( heading );
// delete the previous title (if any) from the entry_titles map
// delete the previous title (if any) from the note_titles map
if ( this.title )
delete entry_titles[ this.title ];
delete note_titles[ this.title ];
// record the new title in entry_titles
// record the new title in note_titles
this.title = title;
entry_titles[ this.title ] = this;
note_titles[ this.title ] = this;
}
Editor.prototype.focused = function () {
@ -325,13 +325,13 @@ Editor.prototype.start_link = function () {
var container = range.startContainer;
range.setStart( container, range.startOffset - 1 );
this.exec_command( "createLink", "/entries/new" );
this.exec_command( "createLink", "/notes/new" );
container.nodeValue = "";
selection.collapse( container, 0 );
// otherwise, just create a link with the selected text as the link title
} else {
this.exec_command( "createLink", "/entries/new" );
this.exec_command( "createLink", "/notes/new" );
}
} else if ( this.document.selection ) { // browsers such as IE
var range = this.document.selection.createRange();
@ -344,7 +344,7 @@ Editor.prototype.start_link = function () {
range.select();
}
this.exec_command( "createLink", "/entries/new" );
this.exec_command( "createLink", "/notes/new" );
}
}
@ -422,10 +422,10 @@ Editor.prototype.contents = function () {
Editor.prototype.shutdown = function( event ) {
if ( this.title )
delete entry_titles[ this.title ];
delete note_titles[ this.title ];
var iframe = this.iframe;
var entry_controls = this.entry_controls;
var note_controls = this.note_controls;
disconnectAll( this );
disconnectAll( this.delete_button );
disconnectAll( this.options_button );
@ -435,7 +435,7 @@ Editor.prototype.shutdown = function( event ) {
disconnectAll( this.document );
blindUp( iframe, options = { "duration": 0.5, afterFinish: function () {
try {
removeElement( entry_controls );
removeElement( note_controls );
removeElement( iframe );
} catch ( e ) { }
} } );

View File

@ -5,7 +5,7 @@ function Wiki() {
this.notebook = null;
this.notebook_id = getElement( "notebook_id" ).value;
this.read_write = false;
this.startup_entries = new Array(); // map of startup entries: entry id to bool
this.startup_notes = new Array(); // map of startup notes: note id to bool
this.invoker = new Invoker();
connect( this.invoker, "error_message", this, "display_message" );
@ -45,7 +45,7 @@ Wiki.prototype.display_user = function ( result ) {
// display links for current notebook a list of other notebooks that the user has access to
var span = createDOM( "span" );
replaceChildNodes( "notebook_area", span );
appendChildNodes( span, createDOM( "a", { "href": "/notebooks/" + this.notebook_id, "id": "recent_entries_link" }, "recent entries" ) );
appendChildNodes( span, createDOM( "a", { "href": "/notebooks/" + this.notebook_id, "id": "recent_notes_link" }, "recent notes" ) );
appendChildNodes( span, createDOM( "br" ) );
appendChildNodes( span, createDOM( "a", { "href": "/notebooks/download_html/" + this.notebook_id, "id": "download_html_link" }, "download as html" ) );
@ -69,9 +69,9 @@ Wiki.prototype.display_user = function ( result ) {
appendChildNodes( span, createDOM( "a", { "href": "/", "id": "logout_link" }, "logout" ) );
var self = this;
connect( "recent_entries_link", "onclick", function ( event ) {
connect( "recent_notes_link", "onclick", function ( event ) {
self.invoker.invoke(
"/notebooks/recent_entries", "GET", { "notebook_id": self.notebook_id },
"/notebooks/recent_notes", "GET", { "notebook_id": self.notebook_id },
function( result ) { self.display_search_results( result ); }
);
event.stop();
@ -107,7 +107,7 @@ Wiki.prototype.populate = function ( result ) {
connect( "insertUnorderedList", "onclick", function ( event ) { self.toggle_button( event, "insertUnorderedList" ); } );
connect( "insertOrderedList", "onclick", function ( event ) { self.toggle_button( event, "insertOrderedList" ); } );
connect( "createLink", "onclick", this, "toggle_link_button" );
connect( "newEntry", "onclick", this, "create_blank_editor" );
connect( "newNote", "onclick", this, "create_blank_editor" );
connect( "html", "onclick", this, "background_clicked" );
// grab the next available object id
@ -116,13 +116,13 @@ Wiki.prototype.populate = function ( result ) {
);
}
// create an editor for each startup entry in the received notebook, focusing the first one
for ( var i in this.notebook.startup_entries ) {
var entry = this.notebook.startup_entries[ i ];
if ( !entry ) continue;
this.startup_entries[ entry.object_id ] = true;
// create an editor for each startup note in the received notebook, focusing the first one
for ( var i in this.notebook.startup_notes ) {
var note = this.notebook.startup_notes[ i ];
if ( !note ) continue;
this.startup_notes[ note.object_id ] = true;
var focus = ( i == 0 );
this.create_editor( entry.object_id, entry.contents, undefined, undefined, false, focus );
this.create_editor( note.object_id, note.contents, undefined, undefined, false, focus );
}
}
@ -142,7 +142,7 @@ Wiki.prototype.create_blank_editor = function ( event ) {
// if there is already a blank editor, then highlight it and bail
if ( this.blank_editor_id != null ) {
var blank_iframe_id = "entry_" + this.blank_editor_id;
var blank_iframe_id = "note_" + this.blank_editor_id;
var iframe = getElement( blank_iframe_id );
if ( iframe && iframe.editor.empty() ) {
iframe.editor.highlight();
@ -153,43 +153,43 @@ Wiki.prototype.create_blank_editor = function ( event ) {
this.blank_editor_id = this.create_editor( undefined, undefined, undefined, undefined, true, true );
}
Wiki.prototype.load_editor = function ( entry_title, insert_after_iframe_id, entry_id ) {
Wiki.prototype.load_editor = function ( note_title, insert_after_iframe_id, note_id ) {
var self = this;
this.invoker.invoke(
"/notebooks/load_entry", "GET", {
"/notebooks/load_note", "GET", {
"notebook_id": this.notebook_id,
"entry_id": entry_id
"note_id": note_id
},
function ( result ) { self.parse_loaded_editor( result, insert_after_iframe_id, entry_title ); }
function ( result ) { self.parse_loaded_editor( result, insert_after_iframe_id, note_title ); }
);
}
Wiki.prototype.load_editor_by_title = function ( entry_title, insert_after_iframe_id ) {
Wiki.prototype.load_editor_by_title = function ( note_title, insert_after_iframe_id ) {
var self = this;
this.invoker.invoke(
"/notebooks/load_entry_by_title", "GET", {
"/notebooks/load_note_by_title", "GET", {
"notebook_id": this.notebook_id,
"entry_title": entry_title
"note_title": note_title
},
function ( result ) { self.parse_loaded_editor( result, insert_after_iframe_id, entry_title ); }
function ( result ) { self.parse_loaded_editor( result, insert_after_iframe_id, note_title ); }
);
}
Wiki.prototype.parse_loaded_editor = function ( result, insert_after_iframe_id, entry_title ) {
if ( result.entry ) {
var id = result.entry.object_id
var entry_text = result.entry.contents;
Wiki.prototype.parse_loaded_editor = function ( result, insert_after_iframe_id, note_title ) {
if ( result.note ) {
var id = result.note.object_id
var note_text = result.note.contents;
} else {
var id = null;
var entry_text = "<h3>" + entry_title;
var note_text = "<h3>" + note_title;
}
this.create_editor( id, entry_text, insert_after_iframe_id, entry_title, true, false );
this.create_editor( id, note_text, insert_after_iframe_id, note_title, true, false );
}
Wiki.prototype.create_editor = function ( id, entry_text, insert_after_iframe_id, entry_title, highlight, focus ) {
Wiki.prototype.create_editor = function ( id, note_text, insert_after_iframe_id, note_title, highlight, focus ) {
this.clear_messages();
this.clear_pulldowns();
@ -209,9 +209,9 @@ Wiki.prototype.create_editor = function ( id, entry_text, insert_after_iframe_id
if ( insert_after_iframe_id ) {
var links = getElementsByTagAndClassName( "a", null, getElement( insert_after_iframe_id ).editor.document );
for ( var i in links ) {
// a link matches if its contained text is the same as this entry's title
if ( scrapeText( links[ i ] ) == entry_title )
links[ i ].href = "/entries/" + id;
// a link matches if its contained text is the same as this note's title
if ( scrapeText( links[ i ] ) == note_title )
links[ i ].href = "/notes/" + id;
}
}
@ -228,8 +228,8 @@ Wiki.prototype.create_editor = function ( id, entry_text, insert_after_iframe_id
}
}
var startup = this.startup_entries[ id ];
var editor = new Editor( id, entry_text, undefined, this.read_write, startup, highlight, focus );
var startup = this.startup_notes[ id ];
var editor = new Editor( id, note_text, undefined, this.read_write, startup, highlight, focus );
if ( this.read_write ) {
connect( editor, "state_changed", this, "editor_state_changed" );
@ -258,10 +258,10 @@ Wiki.prototype.editor_focused = function ( editor, fire_and_forget ) {
this.clear_pulldowns();
if ( editor )
addElementClass( editor.iframe, "focused_entry_frame" );
addElementClass( editor.iframe, "focused_note_frame" );
if ( this.focused_editor && this.focused_editor != editor ) {
removeElementClass( this.focused_editor.iframe, "focused_entry_frame" );
removeElementClass( this.focused_editor.iframe, "focused_note_frame" );
// if the formerly focused editor is completely empty, then remove it as the user leaves it and switches to this editor
if ( this.focused_editor.empty() ) {
@ -297,16 +297,16 @@ Wiki.prototype.editor_key_pressed = function ( editor, event ) {
// ctrl-n: ordered list
} else if ( code == 49 ) {
this.toggle_button( event, "insertOrderedList" );
// ctrl-e: make an entry link
// ctrl-e: make an note link
} else if ( code == 69 ) {
this.toggle_link_button( event );
// ctrl-n: new entry
// ctrl-n: new note
} else if ( code == 78 ) {
this.create_blank_editor( event );
// ctrl-h: hide entry
// ctrl-h: hide note
} else if ( code == 72 ) {
this.hide_editor( event );
// ctrl-d: delete entry
// ctrl-d: delete note
} else if ( code == 68 ) {
this.delete_editor( event );
}
@ -397,13 +397,13 @@ Wiki.prototype.delete_editor = function ( event, editor ) {
}
if ( editor ) {
if ( this.startup_entries[ editor.id ] )
delete this.startup_entries[ editor.id ];
if ( this.startup_notes[ editor.id ] )
delete this.startup_notes[ editor.id ];
if ( this.read_write ) {
this.invoker.invoke( "/notebooks/delete_entry", "POST", {
this.invoker.invoke( "/notebooks/delete_note", "POST", {
"notebook_id": this.notebook_id,
"entry_id": editor.id
"note_id": editor.id
} );
}
@ -422,9 +422,9 @@ Wiki.prototype.save_editor = function ( editor, fire_and_forget ) {
if ( editor && !editor.empty() ) {
// TODO: do something with the result other than just ignoring it
this.invoker.invoke( "/notebooks/save_entry", "POST", {
this.invoker.invoke( "/notebooks/save_note", "POST", {
"notebook_id": this.notebook_id,
"entry_id": editor.id,
"note_id": editor.id,
"contents": editor.contents(),
"startup": editor.startup
}, null, null, fire_and_forget );
@ -449,26 +449,26 @@ Wiki.prototype.display_search_results = function ( result ) {
this.save_editor();
// TODO: somehow highlight the search term within the search results?
// make a map of entry object id to entry
var entries = {};
for ( var i in result.entries ) {
var entry = result.entries[ i ];
entries[ entry.object_id ] = entry;
// make a map of note object id to note
var notes = {};
for ( var i in result.notes ) {
var note = result.notes[ i ];
notes[ note.object_id ] = note;
}
// hide all existing editors except those for startup entries or search results
var iframes = getElementsByTagAndClassName( "iframe", "entry_frame" );
// hide all existing editors except those for startup notes or search results
var iframes = getElementsByTagAndClassName( "iframe", "note_frame" );
for ( var i in iframes ) {
var iframe = iframes[ i ];
// don't hide an existing entry if it's in the search results
if ( entries[ iframe.editor.id ] ) {
// don't hide an existing note if it's in the search results
if ( notes[ iframe.editor.id ] ) {
iframe.editor.highlight( false );
delete entries[ iframe.editor.id ];
delete notes[ iframe.editor.id ];
continue;
}
// don't hide an existing entry if it's a read-only startup entry
// don't hide an existing note if it's a read-only startup note
if ( iframe.editor.startup && !iframe.editor.read_write )
continue;
@ -476,17 +476,17 @@ Wiki.prototype.display_search_results = function ( result ) {
}
// if there are no search results, indicate that and bail
if ( result.entries.length == 0 ) {
this.display_message( "No matching entries." );
if ( result.notes.length == 0 ) {
this.display_message( "No matching notes." );
return;
}
// create an editor for each entry search result, focusing the first one
// create an editor for each note search result, focusing the first one
var i = 0;
for ( var id in entries ) {
var entry = entries[ id ];
for ( var id in notes ) {
var note = notes[ id ];
var focus = ( i == 0 );
this.create_editor( id, entry.contents, undefined, undefined, false, focus );
this.create_editor( id, note.contents, undefined, undefined, false, focus );
i += 1;
}
}
@ -497,7 +497,7 @@ Wiki.prototype.display_message = function ( text ) {
var inner_div = DIV( { "class": "message_inner" }, text );
var div = DIV( { "class": "message" }, inner_div );
appendChildNodes( "entries", div );
appendChildNodes( "notes", div );
ScrollTo( div );
}
@ -578,11 +578,11 @@ Pulldown.prototype.startup_clicked = function ( event ) {
this.startup_checkbox.checked = this.startup_checkbox.checked ? false : true;
this.editor.startup = this.startup_checkbox.checked;
// if this entry isn't empty, save it along with its startup status
// if this note isn't empty, save it along with its startup status
if ( !this.editor.empty() ) {
this.invoker.invoke( "/notebooks/save_entry", "POST", {
this.invoker.invoke( "/notebooks/save_note", "POST", {
"notebook_id": this.notebook_id,
"entry_id": this.editor.id,
"note_id": this.editor.id,
"contents": this.editor.contents(),
"startup": this.editor.startup
} );

View File

@ -6,13 +6,13 @@ from controller.Database import Database
from controller.Scheduler import Scheduler
from model.Notebook import Notebook
from model.Read_only_notebook import Read_only_notebook
from model.Entry import Entry
from model.Note import Note
from model.User import User
class Initializer( object ):
HTML_PATH = u"static/html"
ENTRY_FILES = [ # the second element of the tuple is whether to show the entry on startup
ENTRY_FILES = [ # the second element of the tuple is whether to show the note on startup
( u"navigation.html", True ),
( u"about.html", True ),
( u"features.html", True ),
@ -45,7 +45,7 @@ class Initializer( object ):
self.scheduler.wait_for( thread )
def create_main_notebook( self ):
# create the main notebook and all of its entries
# create the main notebook and all of its notes
self.database.next_id( self.scheduler.thread )
main_notebook_id = ( yield Scheduler.SLEEP )
self.main_notebook = Notebook( main_notebook_id, u"Luminotes" )
@ -55,13 +55,13 @@ class Initializer( object ):
contents = file( full_filename ).read()
self.database.next_id( self.scheduler.thread )
entry_id = ( yield Scheduler.SLEEP )
note_id = ( yield Scheduler.SLEEP )
entry = Entry( entry_id, contents )
self.main_notebook.add_entry( entry )
note = Note( note_id, contents )
self.main_notebook.add_note( note )
if startup:
self.main_notebook.add_startup_entry( entry )
self.main_notebook.add_startup_note( note )
self.database.save( self.main_notebook )
@ -80,16 +80,16 @@ class Initializer( object ):
self.database.save( self.anonymous )
def create_user_notebook( self ):
# create the user notebook along with a startup entry
# create the user notebook along with a startup note
self.database.next_id( self.scheduler.thread )
user_notebook_id = ( yield Scheduler.SLEEP )
self.user_notebook = Notebook( user_notebook_id, u"my notebook" )
self.database.next_id( self.scheduler.thread )
entry_id = ( yield Scheduler.SLEEP )
entry = Entry( entry_id, u"<h3>" )
self.user_notebook.add_entry( entry )
self.user_notebook.add_startup_entry( entry )
note_id = ( yield Scheduler.SLEEP )
note = Note( note_id, u"<h3>" )
self.user_notebook.add_note( note )
self.user_notebook.add_startup_note( note )
self.database.save( self.user_notebook )

37
tools/reloaddb.py Executable file
View File

@ -0,0 +1,37 @@
#!/usr/bin/python2.4
import os
import os.path
from controller.Database import Database
from controller.Scheduler import Scheduler
class Reloader( object ):
def __init__( self, scheduler, database ):
self.scheduler = scheduler
self.database = database
thread = self.reload_database()
self.scheduler.add( thread )
self.scheduler.wait_for( thread )
def reload_database( self ):
for key in self.database._Database__db.keys():
self.database.load( key, self.scheduler.thread )
value = ( yield Scheduler.SLEEP )
if value is None: continue
self.database.save( value, self.scheduler.thread )
value = ( yield Scheduler.SLEEP )
yield None
def main():
scheduler = Scheduler()
database = Database( scheduler, "data.db" )
initializer = Reloader( scheduler, database )
scheduler.wait_until_idle()
if __name__ == "__main__":
main()

View File

@ -4,13 +4,13 @@ import os
import os.path
from controller.Database import Database
from controller.Scheduler import Scheduler
from model.Entry import Entry
from model.Note import Note
class Initializer( object ):
HTML_PATH = u"static/html"
ENTRY_FILES = [ # the second element of the tuple is whether to show the entry on startup
#( u"navigation.html", True ), # skip for now, since the navigtaion entry doesn't have a title
ENTRY_FILES = [ # the second element of the tuple is whether to show the note on startup
#( u"navigation.html", True ), # skip for now, since the navigtaion note doesn't have a title
( u"about.html", True ),
( u"features.html", True ),
( u"take a tour.html", False ),
@ -37,31 +37,31 @@ class Initializer( object ):
self.database.load( u"anonymous", self.scheduler.thread )
anonymous = ( yield Scheduler.SLEEP )
main_notebook = anonymous.notebooks[ 0 ]._Read_only_notebook__wrapped
startup_entries = []
startup_notes = []
# update all of the entries in the main notebook
# update all of the notes in the main notebook
for ( filename, startup ) in self.ENTRY_FILES:
full_filename = os.path.join( self.HTML_PATH, filename )
contents = file( full_filename ).read()
title = filename.replace( u".html", u"" )
entry = main_notebook.lookup_entry_by_title( title )
note = main_notebook.lookup_note_by_title( title )
if entry:
main_notebook.update_entry( entry, contents )
# if for some reason the entry isn't present, create it
if note:
main_notebook.update_note( note, contents )
# if for some reason the note isn't present, create it
else:
self.database.next_id( self.scheduler.thread )
entry_id = ( yield Scheduler.SLEEP )
entry = Entry( entry_id, contents )
main_notebook.add_entry( entry )
note_id = ( yield Scheduler.SLEEP )
note = Note( note_id, contents )
main_notebook.add_note( note )
main_notebook.remove_startup_entry( entry )
main_notebook.remove_startup_note( note )
if startup:
startup_entries.append( entry )
startup_notes.append( note )
for entry in startup_entries:
main_notebook.add_startup_entry( entry )
for note in startup_notes:
main_notebook.add_startup_note( note )
main_notebook.name = u"Luminotes"
self.database.save( main_notebook )

View File

@ -4,15 +4,15 @@ from Tags import Html, Head, Title, Style, Meta, Body, H1, Div, Span, Hr, A
class Html_file( Html ):
ENTRY_LINK_PATTERN = re.compile( u'<a\s+href="\/entries\/([a-z0-9]*)"\s*>', re.IGNORECASE )
ENTRY_LINK_PATTERN = re.compile( u'<a\s+href="\/notes\/([a-z0-9]*)"\s*>', re.IGNORECASE )
def __init__( self, notebook_name, entries ):
relinked_entries = {} # map from entry id to relinked entry contents
def __init__( self, notebook_name, notes ):
relinked_notes = {} # map from note id to relinked note contents
# relink all entry links so they point to named anchors within the page
for entry in entries:
contents = self.ENTRY_LINK_PATTERN.sub( r'<a href="#entry_\1">', entry.contents )
relinked_entries[ entry.object_id ] = contents
# relink all note links so they point to named anchors within the page
for note in notes:
contents = self.ENTRY_LINK_PATTERN.sub( r'<a href="#note_\1">', note.contents )
relinked_notes[ note.object_id ] = contents
cherrypy.response.headerMap[ u"Content-Disposition" ] = u"attachment; filename=wiki.html"
@ -27,12 +27,12 @@ class Html_file( Html ):
Div(
H1( notebook_name ),
[ Span(
A( name = u"entry_%s" % entry.object_id ),
A( name = u"note_%s" % note.object_id ),
Div(
relinked_entries[ entry.object_id ],
class_ = u"entry_frame",
relinked_notes[ note.object_id ],
class_ = u"note_frame",
),
) for entry in entries ],
) for note in notes ],
id = u"center_area",
),
),

View File

@ -42,7 +42,7 @@ class Main_page( Page ):
id = u"top_area",
),
Div(
id = u"entries",
id = u"notes",
),
id = u"center_area",
),

View File

@ -1,12 +1,12 @@
from Tags import Html, Head, Link, Script, Meta, Body
class Entry_page( Html ):
class Note_page( Html ):
def __init__( self, id ):
Html.__init__(
self,
Head(
Link( rel = u"stylesheet", type = u"text/css", href = u"/static/css/entry.css" ),
Link( rel = u"stylesheet", type = u"text/css", href = u"/static/css/note.css" ),
Script( type = u"text/javascript", src = u"/static/js/MochiKit.js" ),
Script( type = u"text/javascript", src = u"/static/js/Invoker.js" ),
Meta( content = u"text/html; charset=UTF-8", http_equiv = u"content-type" ),

View File

@ -11,8 +11,8 @@ class Toolbar( Div ):
Li( Input( type = u"button", value = u"T", id = u"title", title = u"title [ctrl-T]", class_ = u"button" ) ),
Li( Input( type = u"button", value = u"&#149;", id = u"insertUnorderedList", title = u"list [ctrl-L]", class_ = u"button" ) ),
Li( Input( type = u"button", value = u"1.", id = u"insertOrderedList", title = u"numbered list [ctrl-1]", class_ = u"button" ) ),
Li( Input( type = u"button", value = u"&#8594", id = u"createLink", title = u"entry link [ctrl-E]", class_ = u"button" ) ),
Li( Input( type = u"button", value = u"+", id = u"newEntry", title = u"new entry [ctrl-N]", class_ = u"button" ) ),
Li( Input( type = u"button", value = u"&#8594", id = u"createLink", title = u"note link [ctrl-E]", class_ = u"button" ) ),
Li( Input( type = u"button", value = u"+", id = u"newNote", title = u"new note [ctrl-N]", class_ = u"button" ) ),
),
id = u"toolbar",
class_ = u"undisplayed", # start out as hidden, and then shown in the browser if the current notebook is read-write