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

View File

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

View File

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

View File

@ -3,22 +3,31 @@ from Persistent import Persistent
from controller.Html_nuker import Html_nuker 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 ) TITLE_PATTERN = re.compile( u"<h3>(.*)</h3>", flags = re.IGNORECASE )
def __init__( self, id, contents = None ): 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 @type id: unicode
@param id: id of the entry @param id: id of the note
@type contents: unicode or NoneType @type contents: unicode or NoneType
@param contents: initial contents of the entry (optional) @param contents: initial contents of the note (optional)
@rtype: Entry @rtype: Note
@return: newly constructed entry @return: newly constructed note
""" """
Persistent.__init__( self, id ) Persistent.__init__( self, id )
self.__title = None self.__title = None
@ -31,7 +40,7 @@ class Entry( Persistent ):
self.__contents = contents self.__contents = contents
# parse title out of the beginning of the contents # parse title out of the beginning of the contents
result = Entry.TITLE_PATTERN.search( contents ) result = Note.TITLE_PATTERN.search( contents )
if result: if result:
self.__title = result.groups()[ 0 ] self.__title = result.groups()[ 0 ]

View File

@ -1,23 +1,32 @@
from copy import copy from copy import copy
from Entry import Entry from Note import Note
from Persistent import Persistent from Persistent import Persistent
class Notebook( 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 ): def __init__( self, note_id ):
ValueError.__init__( self, entry_id ) ValueError.__init__( self, note_id )
def __init__( self, id, name ): 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 @type id: unicode
@param id: id of the notebook @param id: id of the notebook
@ -28,117 +37,117 @@ class Notebook( Persistent ):
""" """
Persistent.__init__( self, id ) Persistent.__init__( self, id )
self.__name = name self.__name = name
self.__entries = {} # map of entry id to entry self.__notes = {} # map of note id to note
self.__titles = {} # map of entry title to entry self.__titles = {} # map of note title to note
self.__startup_entries = [] # list of entries shown on startup 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 @type note: Note
@param entry: entry to add @param note: note to add
""" """
self.update_revision() self.update_revision()
self.__entries[ entry.object_id ] = entry self.__notes[ note.object_id ] = note
self.__titles[ entry.title ] = entry 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 @type note: Note
@param entry: entry to remove @param note: note to remove
@rtype: bool @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.update_revision()
self.__titles.pop( entry.title, None ) self.__titles.pop( note.title, None )
if entry in self.__startup_entries: if note in self.__startup_notes:
self.__startup_entries.remove( entry ) self.__startup_notes.remove( note )
return True return True
return False 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 @type note_id: unicode
@param entry_id: id of the entry to return @param note_id: id of the note to return
@rtype: Entry or NoneType @rtype: Note or NoneType
@return: entry corresponding to the entry id or None @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 @type title: unicode
@param title: title of the entry to return @param title: title of the note to return
@rtype: Entry or NoneType @rtype: Note or NoneType
@return: entry corresponding to the title or None @return: note corresponding to the title or None
""" """
return self.__titles.get( title ) 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 @type note: Note
@param entry: entry to update @param note: note to update
@type contents: unicode @type contents: unicode
@param contents: new textual contents for the entry @param contents: new textual contents for the note
@raises UnknownEntryError: entry to update is not in this notebook @raises UnknownNoteError: note to update is not in this notebook
""" """
old_entry = self.__entries.get( entry.object_id ) old_note = self.__notes.get( note.object_id )
if old_entry is None: if old_note is None:
raise Notebook.UnknownEntryError( entry.object_id ) raise Notebook.UnknownNoteError( note.object_id )
if contents == old_entry.contents: if contents == old_note.contents:
return return
self.update_revision() 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 @type note: unicode
@param entry: entry to be added for startup @param note: note to be added for startup
@rtype: bool @rtype: bool
@return: True if the entry was added for startup @return: True if the note was added for startup
@raises UnknownEntryError: given entry is not in this notebook @raises UnknownNoteError: given note is not in this notebook
""" """
if self.__entries.get( entry.object_id ) is None: if self.__notes.get( note.object_id ) is None:
raise Notebook.UnknownEntryError( entry.object_id ) raise Notebook.UnknownNoteError( note.object_id )
if not entry in self.__startup_entries: if not note in self.__startup_notes:
self.update_revision() self.update_revision()
self.__startup_entries.append( entry ) self.__startup_notes.append( note )
return True return True
return False 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 @type note: unicode
@param entry: entry to be removed from startup @param note: note to be removed from startup
@rtype: bool @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.update_revision()
self.__startup_entries.remove( entry ) self.__startup_notes.remove( note )
return True return True
return False return False
@ -147,7 +156,7 @@ class Notebook( Persistent ):
d = Persistent.to_dict( self ) d = Persistent.to_dict( self )
d.update( dict( d.update( dict(
name = self.__name, name = self.__name,
startup_entries = copy( self.startup_entries ), startup_notes = copy( self.startup_notes ),
read_write = True, read_write = True,
) ) ) )
@ -158,5 +167,5 @@ class Notebook( Persistent ):
self.update_revision() self.update_revision()
name = property( lambda self: self.__name, __set_name ) name = property( lambda self: self.__name, __set_name )
startup_entries = property( lambda self: copy( self.__startup_entries ) ) startup_notes = property( lambda self: copy( self.__startup_notes ) )
entries = property( lambda self: self.__entries.values() ) notes = property( lambda self: self.__notes.values() )

