Code

. Modified cgi interface to change properties only once all changes are
authorrochecompaan <rochecompaan@57a73879-2fb5-44c3-a270-3262357dd7e2>
Sat, 15 Dec 2001 19:24:39 +0000 (19:24 +0000)
committerrochecompaan <rochecompaan@57a73879-2fb5-44c3-a270-3262357dd7e2>
Sat, 15 Dec 2001 19:24:39 +0000 (19:24 +0000)
   collected, files created and messages generated.
 . Moved generation of change note to nosyreactors.
 . We now check for changes to "assignedto" to ensure it's added to the
   nosy list.

git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@465 57a73879-2fb5-44c3-a270-3262357dd7e2

roundup/cgi_client.py
roundup/mailgw.py
roundup/roundupdb.py
roundup/templates/classic/detectors/nosyreaction.py
roundup/templates/extended/detectors/nosyreaction.py

index f4fa8d14e6fcfb015f176bbd596b360e9065157f..4e6d0754fae49de7cc63d4a3ef4f88ca6ccccc87 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: cgi_client.py,v 1.81 2001-12-12 23:55:00 richard Exp $
+# $Id: cgi_client.py,v 1.82 2001-12-15 19:24:39 rochecompaan Exp $
 
 __doc__ = """
 WWW request handler (also used in the stand-alone server).
@@ -314,32 +314,10 @@ class Client:
             try:
                 props, changed = parsePropsFromForm(self.db, cl, self.form,
                     self.nodeid)
-
-                # set status to chatting if 'unread' or 'resolved'
-                if not changed.has_key('status'):
-                    try:
-                        # determine the id of 'unread','resolved' and 'chatting'
-                        unread_id = self.db.status.lookup('unread')
-                        resolved_id = self.db.status.lookup('resolved')
-                        chatting_id = self.db.status.lookup('chatting')
-                    except KeyError:
-                        pass
-                    else:
-                        if (not props.has_key('status') or
-                                props['status'] == unread_id or
-                                props['status'] == resolved_id):
-                            props['status'] = chatting_id
-                            changed['status'] = chatting_id
-
-                # get the change note
-                change_note = cl.generateChangeNote(self.nodeid, changed)
-
-                # make the changes
-                cl.set(self.nodeid, **props)
-
-                # handle linked nodes and change message generation
-                self._post_editnode(self.nodeid, change_note)
-
+                # make changes to the node
+                self._changenode(props)
+                # handle linked nodes 
+                self._post_editnode(self.nodeid)
                 # and some nice feedback for the user
                 if changed:
                     message = _('%(changes)s edited ok')%{'changes':
@@ -455,37 +433,52 @@ class Client:
                 pass
             else:
                 props['status'] = unread_id
+        # add assignedto to the nosy list
+        if props.has_key('assignedto'):
+            assignedto_id = props['assignedto']
+            if props.has_key('nosy') and not assignedto_id in props['nosy']:
+                props['nosy'].append(assignedto_id)
+            else:
+                props['nosy'] = [assignedto_id]
+        # check for messages
+        message = self._handle_message()
+        if message:
+            props['messages'] = [message]
+        # create the node and return it's id
         return cl.create(**props)
 
-    def _post_editnode(self, nid, change_note=''):
-        ''' do the linking and message sending part of the node creation
+    def _changenode(self, props):
+        ''' change the node based on the contents of the form
         '''
-        cn = self.classname
-        cl = self.db.classes[cn]
-        # link if necessary
-        keys = self.form.keys()
-        for key in keys:
-            if key == ':multilink':
-                value = self.form[key].value
-                if type(value) != type([]): value = [value]
-                for value in value:
-                    designator, property = value.split(':')
-                    link, nodeid = roundupdb.splitDesignator(designator)
-                    link = self.db.classes[link]
-                    value = link.get(nodeid, property)
-                    value.append(nid)
-                    link.set(nodeid, **{property: value})
-            elif key == ':link':
-                value = self.form[key].value
-                if type(value) != type([]): value = [value]
-                for value in value:
-                    designator, property = value.split(':')
-                    link, nodeid = roundupdb.splitDesignator(designator)
-                    link = self.db.classes[link]
-                    link.set(nodeid, **{property: nid})
-
-        # handle file attachments
-        files = cl.get(nid, 'files')
+        cl = self.db.classes[self.classname]
+        # set status to chatting if 'unread' or 'resolved'
+        try:
+            # determine the id of 'unread','resolved' and 'chatting'
+            unread_id = self.db.status.lookup('unread')
+            resolved_id = self.db.status.lookup('resolved')
+            chatting_id = self.db.status.lookup('chatting')
+        except KeyError:
+            pass
+        else:
+            if (props['status'] == unread_id or props['status'] == resolved_id):
+                props['status'] = chatting_id
+        # add assignedto to the nosy list
+        if props.has_key('assignedto'):
+            assignedto_id = props['assignedto']
+            if not assignedto_id in props['nosy']:
+                props['nosy'].append(assignedto_id)
+        # create the message
+        message = self._handle_message()
+        if message:
+            props['messages'] = cl.get(self.nodeid, 'messages') + [message]
+        # make the changes
+        cl.set(self.nodeid, **props)
+
+    def _handle_message(self):
+        ''' generate and edit message '''
+
+        # handle file attachments 
+        files = []
         if self.form.has_key('__file'):
             file = self.form['__file']
             if file.filename:
@@ -495,14 +488,10 @@ class Client:
                 # create the new file entry
                 files.append(self.db.file.create(type=mime_type,
                     name=file.filename, content=file.file.read()))
-                # and save the reference
-                cl.set(nid, files=files)
-
-        #
-        # generate an edit message
-        #
 
         # we don't want to do a message if none of the following is true...
+        cn = self.classname
+        cl = self.db.classes[self.classname]
         props = cl.getprops()
         note = None
         if self.form.has_key('__note'):
@@ -513,7 +502,7 @@ class Client:
             return
         if not props['messages'].classname == 'msg':
             return
-        if not (len(cl.get(nid, 'nosy', [])) or note):
+        if not (self.form.has_key('nosy') or note):
             return
 
         # handle the note
@@ -528,10 +517,6 @@ class Client:
                 ' the web.\n')%{'classname': cn}
             m = [summary]
 
-        # append the change note
-        if change_note:
-            m.append(change_note)
-
         # now create the message
         content = '\n'.join(m)
         message_id = self.db.msg.create(author=self.getuid(),
@@ -539,9 +524,34 @@ class Client:
             content=content, files=files)
 
         # update the messages property
-        messages = cl.get(nid, 'messages')
-        messages.append(message_id)
-        cl.set(nid, messages=messages, files=files)
+        return message_id
+
+    def _post_editnode(self, nid):
+        ''' do the linking part of the node creation
+        '''
+        cn = self.classname
+        cl = self.db.classes[cn]
+        # link if necessary
+        keys = self.form.keys()
+        for key in keys:
+            if key == ':multilink':
+                value = self.form[key].value
+                if type(value) != type([]): value = [value]
+                for value in value:
+                    designator, property = value.split(':')
+                    link, nodeid = roundupdb.splitDesignator(designator)
+                    link = self.db.classes[link]
+                    value = link.get(nodeid, property)
+                    value.append(nid)
+                    link.set(nodeid, **{property: value})
+            elif key == ':link':
+                value = self.form[key].value
+                if type(value) != type([]): value = [value]
+                for value in value:
+                    designator, property = value.split(':')
+                    link, nodeid = roundupdb.splitDesignator(designator)
+                    link = self.db.classes[link]
+                    link.set(nodeid, **{property: nid})
 
     def newnode(self, message=None):
         ''' Add a new node to the database.
@@ -574,7 +584,7 @@ class Client:
             props = {}
             try:
                 nid = self._createnode()
-                # handle linked nodes and change message generation
+                # handle linked nodes 
                 self._post_editnode(nid)
                 # and some nice feedback for the user
                 message = _('%(classname)s created ok')%{'classname': cn}
@@ -1090,6 +1100,9 @@ def parsePropsFromForm(db, cl, form, nodeid=0):
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.81  2001/12/12 23:55:00  richard
+# Fixed some problems with user editing
+#
 # Revision 1.80  2001/12/12 23:27:14  richard
 # Added a Zope frontend for roundup.
 #
index 1f0a48ab6984585f1c4ef30bc690eb3eea7a8a25..0d6285eeb50370d6cc779b69f1ab121297580690 100644 (file)
@@ -73,7 +73,7 @@ are calling the create() method to create a new node). If an auditor raises
 an exception, the original message is bounced back to the sender with the
 explanatory message given in the exception. 
 
-$Id: mailgw.py,v 1.41 2001-12-10 00:57:38 richard Exp $
+$Id: mailgw.py,v 1.42 2001-12-15 19:24:39 rochecompaan Exp $
 '''
 
 
@@ -506,6 +506,7 @@ not find a text/plain part to use.
                 if n.has_key(nid): continue
                 n[nid] = 1
             props['nosy'] = n.keys()
+            # add assignedto to the nosy list
             try:
                 assignedto = self.db.user.lookup(props['assignedto'])
                 if assignedto not in props['nosy']:
@@ -513,9 +514,6 @@ not find a text/plain part to use.
             except:
                 pass
                 
-            change_note = cl.generateChangeNote(nodeid, props)
-            content += change_note
-            
             message_id = self.db.msg.create(author=author,
                 recipients=recipients, date=date.Date('.'), summary=summary,
                 content=content, files=files)
@@ -572,16 +570,21 @@ There was a problem with the message you sent:
                 if self.db.hasnode('user', value):
                     nid = value
                 else:
-                    try:
-                        nid = self.db.user.lookup(value)
-                    except:
-                        continue
+                    continue
                 if n.has_key(nid): continue
                 n[nid] = 1
             props['nosy'] = n.keys() + recipients
+            # add the author to the nosy list
             if not n.has_key(author):
                 props['nosy'].append(author)
                 n[author] = 1
+            # add assignedto to the nosy list
+            try:
+                assignedto = self.db.user.lookup(props['assignedto'])
+                if not n.has_key(assignedto):
+                    props['nosy'].append(assignedto)
+            except:
+                pass
 
             # and attempt to create the new node
             try:
@@ -620,21 +623,35 @@ def parseContent(content, blank_line=re.compile(r'[\r\n]+\s*[\r\n]+'),
         if not section:
             continue
         lines = eol.split(section)
-        if lines[0] and lines[0][0] in '>|':
-            continue
-        if len(lines) > 1 and lines[1] and lines[1][0] in '>|':
-            continue
         if not summary:
             summary = lines[0]
             l.append(section)
             continue
-        if signature.match(lines[0]):
-            break
+        # TODO: write better pattern for matching signature - it
+        # currently truncates messages with dashes in
+        #if signature.match(lines[0]):
+        #    break
         l.append(section)
     return summary, '\n\n'.join(l)
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.27  2001/12/15 06:51:04  roche
+# Merge with CVS
+#
+# Revision 1.1.1.11  2001/12/13 07:05:43  roche
+# update from cvs
+#
+# Revision 1.41  2001/12/10 00:57:38  richard
+# From CHANGES:
+#  . Added the "display" command to the admin tool - displays a node's values
+#  . #489760 ] [issue] only subject
+#  . fixed the doc/index.html to include the quoting in the mail alias.
+#
+# Also:
+#  . fixed roundup-admin so it works with transactions
+#  . disabled the back_anydbm module if anydbm tries to use dumbdbm
+#
 # Revision 1.40  2001/12/05 14:26:44  rochecompaan
 # Removed generation of change note from "sendmessage" in roundupdb.py.
 # The change note is now generated when the message is created.
index 609a626372544e1b5a55c7e9945e91831b48a102..6cb939a2b988665f5234c97c2eb1b29e47e0d70e 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: roundupdb.py,v 1.30 2001-12-12 21:47:45 richard Exp $
+# $Id: roundupdb.py,v 1.31 2001-12-15 19:24:39 rochecompaan Exp $
 
 __doc__ = """
 Extending hyperdb with types specific to issue-tracking.
