Howdy, chandler-dev@:

So, I'm getting ready to commit the first round of changes for edit/ update in the next day or two. This should cover the domain model changes for supporting "lastModified", and I’ve hooked up enough of the UI (e.g., by adding a field or two to the detail view) that you can tell edit state is being tracked.

Here's a high-level overview. It's perhaps a little long and heavy on using the code as illustration, but comments or suggestions are welcome. If you're a managerial type, there are some TODOs at the end, too.

1. In osaf.pim.items, there's now a Modification enumerated type that is used to say what the last change to a given ContentItem was:

class Modification(schema.Enumeration):
    """
    Enumeration of the types of modification that are part of
    the edit/update workflows (a.k.a. "Stamping Storyboards")
    """
    values = { "edited":100, "queued":200, "sent":300, "updated":400 }

2. The design requires some state to be associated with each item; for example, once an invitation has been sent, future sendings are actually called "updates". So, besides just storing the what the last modification, there's a set of flags that is used to maintain that history:

(added to ContentItem):

    lastModification = schema.One(
        Modification,
        doc="What the last modification was"
    )

    modifiedFlags = schema.Many(
        Modification,
        initialValue=set([]),
        description='Used to track the modification state of the item'
    )

3. I added the following method to ContentItem:

    def changeEditState(self, modType=Modification.edited, who=None,
                        when=None):

This does the job of updating the lastModified-related attributes, including modifiedFlags, as appropriate. (See #7 for how the UI ends up calling this).

4. There's a "byline" Calculated attribute on ContentItem; this is used to show a string like "Edited by me on 12/21/2006" in the detail view.

5. I added an "error" attribute (a schema.Text) that stores a string containing the last error associated with a given item. At the moment, it’s only used during mail delivery failures, but in theory it could be used for sharing problems, too.

6. I changed the mail delivery code to use ContentItem.changeEditState (); in particular, we set the edited state to queued when we first hand off your message to the twisted thread for delivery, and set the sent/updated/error attributes as appropriate when done.

7. Making sure the UI calls changeEditState() when the user makes changes was an interesting strategy. One option I tried, but seemed a little haphazard, was to find all the setattr() calls in the various AttributeEditor subclasses, and add calls to changeEditState(). I realized this would also lead to weirdness if, for example, you edited a recurring event, because there the proxy would delay the actual attribute change till the user had confirmed it, but the change to lastModified would have happened anyway.

So, for now I went via a different route, which was to retrofit the occurrence proxy to call changeEditState(), even for items that aren’t recurring events. There are probably a few cases where we are explicitly not using the proxy in the UI; it's on my list to seek out and find those, and deal with the case where we want to call changeEditState() but not have the recurring event dialog show up.

8. I reworked some of Bryan Stearns' code for the communication column icons a little. I left the code that figures out what icon to use in the osaf.views.main.summaryblocks, but I moved the calculation of the various bits that contribute to an item's "communication state" over to an Annotation in osaf.pim.mail:

class CommunicationStatus(schema.Annotation):
    schema.kindInfo(annotates=items.ContentItem)

# These flag bits govern the sort position of each communications state:
    # UPDATE      =         1
    # IN          =        1
    # OUT         =       1
    # DRAFT       =      1
    # QUEUED      =     1
    # SENT        =    1
    # NEEDS_REPLY =   1
    # READ        =  1
    # ERROR       = 1
    UPDATE, IN, OUT, DRAFT, QUEUED, SENT, NEEDS_REPLY, READ, ERROR = (
        1<<n for n in xrange(9)
    )

    @staticmethod
    def getItemCommState(itemOrUUID, view=None):
"""Given an item or a UUID, determine its communications status"""
        ...

attributes = ... # attributes that contribute toward Communication status

    status = schema.Calculated(
        schema.Integer,
        basedOn=tuple(t[0] for t in attributes),
        fget=lambda self: self.getItemCommState(self.itsItem),
doc="A 'bitfield' of (UPDATE, IN, OUT, DRAFT, ...) |'ed together"

9. The index used by the communication column now uses the above CommunicationStatus.status attribute (and knows the dependency on CommunicationStatus.attributes). Howvever, as Bryan originally designed it, this could be done via a method index and the getItemCommState method.

10. In the detail view, I added fields to show the byline and error string (if any), and changed the "from" field to be a "send as" for outgoing messages. As I'm a domain-model troglodyte lacking in high- level UI sensibilities, these probably need some tweaking w.r.t positioning, fonts and all that fun stuff.

TODO:
=====

- Add support for lastModifiedBy. (Currently, this value is always None, which means it's treated as being by the user). Mainly, I/we need to decide on using Contact vs EmailAddress here.

- Review the various CommunicationStatus states, to make sure they match the design spec.

- Look into how all this works (or doesn't!) with recurring events.

- Currently, there's an SMTPDeliveryStatus class in the mail code that tracks DRAFT/QUEUED/SENT/ERROR state. Look into unifying this with the enumerated type above, or for moving the communication- related Modification values into the mail module somehow. If I knew how to do this cleanly, I probably would have done it already, so suggestions are welcome :).

- Add support for a 'created' Modification type. Currently, if you create a new item, it shows up as "Created by me ...". Then, as soon as you change something, it says "Edited by me ...". As a nice to have (IIRC), the design called for it remaining "Created" in this case, until you switch focus to a different item in the detail view. I had a first cut at doing this, but it turns out it depends on some changes I’m making in the recurrence branch.

- UI polish/review detail view changes with Reid/Bryan.

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

Open Source Applications Foundation "chandler-dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/chandler-dev

Reply via email to