View File

@ -9,11 +9,11 @@ class Read_only_notebook( Persistent ):
Persistent.__init__( self, id ) Persistent.__init__( self, id )
self.__wrapped = notebook self.__wrapped = notebook
def lookup_entry( self, entry_id ): def lookup_note( self, note_id ):
return self.__wrapped.lookup_entry( entry_id ) return self.__wrapped.lookup_note( note_id )
def lookup_entry_by_title( self, title ): def lookup_note_by_title( self, title ):
return self.__wrapped.lookup_entry_by_title( title ) return self.__wrapped.lookup_note_by_title( title )
def to_dict( self ): def to_dict( self ):
d = self.__wrapped.to_dict() d = self.__wrapped.to_dict()
@ -25,5 +25,5 @@ class Read_only_notebook( Persistent ):
return d return d
name = property( lambda self: self.__wrapped.name ) name = property( lambda self: self.__wrapped.name )
entries = property( lambda self: self.__wrapped.entries ) notes = property( lambda self: self.__wrapped.notes )
startup_entries = property( lambda self: self.__wrapped.startup_entries ) 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 nose.tools import raises
from model.Notebook import Notebook from model.Notebook import Notebook
from model.Entry import Entry from model.Note import Note
class Test_notebook( object ): class Test_notebook( object ):
@ -9,7 +9,7 @@ class Test_notebook( object ):
self.name = u"my notebook" self.name = u"my notebook"
self.notebook = Notebook( self.object_id, self.name ) 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 ): def test_create( self ):
assert self.notebook.object_id == self.object_id 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.name == new_name
assert self.notebook.revision > previous_revision 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 previous_revision = self.notebook.revision
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
assert self.notebook.revision > previous_revision assert self.notebook.revision > previous_revision
entry = self.notebook.lookup_entry( self.entry.object_id ) note = self.notebook.lookup_note( self.note.object_id )
assert entry == self.entry assert note == self.note
def test_lookup_unknown_entry( self ): def test_lookup_unknown_note( self ):
entry = self.notebook.lookup_entry( self.entry.object_id ) note = self.notebook.lookup_note( self.note.object_id )
assert entry == None 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 previous_revision = self.notebook.revision
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
assert self.notebook.revision > previous_revision assert self.notebook.revision > previous_revision
entry = self.notebook.lookup_entry_by_title( self.entry.title ) note = self.notebook.lookup_note_by_title( self.note.title )
assert entry == self.entry assert note == self.note
def test_lookup_unknown_entry_by_title( self ): def test_lookup_unknown_note_by_title( self ):
entry = self.notebook.lookup_entry( self.entry.title ) note = self.notebook.lookup_note( self.note.title )
assert entry == None assert note == None
def test_remove_entry( self ): def test_remove_note( self ):
previous_revision = self.notebook.revision previous_revision = self.notebook.revision
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
result = self.notebook.remove_entry( self.entry ) result = self.notebook.remove_note( self.note )
assert result == True assert result == True
assert self.notebook.revision > previous_revision assert self.notebook.revision > previous_revision
entry = self.notebook.lookup_entry( self.entry.object_id ) note = self.notebook.lookup_note( self.note.object_id )
assert entry == None assert note == None
entry = self.notebook.lookup_entry_by_title( self.entry.title ) note = self.notebook.lookup_note_by_title( self.note.title )
assert entry == None 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 revision = self.notebook.revision
result = self.notebook.remove_entry( self.entry ) result = self.notebook.remove_note( self.note )
assert result == False assert result == False
assert self.notebook.revision == revision assert self.notebook.revision == revision
entry = self.notebook.lookup_entry( self.entry.object_id ) note = self.notebook.lookup_note( self.note.object_id )
assert entry == None assert note == None
def test_update_entry( self ): def test_update_note( self ):
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
old_title = self.entry.title old_title = self.note.title
new_title = u"new title" new_title = u"new title"
new_contents = u"<h3>%s</h3>new blah" % new_title new_contents = u"<h3>%s</h3>new blah" % new_title
previous_revision = self.notebook.revision 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.note.contents == new_contents
assert self.entry.title == new_title assert self.note.title == new_title
assert self.notebook.revision > previous_revision assert self.notebook.revision > previous_revision
entry = self.notebook.lookup_entry( self.entry.object_id ) note = self.notebook.lookup_note( self.note.object_id )
assert entry == self.entry assert note == self.note
entry = self.notebook.lookup_entry_by_title( old_title ) note = self.notebook.lookup_note_by_title( old_title )
assert entry == None assert note == None
entry = self.notebook.lookup_entry_by_title( new_title ) note = self.notebook.lookup_note_by_title( new_title )
assert entry == self.entry assert note == self.note
def test_update_unrevised_entry( self ): def test_update_unrevised_note( self ):
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
old_title = self.entry.title old_title = self.note.title
revision = self.notebook.revision 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 assert self.notebook.revision == revision
entry = self.notebook.lookup_entry( self.entry.object_id ) note = self.notebook.lookup_note( self.note.object_id )
assert entry == self.entry assert note == self.note
@raises( Notebook.UnknownEntryError ) @raises( Notebook.UnknownNoteError )
def test_update_unknown_entry( self ): def test_update_unknown_note( self ):
new_contents = u"<h3>new title</h3>new blah" 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 ): def test_add_startup_note( self ):
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
previous_revision = self.notebook.revision 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 assert self.notebook.revision > previous_revision
def test_add_duplicate_startup_entry( self ): def test_add_duplicate_startup_note( self ):
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
previous_revision = self.notebook.revision 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 assert self.notebook.revision > previous_revision
revision = self.notebook.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 assert self.notebook.revision == revision
@raises( Notebook.UnknownEntryError ) @raises( Notebook.UnknownNoteError )
def test_add_unknown_startup_entry( self ): def test_add_unknown_startup_note( self ):
self.notebook.add_startup_entry( self.entry ) self.notebook.add_startup_note( self.note )
def test_remove_startup_entry( self ): def test_remove_startup_note( self ):
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
self.notebook.add_startup_entry( self.entry ) self.notebook.add_startup_note( self.note )
previous_revision = self.notebook.revision 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 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 assert self.notebook.revision > previous_revision
def test_remove_unknown_startup_entry( self ): def test_remove_unknown_startup_note( self ):
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
revision = self.notebook.revision revision = self.notebook.revision
result = self.notebook.remove_startup_entry( self.entry ) result = self.notebook.remove_startup_note( self.note )
assert result == False 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 assert self.notebook.revision == revision
def test_to_dict( self ): def test_to_dict( self ):
d = self.notebook.to_dict() d = self.notebook.to_dict()
assert d.get( "name" ) == self.name assert d.get( "name" ) == self.name
assert d.get( "startup_entries" ) == [] assert d.get( "startup_notes" ) == []
assert d.get( "read_write" ) == True assert d.get( "read_write" ) == True
def test_to_dict_with_startup_entries( self ): def test_to_dict_with_startup_notes( self ):
self.notebook.add_entry( self.entry ) self.notebook.add_note( self.note )
self.notebook.add_startup_entry( self.entry ) self.notebook.add_startup_note( self.note )
d = self.notebook.to_dict() d = self.notebook.to_dict()
assert d.get( "name" ) == self.name 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 assert d.get( "read_write" ) == True