@@ -268,7 +268,7 @@ class IssueClass(Class):
         appended to the "messages" field of the specified issue.
         """
 
-    def sendmessage(self, nodeid, msgid):
+    def sendmessage(self, nodeid, msgid, change_note):
         """Send a message to the members of an issue's nosy list.
 
         The message is sent only to users on the nosy list who are not
@@ -344,6 +344,10 @@ class IssueClass(Class):
         # add the content
         m.append(self.db.msg.get(msgid, 'content'))
 
+        # add the change note
+        if change_note:
+            m.append(change_note)
+
         # put in roundup's signature
         if self.EMAIL_SIGNATURE_POSITION == 'bottom':
             m.append(self.email_signature(nodeid, msgid))
@@ -416,7 +420,7 @@ class IssueClass(Class):
         line = '_' * max(len(web), len(email))
         return '%s\n%s\n%s\n%s'%(line, email, web, line)
 
-    def generateChangeNote(self, nodeid, newvalues):
+    def generateChangeNote(self, nodeid, oldvalues):
         """Generate a change note that lists property changes
         """
         cn = self.classname
@@ -425,26 +429,25 @@ class IssueClass(Class):
         props = cl.getprops(protected=0)
 
         # determine what changed
-        for key in newvalues.keys():
+        for key in oldvalues.keys():
             if key in ['files','messages']: continue
