The goal of the project is to develop and/or deploy new infrastructure for document editing in Melange. This infrastructure should provide revision control of the documents, displaying diffs between revisions, storing documents in HTML and markdown. MarkItUp! can be deployed as an optional editor.

Revision control architecture

Revision control implementation involves creation of three separate models: Revision, RevisionInfo and RevisionContent.

The main purposes of Revision are:

  1. Denote that derived model implements revision control.
  2. Store list of keys for RevisionInfo entities.
class Revision(soc.models.base.ModelWithFieldAttributes):
  revisions = db.ListProperty(db.Key, verbose_name = ugettext("Revisions"))

Revision can be added to the list of base classes of the model, as GAE supports multiple inheritence for models since 1.2.4.

RevisionInfo stores information about the revision. Revision number, author, date and time of creation, etc. All the meta goes here. RevisionInfo also contains reference to RevisionContent entity. Keys for the RevisionInfo entities may be implemented as "%s_%d" % (entity_key, revnumber). This helps to retrieve given revision without retrieving model entity. Division of info and content is crucial for revision control. Some operations on revisions manipulate only info, but not the content. One can consider view that shows all the revisions for the current entity.

class RevisionInfo(soc.models.base.ModelWithFieldAttributes):
  revnumber = db.IntegerProperty(required = True)
  author = db.ReferenceProperty(reference_class = soc.models.user.User, required = True)
  created = db.DateTimeProperty(auto_now_add = True)
  content = db.ReferenceProperty(reference_class = RevisionContent, required = True)

RevisionContent stores the content. Content can be stored as plain text, JSON or something else. Revision model may implement methods to store the content in different formats. This methods can be redefined in derived models.

class RevisionContent(soc.models.base.ModelWithFieldAttributes):
  content = db.TextProperty(verbose_name = ugettext("Content"))

Project timeline

Week 1 (24 May - 30 May)

  1. Dig into GAE datastore (read “Programming Google App Engine”, review google.appengine.ext.db, play with the datastore)
  2. Deploy test Melange instance to
  3. Familiarize myself with the code base

Week 2 (31 May - 6 June)

  1. Design revision control architecture
  2. Digg deep into soc.models, soc.logic, soc.views packages

Week 3 (7 June - 13 June)

  1. Implement Revision, RevisionInfo and RevisionContent
  2. Implement logic for Revision
  3. Refactor soc.views.models.base.View.create to support revision creation

Week 4 (14 June - 20 June)

  1. Refactor soc.views.models.base.View.edit to support revision
  2. Refactor Document model, logic and view to support revision control.

Week 5 (21 June - 27 June)

  1. Implement view to list all revisions, roll back and show diff.
  2. Fix bugs

Week 6 (28 June - 4 July)

  1. Start working on HTML diffs
  2. Try stuff from HtmlDiff

Week 7 (5 July - 11 July)

  1. Implement HTML diffs for RevisionContent
  2. Refactor views to show diffs between selected revisions

Week 8 (12 July - 18 July)

  1. Intensive testing of revision control and diffs
  2. Fix issues

Week 9 (19 July - 25 July)

  1. Refactor RevisionContent to store custom number of fields as JSON
  2. Refactor code to support new architecture
  3. Start implementing integrating RC with StudentProposal model

Week 10 (26 July - 1 August)

  1. Finish RC for StudentProposal

Week 11 (2 August - 8 August)

  1. Work on auto-saving feature
  2. Deploy some JS module to filter out changed form fields
  3. Implement backend to store temporary forms

Week 12 (9 August - 15 August)

  1. Finish work on auto-saving
  2. Testing and code clean-up