View File

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

View File

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

View File

@ -133,19 +133,19 @@ a:hover {
font-size: 0.75em; font-size: 0.75em;
} }
#entries { #notes {
text-align: left; text-align: left;
margin-top: 1em; margin-top: 1em;
margin-bottom: 1em; margin-bottom: 1em;
} }
.entry_controls { .note_controls {
float: right; float: right;
margin-right: 1.5em; margin-right: 1.5em;
font-size: 0.75em; font-size: 0.75em;
} }
.entry_button { .note_button {
border-style: outset; border-style: outset;
border-width: 0px; border-width: 0px;
background-color: #d0e0f0; background-color: #d0e0f0;
@ -155,11 +155,11 @@ a:hover {
-webkit-border-radius: 0.25em; -webkit-border-radius: 0.25em;
} }
.entry_button:hover { .note_button:hover {
background-color: #ffcc66; background-color: #ffcc66;
} }
.entry_frame { .note_frame {
margin: 0em; margin: 0em;
padding: 0em; padding: 0em;
overflow: hidden; overflow: hidden;
@ -172,7 +172,7 @@ a:hover {
-webkit-border-radius: 0.5em; -webkit-border-radius: 0.5em;
} }
.focused_entry_frame { .focused_note_frame {
border: 2px solid black; 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 /> <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. a separate edit mode. And you can forget about markup or markdown.
<li><b>big-picture browsing</b><br /> <li><b>big-picture browsing</b><br />
Deal with several wiki entries all at once on the same page. Perfect for notes Deal with several wiki notes all at once on the same page. Perfect for
and brainstorming.</li> brainstorming.</li>
<li><b>web-based goodness</b><br /> <li><b>web-based goodness</b><br />
@ -24,7 +24,7 @@ wherever you go.</li>
<li><b>no FunnyLookingTitles</b><br /> <li><b>no FunnyLookingTitles</b><br />
You like spaces? So do we. Smashed together titles are completely unnecessary. 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 /> <li><b>built-in searching</b><br />
@ -33,5 +33,5 @@ A single search looks through every word in the entire wiki.</li>
</ul> </ul>
<p> <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> </p>

View File

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

View File

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

View File

@ -1,7 +1,7 @@
<h3>supported browsers</h3> <h3>supported browsers</h3>
<p> <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: so not all browsers will work for editing your wiki. Supported browsers include:
</p> </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" /> <input type="submit" name="signup_button" id="signup_button" class="button" value="sign up" />
</p> </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> </form>

View File

@ -3,23 +3,23 @@
<p>Here's how to get started with your personal wiki notebook.</p> <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 <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 linked notes, each with a unique title. Right now you're reading a note titled
titled "welcome to your wiki".</p> "welcome to your wiki".</p>
<p><b>To make a new wiki entry</b>, hit the "+" button on the left, or click <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 entry, 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 entry, 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 using the formatting buttons on the left for things like bold, italics, or
lists.</p> lists.</p>
<p><b>To link one entry to another</b>, use the entry link button with the <p><b>To link one note to another</b>, use the note link button with the arrow
arrow on it. Hit the button once, type the title of an entry you want to link on it. Hit the button once, type the title of a note you want to link to, and
to, and then hit the button again. Or, if you've already typed some text, you then hit the button again. Or, if you've already typed some text, you can
can select it with your mouse and then hit the entry link button.</p> 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 <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 entries just by clicking on up for you to view or edit. You can switch between notes just by clicking on
them, and hide entries simply by clicking the "hide" button.</p> 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 <p>That's all you need to know to get started with your personal wiki. It's
that easy. Enjoy!</p> 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 ) { function Editor( id, note_text, insert_after_iframe_id, read_write, startup, highlight, focus ) {
this.initial_text = entry_text; this.initial_text = note_text;
this.id = id; this.id = id;
this.read_write = read_write; 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_highlight = highlight || false;
this.init_focus = focus || false; this.init_focus = focus || false;
var iframe_id = "entry_" + id; var iframe_id = "note_" + id;
var self = this; var self = this;
this.document = null; this.document = null;
this.iframe = createDOM( "iframe", { this.iframe = createDOM( "iframe", {
"src": "/notebooks/blank_entry/" + id, "src": "/notebooks/blank_note/" + id,
"frameBorder": "0", "frameBorder": "0",
"scrolling": "no", "scrolling": "no",
"id": iframe_id, "id": iframe_id,
"name": iframe_id, "name": iframe_id,
"class": "entry_frame" "class": "note_frame"
} ); } );
this.iframe.editor = this; this.iframe.editor = this;
this.title = null; this.title = null;
@ -25,19 +25,19 @@ function Editor( id, entry_text, insert_after_iframe_id, read_write, startup, hi
if ( read_write ) { if ( read_write ) {
this.delete_button = createDOM( "input", { this.delete_button = createDOM( "input", {
"type": "button", "type": "button",
"class": "entry_button", "class": "note_button",
"id": "delete_" + iframe_id, "id": "delete_" + iframe_id,
"value": "delete", "value": "delete",
"title": "delete entry [ctrl-d]" "title": "delete note [ctrl-d]"
} ); } );
connect( this.delete_button, "onclick", function ( event ) { signal( self, "delete_clicked", event ); } ); connect( this.delete_button, "onclick", function ( event ) { signal( self, "delete_clicked", event ); } );
this.options_button = createDOM( "input", { this.options_button = createDOM( "input", {
"type": "button", "type": "button",
"class": "entry_button", "class": "note_button",
"id": "options_" + iframe_id, "id": "options_" + iframe_id,
"value": "options", "value": "options",
"title": "entry options" "title": "note options"
} ); } );
connect( this.options_button, "onclick", function ( event ) { signal( self, "options_clicked", event ); } ); 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 ) { if ( read_write || !startup ) {
this.hide_button = createDOM( "input", { this.hide_button = createDOM( "input", {
"type": "button", "type": "button",
"class": "entry_button", "class": "note_button",
"id": "hide_" + iframe_id, "id": "hide_" + iframe_id,
"value": "hide", "value": "hide",
"title": "hide entry [ctrl-h]" "title": "hide note [ctrl-h]"
} ); } );
connect( this.hide_button, "onclick", function ( event ) { signal( self, "hide_clicked", event ); } ); 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 ? this.delete_button : null,
this.delete_button ? " " : null, this.delete_button ? " " : null,
this.options_button ? this.options_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 // 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 // iframe. otherwise just append the iframe for the new editor
if ( insert_after_iframe_id ) { if ( insert_after_iframe_id ) {
insertSiblingNodesAfter( insert_after_iframe_id, this.entry_controls ); insertSiblingNodesAfter( insert_after_iframe_id, this.note_controls );
insertSiblingNodesAfter( this.entry_controls, this.iframe ); insertSiblingNodesAfter( this.note_controls, this.iframe );
} else { } else {
appendChildNodes( "entries", this.entry_controls ); appendChildNodes( "notes", this.note_controls );
appendChildNodes( "entries", this.iframe ); appendChildNodes( "notes", this.iframe );
} }
} }
// second stage of construction, invoked by the iframe's body onload handler. do not call directly. // 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 // four-stage construction is only necessary because IE is such a piece of shit
function editor_loaded( id ) { function editor_loaded( id ) {
var iframe = getElement( "entry_" + id ); var iframe = getElement( "note_" + id );
setTimeout( function () { iframe.editor.init_document(); }, 1 ); 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, "onblur", function ( event ) { self.blurred( event ); } );
connect( this.document.body, "onfocus", function ( event ) { self.focused( 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" ); } ); var signup_button = withDocument( this.document, function () { return getElement( "signup_button" ); } );
if ( signup_button ) { if ( signup_button ) {
var signup_form = withDocument( this.document, function () { return getElement( "signup_form" ); } ); var signup_form = withDocument( this.document, function () { return getElement( "signup_form" ); } );
@ -256,24 +256,24 @@ Editor.prototype.mouse_clicked = function ( event ) {
var id; var id;
var link_title = scrapeText( link ); var link_title = scrapeText( link );
var editor = entry_titles[ link_title ]; var editor = note_titles[ link_title ];
var href_leaf = link.href.split( "/" ).pop(); 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 ) { if ( editor ) {
id = editor.id; id = editor.id;
link.href = "/entries/" + id; link.href = "/notes/" + id;
// if this is a new link, get a new entry id and set it for the link's destination // if this is a new link, get a new note id and set it for the link's destination
} else if ( href_leaf == "new" ) { } else if ( href_leaf == "new" ) {
signal( this, "load_editor_by_title", link_title, this.iframe.id ); signal( this, "load_editor_by_title", link_title, this.iframe.id );
return; return;
// otherwise, use the id from link's current destination // otherwise, use the id from link's current destination
} else { } 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; id = href_leaf;
} }
// find the entry corresponding to the linked id, or create a new entry // find the note corresponding to the linked id, or create a new note
var iframe = getElement( "entry_" + id ); var iframe = getElement( "note_" + id );
if ( iframe ) { if ( iframe ) {
iframe.editor.highlight(); iframe.editor.highlight();
return; return;
@ -283,18 +283,18 @@ Editor.prototype.mouse_clicked = function ( event ) {
} }
Editor.prototype.scrape_title = function () { 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 ); var heading = getFirstElementByTagAndClassName( "h3", null, this.document );
if ( !heading ) return; if ( !heading ) return;
var title = scrapeText( heading ); 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 ) 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; this.title = title;
entry_titles[ this.title ] = this; note_titles[ this.title ] = this;
} }
Editor.prototype.focused = function () { Editor.prototype.focused = function () {
@ -325,13 +325,13 @@ Editor.prototype.start_link = function () {
var container = range.startContainer; var container = range.startContainer;
range.setStart( container, range.startOffset - 1 ); range.setStart( container, range.startOffset - 1 );
this.exec_command( "createLink", "/entries/new" ); this.exec_command( "createLink", "/notes/new" );
container.nodeValue = ""; container.nodeValue = "";
selection.collapse( container, 0 ); selection.collapse( container, 0 );
// otherwise, just create a link with the selected text as the link title // otherwise, just create a link with the selected text as the link title
} else { } else {
this.exec_command( "createLink", "/entries/new" ); this.exec_command( "createLink", "/notes/new" );
} }
} else if ( this.document.selection ) { // browsers such as IE } else if ( this.document.selection ) { // browsers such as IE
var range = this.document.selection.createRange(); var range = this.document.selection.createRange();
@ -344,7 +344,7 @@ Editor.prototype.start_link = function () {
range.select(); 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 ) { Editor.prototype.shutdown = function( event ) {
if ( this.title ) if ( this.title )
delete entry_titles[ this.title ]; delete note_titles[ this.title ];
var iframe = this.iframe; var iframe = this.iframe;
var entry_controls = this.entry_controls; var note_controls = this.note_controls;
disconnectAll( this ); disconnectAll( this );
disconnectAll( this.delete_button ); disconnectAll( this.delete_button );
disconnectAll( this.options_button ); disconnectAll( this.options_button );
@ -435,7 +435,7 @@ Editor.prototype.shutdown = function( event ) {
disconnectAll( this.document ); disconnectAll( this.document );
blindUp( iframe, options = { "duration": 0.5, afterFinish: function () { blindUp( iframe, options = { "duration": 0.5, afterFinish: function () {
try { try {
removeElement( entry_controls ); removeElement( note_controls );
removeElement( iframe ); removeElement( iframe );
} catch ( e ) { } } catch ( e ) { }
} } ); } } );

View File

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

View File

@ -6,13 +6,13 @@ from controller.Database import Database
from controller.Scheduler import Scheduler from controller.Scheduler import Scheduler
from model.Notebook import Notebook from model.Notebook import Notebook
from model.Read_only_notebook import Read_only_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 from model.User import User
class Initializer( object ): class Initializer( object ):
HTML_PATH = u"static/html" 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"navigation.html", True ),
( u"about.html", True ), ( u"about.html", True ),
( u"features.html", True ), ( u"features.html", True ),
@ -45,7 +45,7 @@ class Initializer( object ):
self.scheduler.wait_for( thread ) self.scheduler.wait_for( thread )
def create_main_notebook( self ): 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 ) self.database.next_id( self.scheduler.thread )
main_notebook_id = ( yield Scheduler.SLEEP ) main_notebook_id = ( yield Scheduler.SLEEP )
self.main_notebook = Notebook( main_notebook_id, u"Luminotes" ) self.main_notebook = Notebook( main_notebook_id, u"Luminotes" )
@ -55,13 +55,13 @@ class Initializer( object ):
contents = file( full_filename ).read() contents = file( full_filename ).read()
self.database.next_id( self.scheduler.thread ) self.database.next_id( self.scheduler.thread )
entry_id = ( yield Scheduler.SLEEP ) note_id = ( yield Scheduler.SLEEP )
entry = Entry( entry_id, contents ) note = Note( note_id, contents )
self.main_notebook.add_entry( entry ) self.main_notebook.add_note( note )
if startup: if startup:
self.main_notebook.add_startup_entry( entry ) self.main_notebook.add_startup_note( note )
self.database.save( self.main_notebook ) self.database.save( self.main_notebook )
@ -80,16 +80,16 @@ class Initializer( object ):
self.database.save( self.anonymous ) self.database.save( self.anonymous )
def create_user_notebook( self ): 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 ) self.database.next_id( self.scheduler.thread )
user_notebook_id = ( yield Scheduler.SLEEP ) user_notebook_id = ( yield Scheduler.SLEEP )
self.user_notebook = Notebook( user_notebook_id, u"my notebook" ) self.user_notebook = Notebook( user_notebook_id, u"my notebook" )
self.database.next_id( self.scheduler.thread ) self.database.next_id( self.scheduler.thread )
entry_id = ( yield Scheduler.SLEEP ) note_id = ( yield Scheduler.SLEEP )
entry = Entry( entry_id, u"<h3>" ) note = Note( note_id, u"<h3>" )
self.user_notebook.add_entry( entry ) self.user_notebook.add_note( note )
self.user_notebook.add_startup_entry( entry ) self.user_notebook.add_startup_note( note )
self.database.save( self.user_notebook ) 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 import os.path
from controller.Database import Database from controller.Database import Database
from controller.Scheduler import Scheduler from controller.Scheduler import Scheduler
from model.Entry import Entry from model.Note import Note
class Initializer( object ): class Initializer( object ):
HTML_PATH = u"static/html" 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 ), # skip for now, since the navigtaion entry doesn't have a title #( u"navigation.html", True ), # skip for now, since the navigtaion note doesn't have a title
( u"about.html", True ), ( u"about.html", True ),
( u"features.html", True ), ( u"features.html", True ),
( u"take a tour.html", False ), ( u"take a tour.html", False ),
@ -37,31 +37,31 @@ class Initializer( object ):
self.database.load( u"anonymous", self.scheduler.thread ) self.database.load( u"anonymous", self.scheduler.thread )
anonymous = ( yield Scheduler.SLEEP ) anonymous = ( yield Scheduler.SLEEP )
main_notebook = anonymous.notebooks[ 0 ]._Read_only_notebook__wrapped 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: for ( filename, startup ) in self.ENTRY_FILES:
full_filename = os.path.join( self.HTML_PATH, filename ) full_filename = os.path.join( self.HTML_PATH, filename )
contents = file( full_filename ).read() contents = file( full_filename ).read()
title = filename.replace( u".html", u"" ) title = filename.replace( u".html", u"" )
entry = main_notebook.lookup_entry_by_title( title ) note = main_notebook.lookup_note_by_title( title )
if entry: if note:
main_notebook.update_entry( entry, contents ) main_notebook.update_note( note, contents )
# if for some reason the entry isn't present, create it # if for some reason the note isn't present, create it
else: else:
self.database.next_id( self.scheduler.thread ) self.database.next_id( self.scheduler.thread )
entry_id = ( yield Scheduler.SLEEP ) note_id = ( yield Scheduler.SLEEP )
entry = Entry( entry_id, contents ) note = Note( note_id, contents )
main_notebook.add_entry( entry ) main_notebook.add_note( note )
main_notebook.remove_startup_entry( entry ) main_notebook.remove_startup_note( note )
if startup: if startup:
startup_entries.append( entry ) startup_notes.append( note )
for entry in startup_entries: for note in startup_notes:
main_notebook.add_startup_entry( entry ) main_notebook.add_startup_note( note )
main_notebook.name = u"Luminotes" main_notebook.name = u"Luminotes"
self.database.save( main_notebook ) 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 ): 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 ): def __init__( self, notebook_name, notes ):
relinked_entries = {} # map from entry id to relinked entry contents relinked_notes = {} # map from note id to relinked note contents
# relink all entry links so they point to named anchors within the page # relink all note links so they point to named anchors within the page
for entry in entries: for note in notes:
contents = self.ENTRY_LINK_PATTERN.sub( r'<a href="#entry_\1">', entry.contents ) contents = self.ENTRY_LINK_PATTERN.sub( r'<a href="#note_\1">', note.contents )
relinked_entries[ entry.object_id ] = contents relinked_notes[ note.object_id ] = contents
cherrypy.response.headerMap[ u"Content-Disposition" ] = u"attachment; filename=wiki.html" cherrypy.response.headerMap[ u"Content-Disposition" ] = u"attachment; filename=wiki.html"
@ -27,12 +27,12 @@ class Html_file( Html ):
Div( Div(
H1( notebook_name ), H1( notebook_name ),
[ Span( [ Span(
A( name = u"entry_%s" % entry.object_id ), A( name = u"note_%s" % note.object_id ),
Div( Div(
relinked_entries[ entry.object_id ], relinked_notes[ note.object_id ],
class_ = u"entry_frame", class_ = u"note_frame",
), ),
) for entry in entries ], ) for note in notes ],
id = u"center_area", id = u"center_area",
), ),
), ),

View File

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

View File

@ -1,12 +1,12 @@
from Tags import Html, Head, Link, Script, Meta, Body from Tags import Html, Head, Link, Script, Meta, Body
class Entry_page( Html ): class Note_page( Html ):
def __init__( self, id ): def __init__( self, id ):
Html.__init__( Html.__init__(
self, self,
Head( 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/MochiKit.js" ),
Script( type = u"text/javascript", src = u"/static/js/Invoker.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" ), 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"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"&#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"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"&#8594", id = u"createLink", title = u"note 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"+", id = u"newNote", title = u"new note [ctrl-N]", class_ = u"button" ) ),
), ),
id = u"toolbar", id = u"toolbar",
class_ = u"undisplayed", # start out as hidden, and then shown in the browser if the current notebook is read-write class_ = u"undisplayed", # start out as hidden, and then shown in the browser if the current notebook is read-write