-            new_value = newvalues[key]
+            new_value = cl.get(nodeid, key)
             # the old value might be non existent
             try:
-                old_value = cl.get(nodeid, key)
-                if type(old_value) is type([]):
-                    old_value.sort()
+                old_value = oldvalues[key]
+                if type(new_value) is type([]):
                     new_value.sort()
-                if old_value != new_value:
-                    changed[key] = new_value
+                    old_value.sort()
+                if new_value != old_value:
+                    changed[key] = old_value
             except:
                 changed[key] = new_value
 
         # list the changes
         m = []
-        for propname, value in changed.items():
+        for propname, oldvalue in changed.items():
             prop = cl.properties[propname]
-            oldvalue = cl.get(nodeid, propname, None)
-            change = '%s -> %s'%(oldvalue, value)
+            value = cl.get(nodeid, propname, None)
             if isinstance(prop, hyperdb.Link):
                 link = self.db.classes[prop.classname]
                 key = link.labelprop(default_to_id=1)
@@ -484,6 +487,8 @@ class IssueClass(Class):
                         l.append(entry)
                 if l:
                     change += ' -%s'%(', '.join(l))
+            else:
+                change = '%s -> %s'%(oldvalue, value)
             m.append('%s: %s'%(propname, change))
         if m:
             m.insert(0, '----------')
@@ -492,6 +497,12 @@ class IssueClass(Class):
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.30  2001/12/12 21:47:45  richard
+#  . Message author's name appears in From: instead of roundup instance name
+#    (which still appears in the Reply-To:)
+#  . envelope-from is now set to the roundup-admin and not roundup itself so
+#    delivery reports aren't sent to roundup (thanks Patrick Ohly)
+#
 # Revision 1.29  2001/12/11 04:50:49  richard
 # fixed the order of the blank line and '-------' line
 #
index b81e587ce801a9913fcca7eac7a08a2b5822036f..1088aa09c4edee5b86950942f1acb1614a706b56 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-#$Id: nosyreaction.py,v 1.8 2001-12-05 14:26:44 rochecompaan Exp $
+#$Id: nosyreaction.py,v 1.9 2001-12-15 19:24:39 rochecompaan Exp $
 
 from roundup import roundupdb
 
@@ -35,6 +35,7 @@ def nosyreaction(db, cl, nodeid, oldvalues):
         then provides a log of when the message was sent to whom. 
     '''
     messages = []
+    change_note = ''
     if oldvalues is None:
         # the action was a create, so use all the messages in the create
         messages = cl.get(nodeid, 'messages')
@@ -48,13 +49,15 @@ def nosyreaction(db, cl, nodeid, oldvalues):
         for msgid in cl.get(nodeid, 'messages'):
             if not m.has_key(msgid):
                 messages.append(msgid)
+        if messages:
+            change_note = cl.generateChangeNote(nodeid, oldvalues)
     if not messages:
         return
 
     # send a copy to the nosy list
     for msgid in messages:
         try:
-            cl.sendmessage(nodeid, msgid)
+            cl.sendmessage(nodeid, msgid, change_note)
         except roundupdb.MessageSendError, message:
             raise roundupdb.DetectorError, message
 
@@ -63,15 +66,17 @@ def nosyreaction(db, cl, nodeid, oldvalues):
     n = {}
     for nosyid in nosy: n[nosyid] = 1
     change = 0
-    # but don't add admin or the anonymous user to the nosy list
+    # but don't add admin or the anonymous user to the nosy list and
+    # don't add the author if he just removed himself
     for msgid in messages:
+        authid = db.msg.get(msgid, 'author')
         for recipid in db.msg.get(msgid, 'recipients'):
             if recipid == '1': continue
             if n.has_key(recipid): continue
             if db.user.get(recipid, 'username') == 'anonymous': continue
+            if recipid == authid and not n.has_key(authid): continue
             change = 1
             nosy.append(recipid)
-        authid = db.msg.get(msgid, 'author')
         if authid == '1': continue
         if n.has_key(authid): continue
         if db.user.get(authid, 'username') == 'anonymous': continue
@@ -89,6 +94,10 @@ def init(db):
 
 #
 #$Log: not supported by cvs2svn $
+#Revision 1.8  2001/12/05 14:26:44  rochecompaan
+#Removed generation of change note from "sendmessage" in roundupdb.py.
+#The change note is now generated when the message is created.
+#
 #Revision 1.7  2001/11/30 11:29:04  rochecompaan
 #Property changes are now listed in emails generated by Roundup
 #
index 4643ed99a37eefba41cae70ae4164bb0425b9192..6dfe243189abfff4d23b09903c1e8d8364dc3525 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-#$Id: nosyreaction.py,v 1.8 2001-12-05 14:26:44 rochecompaan Exp $
+#$Id: nosyreaction.py,v 1.9 2001-12-15 19:24:39 rochecompaan Exp $
 
 from roundup import roundupdb
 
@@ -35,6 +35,7 @@ def nosyreaction(db, cl, nodeid, oldvalues):
         then provides a log of when the message was sent to whom. 
     '''
     messages = []
+    change_note = ''
     if oldvalues is None:
         # the action was a create, so use all the messages in the create
         messages = cl.get(nodeid, 'messages')
@@ -48,13 +49,15 @@ def nosyreaction(db, cl, nodeid, oldvalues):
         for msgid in cl.get(nodeid, 'messages'):
             if not m.has_key(msgid):
                 messages.append(msgid)
+        if messages:
+            change_note = cl.generateChangeNote(nodeid, oldvalues)
     if not messages:
         return
 
     # send a copy to the nosy list
     for msgid in messages:
         try:
-            cl.sendmessage(nodeid, msgid)
+            cl.sendmessage(nodeid, msgid, change_note)
         except roundupdb.MessageSendError, message:
             raise roundupdb.DetectorError, message
 
@@ -63,15 +66,17 @@ def nosyreaction(db, cl, nodeid, oldvalues):
     n = {}
     for nosyid in nosy: n[nosyid] = 1
     change = 0
-    # but don't add admin or the anonymous user to the nosy list
+    # but don't add admin or the anonymous user to the nosy list and
+    # don't add the author if he just removed himself
     for msgid in messages:
+        authid = db.msg.get(msgid, 'author')
         for recipid in db.msg.get(msgid, 'recipients'):
             if recipid == '1': continue
             if n.has_key(recipid): continue
             if db.user.get(recipid, 'username') == 'anonymous': continue
+            if recipid == authid and not n.has_key(authid): continue
             change = 1
             nosy.append(recipid)
-        authid = db.msg.get(msgid, 'author')
         if authid == '1': continue
         if n.has_key(authid): continue
         if db.user.get(authid, 'username') == 'anonymous': continue
@@ -89,6 +94,10 @@ def init(db):
 
 #
 #$Log: not supported by cvs2svn $
+#Revision 1.8  2001/12/05 14:26:44  rochecompaan
+#Removed generation of change note from "sendmessage" in roundupdb.py.
+#The change note is now generated when the message is created.
+#
 #Revision 1.7  2001/11/30 11:29:04  rochecompaan
 #Property changes are now listed in emails generated by Roundup
 #