changeset 60:dc41deabc8f8

more work on projects. more cleanup.
author casties
date Thu, 02 May 2013 11:26:57 +0200
parents d452fff7c52e
children 04fb655633ef
files MPIWGProjects.py MPIWGProjects_removed.py MPIWGRoot.py MPIWGRoot_deleted_methods.py zpt/project/edit_basic.zpt zpt/project/edit_images.zpt zpt/project/edit_publications.zpt zpt/project/edit_related_projects.zpt zpt/project/edit_template.zpt
diffstat 9 files changed, 326 insertions(+), 387 deletions(-) [+]
line wrap: on
line diff
--- a/MPIWGProjects.py	Thu May 02 10:14:52 2013 +0200
+++ b/MPIWGProjects.py	Thu May 02 11:26:57 2013 +0200
@@ -201,6 +201,7 @@
     """publications object fuer project"""
 
     meta_type = "MPIWGProject_relatedProject"
+    
     def redirect(self, RESPONSE, url):
         """mache ein redirect mit einem angehaengten time stamp um ein reload zu erzwingen"""
         
@@ -215,6 +216,11 @@
         logging.debug(email.Utils.formatdate() + ' GMT')
         RESPONSE.redirect(url + addStr % timeStamp)
 
+    
+    def getProjectTitle(self):
+        """Return the title of the related project."""
+        return getattr(self, 'projectWEB_title', None)
+    
         
     def editRelatedProject(self, link=None, RESPONSE=None):
         """edit a publication"""
@@ -254,7 +260,7 @@
 
     def showImage(self, imageUrl=None):
         """show Images at an extra page"""
-        self.getContent('WEB_project_description', filter='yes')  # get the content and store image infos into session
+        #self.getContent('WEB_project_description', filter='yes')  # get the content and store image infos into session
         pt = PageTemplateFile(os.path.join(package_home(globals()), 'zpt', 'projectImageView.zpt')).__of__(self)
         return pt()
     
@@ -307,7 +313,9 @@
     edit_basic = PageTemplateFile('zpt/project/edit_basic', globals())
     editForm = PageTemplateFile('zpt/project/edit_description', globals())
     edit_template = PageTemplateFile('zpt/project/edit_template', globals())
-    edit_related_projects = PageTemplateFile('zpt/project/edit_related_projects', globals())
+    editRelatedProjectsForm = PageTemplateFile('zpt/project/edit_related_projects', globals())
+    editImagesForm = PageTemplateFile('zpt/project/edit_images', globals())    
+    editPublicationsForm = PageTemplateFile('zpt/project/edit_publications', globals())
     # management templates
     loadNewFileForm = PageTemplateFile('zpt/project/manage_newfile', globals())
     description_only_html = PageTemplateFile('zpt/project/description_only_html', globals())
@@ -360,6 +368,21 @@
         RESPONSE.redirect(url + addStr % timeStamp)
 
 
+    def getDefinedFields(self):
+        """show all defined fields."""
+        return definedFields
+
+
+    def getFieldLabels(self):
+        """Return the field labels dict."""
+        return fieldLabels
+    
+
+    def getEditableFields(self):
+        """giveListofDatafields"""
+        return editableFields
+    
+
     def getNumber(self):
         """returns sorting number"""
         n = getattr(self, 'xdata_05', None)
@@ -561,97 +584,55 @@
             return t
 
               
+    def moveObjectPlace(self, objectList, objectId, direction):
+        """Move object with objectId from objectList in direction 
+        by changing its place attribute."""
+        if not objectId or not direction:
+            return
+
+        for idx in range(len(objectList)):
+            object = objectList[idx]
+            if object.getId() == objectId():
+                if direction == 'up':
+                    if idx > 0:
+                        # move up
+                        objectList[idx -1].place += 1
+                        objectList[idx].place -= 1
+                        
+                elif direction == 'down':
+                    if idx < len(objectList) - 1:
+                        # move down
+                        objectList[idx + 1].place -= 1
+                        objectList[idx].place += 1
+                        
+                return
+                      
     def manageImages(self, imageName=None, op=None):
-        """managage images"""
-        if imageName and op:
-            if op == 'up':
-                images = self.getImages()
-                for image in images:
-                    if image[0] == imageName:
-                        nr = images.index(image)
-                        if not nr == 0:
-                            images[nr - 1][1].place += 1
-                            images[nr][1].place -= 1
-                        pass
-            elif op == 'down':
-                images = self.getImages()
-                for image in images:
-                    if image[0] == imageName:
-                        nr = images.index(image)
-                        if not (nr == len(images) - 1):
-                            images[nr + 1][1].place -= 1
-                            images[nr][1].place += 1
-                        pass
-
-
+        """manage images"""
+        self.moveObjectPlace(self.getImageList(), imageName, op)
+ 
         # invalidate thumbnail
         self.projectThumb = None
-        pt = PageTemplateFile('zpt/project/edit_images', globals()).__of__(self)
+        
+        pt = self.editImagesForm
         return pt()
 
-    def managePublications(self, pubName=None, op=None):
-        """managage images"""
-        if pubName and op:
-            if op == 'up':
-                publications = self.getPublications()
-                for publication in publications:
-                    if publication[0] == pubName:
-                        nr = publications.index(publication)
-                        if not nr == 0:
-                            publications[nr - 1][1].place += 1
-                            publications[nr][1].place -= 1
-                        pass
-            elif op == 'down':
-                publications = self.getPublications()
-                for publication in publications:
-                    if publication[0] == pubName:
-                        nr = publications.index(publication)
-                        if not (nr == len(publications) - 1):
-                            publications[nr + 1][1].place -= 1
-                            publications[nr][1].place += 1
-                        pass
+
+    def managePublications(self, name=None, op=None):
+        """manage publications"""
+        self.moveObjectPlace(self.getRelatedPublications(), name, op)
 
-
-        pt = PageTemplateFile('zpt/project/edit_publications', globals()).__of__(self)
+        pt = self.editPublicationsForm
         return pt()
+
     
-    def manageRelatedProjects(self, pubName=None, op=None):
+    def manageRelatedProjects(self, name=None, op=None):
         """manage related projects"""
-        if pubName and op:
-            if op == 'up':
-                relatedProjects = self.getRelatedProjects()
-                for project in relatedProjects:
-                    if project[0] == pubName:
-                        nr = relatedProjects.index(project)
-                        if not nr == 0:
-                            relatedProjects[nr - 1][1].place += 1
-                            relatedProjects[nr][1].place -= 1
-                        pass
-            elif op == 'down':
-                relatedProjects = self.getRelatedProjects()
-                for project in relatedProjects:
-                    if project[0] == pubName:
-                        nr = relatedProjects.index(project)
-                        if not (nr == len(relatedProjects) - 1):
-                            relatedProjects[nr + 1][1].place -= 1
-                            relatedProjects[nr][1].place += 1
-                        pass
+        self.moveObjectPlace(self.getRelatedProjects(), name, op)
 
-
-        pt = self.edit_related_projects
-        return pt()
-    
-
+        pt = self.editRelatedProjectsForm
+        return pt()    
 
-    def getPublications(self):
-        """get all Publications"""
-        def sort_images(x, y):
-            return cmp(getattr(x[1], 'place', 0), getattr(y[1], 'place', 0))
-
-        publications = self.ZopeFind(self, obj_metatypes=['MPIWGProject_publication'])
-        
-        publications.sort(sort_images)
-        return publications
 
     def addPublication(self, text, RESPONSE=None):
         """add an MPIWG_Publication"""
@@ -669,18 +650,18 @@
         obj.enabled = True;
         obj.place = self.getLastPublicationNumber() + 1
         obj.id = name
-        self.ZCacheable_invalidate()
         if RESPONSE is not None:
-        
             self.redirect(RESPONSE, 'managePublications')
 
+
     def errorRelatedProjects(self, link):
         """error creating a related project"""
         pt = PageTemplateFile(os.path.join(package_home(globals()), 'zpt', 'edit_project_error_relatedProject.zpt')).__of__(self)
         return pt(link=link)
 
+
     def addRelatedProject(self, link, RESPONSE=None):
-        """add an MPIWG_Publication"""
+        """add a MPIWGProject_relatedProject"""
         number = self.getLastPublicationNumber() + 1
         name = "RelatedProject" + str(number)
         while hasattr(self, name):
@@ -708,7 +689,7 @@
         obj.orginallink = link[0:]
         obj.objid = objid[0:]
         logging.debug("add relobj:objid" + repr(obj.objid))
-        obj.projectWEB_title = object.getContent('WEB_title')[0:]
+        obj.projectWEB_title = object.getProjectTitle()
         logging.debug("add relobj:webtitle" + repr(obj.projectWEB_title))
         obj.enabled = True;
         obj.place = self.getLastRelatedProjectNumber() + 1
@@ -719,63 +700,35 @@
 
      
     def getLastPublicationNumber(self):
-        publications = self.getPublications()
-       
+        publications = self.getRelatedPublications()
         if not publications:
             return 0
         else:
-            return getattr(publications[-1][1], 'place', 0)
+            return getattr(publications[-1], 'place', 0)
+
         
     def getLastRelatedProjectNumber(self):
         publications = self.getRelatedProjects()
-        
         if not publications:
             return 0
         else:
-            return getattr(publications[-1][1], 'place', 0)
+            return getattr(publications[-1], 'place', 0)
+
         
     def deletePublication(self, id, RESPONSE=None):
             """delete Publication id"""
             self.manage_delObjects([id])
-            self.ZCacheable_invalidate()
             if RESPONSE:
                 self.redirect(RESPONSE, 'managePublications')
+
               
     def deleteRelatedProject(self, id, RESPONSE=None):
             """delete Publication id"""
             self.manage_delObjects([id])
-            self.ZCacheable_invalidate()
             if RESPONSE:
                 self.redirect(RESPONSE, 'manageRelatedProjects')
 
-    def getImages(self):
-        """get all Images"""
 
-        def sort_images(x, y):
-            return cmp(getattr(x[1], 'place', 0), getattr(y[1], 'place', 0))
-
-
-        if (getattr(self, 'imageURL', '') != '') or  (getattr(self, 'imagecap', '') != '')  :
-            try:
-                self.addImage(None, getattr(self, 'imagecap', ''), RESPONSE=None, filename=getattr(self, 'imageURL', ''))
-            except:
-                pass
-            self.imageURL = ''
-            self.imagecap = ''
-
-        images = self.ZopeFind(self, obj_metatypes=['MPIWGProject_image'])
-        
-        images.sort(sort_images)
-        return images
-
-    def getLastImageNumber(self):
-        images = self.getImages()
-        
-        if not images:
-            return 0
-        else:
-            return getattr(images[-1][1], 'place', 0)
-        
     def deleteImage(self, id, RESPONSE=None):
         """delete Image id"""
         try:
@@ -789,7 +742,6 @@
         if RESPONSE:
             self.redirect(RESPONSE, 'manageImages')
 
-
  
     def addImage(self, fileHd, caption, RESPONSE=None, filename=None):
         """add an MPIWG_Project_image"""
@@ -816,11 +768,6 @@
             self.redirect(RESPONSE, 'manageImages')
 
 
-    def getEditableFields(self):
-        """giveListofDatafields"""
-        return editableFields
-    
-
     def getActualVersion(self, date=None):
         """actuelle version"""
         def sortProjectsByTime(x, y):
@@ -885,18 +832,22 @@
         logging.info("copytoarchive 6")
         obj.manage_delObjects(ids)
         logging.info("copytoarchive 7")
+
         
     def setArchiveTime(self, time):
         """set Archive Time"""
         self.archiveTime = time[0:]
+
         
     def delArchiveTime(self):
         """delete archive time"""
         del self.archiveTime
+
    
     def isActiveProject(self):
         """check if the project is still active, default is true."""
         return getattr(self, 'isActiveFlag', True)
+
  
     def checkActive(self, active):
         """returns if the project state matches the active state.
@@ -906,6 +857,7 @@
         """
         act = getattr(self, 'isActiveFlag', True)
         return (active == 1 and act) or (active == 0) or (active == 2 and not act)
+
  
     def isArchivedProject(self):
         """check if the project is archived"""
@@ -917,6 +869,7 @@
             return False;
         
         return True
+
         
     def checkArchived(self, archived):
         """returns if the project state matches the archived state.
@@ -926,10 +879,12 @@
         """
         arch = self.isArchivedProject()
         return (archived == 1 and not arch) or (archived == 0) or (archived == 2 and arch)        
+
         
     def setActiveFlag(self, status=True):
         """set the active flag"""
         self.isActiveFlag = status
+
         
     def setCompletedAt(self, date):
         """set the date of completion, date should be in the form DD.MM.YYYY or MM.YYYY or YYYY"""
@@ -1041,7 +996,6 @@
             else:
                 return self.REQUEST['URL1'] + "/no_project"
 
-
         else:
             finds.sort(sortProjectsByTime)
 
@@ -1053,116 +1007,12 @@
         # kein passendes gefunden, dann teste ob das aktuelle in frage kommt
         ad = getattr(self, 'creationTime', '20050101000000')
         
-        if int(date) > int(ad):
-        
+        if int(date) > int(ad):        
             return self.REQUEST['URL1'] + "/" + self.getId()
         else:
             return self.REQUEST['URL1'] + "/no_project"
-        
-            
-            
-    def getDefinedFields(self):
-        """show all defined fields"""
-        return definedFields
-
-    def getAttribute(self, field):
-        """get attrbiute"""
-        return getattr(self, field)
-
-    def getContent(self, field, filter=None):
-        """Inhalt des Feldes"""
-        # logging.debug("getContent field=%s filter=%s"%(field,filter))
-        
-        if field == "short_title":
-                text = self.getContent("xdata_07")
-                if text == "":
-                        text = self.getContent("WEB_title")
-                return text
-
-        text = u''
-
-        f = getattr(self, field)
-        if isinstance(f, list):
-            # compat with old lists
-            for x in f:
-                try:
-                    text += x
-                except:
-                    text = x
-        else:
-            text = f
-
-        try:
-            if text[len(text) - 1] == ";":
-                text = text[0:len(text) - 1]
-                
-        except:
-            pass
-        
-        if text == '':  # # wozu die folgenden Zeilen??
-            text2 = text
-        else:
-            text2 = re.sub(r';([^\s])', '; \g<1>', text)
-       
-        if field == "WEB_project_description":  # #Jedenfalls darf letzteres nicht gemacht werden, falls normaler text
-            text2 = text
+                    
             
-        # teste ob ergebnis leer und header dann nehme title
-        
-        if (text2 == '') and (field == 'WEB_project_header'):
-            return self.getContent('WEB_title')
-
-        if filter:
-            splitted = text2.split("""<p class="picture">""")
-            if len(splitted) > 1:
-                tmp = splitted[1].split("</p>")
-                # return repr(splitted[1])
-                try:
-                        self.imageURL = tmp[0].split("\"")[1].encode('utf-8')
-                except:
-                    try:
-                        self.imageURL = tmp[0].split("src=")[1].split(" ")[0].encode('utf-8')
-                    except:
-                        self.imageURL = ""
-
-                split2 = "</p>".join(tmp[1:])
-
-                text3 = splitted[0] + split2
-
-                splitted = text3.split("""<p class="picturetitle">""")
-                if len(splitted) > 1:
-                    tmp = splitted[1].split("</p>")
-                    self.imagecap = tmp[0].encode('utf-8')
-                
-                    split4 = "".join(tmp[1:])
-
-                    text5 = splitted[0] + split4
-                else:
-                    # keine caption
-                    text5 = text3
-            else:
-                # kein bild
-                text5 = text2
-        else:
-            text5 = text2
-
-        # teste ob WEB_project_description und keine fuehrenden p tags
-        if (len(text5) > 4) and (not text5[0:3] == '<p>') and (field == 'WEB_project_description'):
-            text5 = "<p>" + text5 + "</p>"
-
-
-        # filter image
-        
-        text5 = text5.lstrip().rstrip()  # loescher leerzeichen und einzelndes br
-        if (text5 == "<br>") or (text5 == "<br/>"):
-            text5 = ""
-
-        # logging.debug("getcontent: field=%s filter=%s -> %s"%(field,filter,repr(text5)))
-        return unicodify(text5)
-        # return utf8ify(text5) # return as utf-8 byte string
-
-
-
     def saveFromPreview(self):
         """save content aus preview"""
         self.WEB_project_description = self.previewTemplate.WEB_project_description[0:]
@@ -1190,6 +1040,7 @@
         
         return True
 
+
     security.declareProtected('View management screens', 'edit')
     def edit(self, western=None):
         """Edit pages"""
@@ -1255,8 +1106,10 @@
 
     def isResponsibleScientist(self, key):
         """teste ob eine Person in der Liste der respl. scientists auftaucht"""
+        #key = utf8ify(key)
         for resp in self.getResponsibleScientistsList():
-            if resp.get('key', None) == utf8ify(key):
+            logging.debug("resp=%s key=%s"%(repr(resp),repr(key)))
+            if resp.get('key', '').lower() == key.lower():
                 return True
         
         return False
@@ -1376,9 +1229,8 @@
         if fromEdit and (RESPONSE is not None):
             return self.editBasic()
             
-        else:
-            if RESPONSE is not None:
-                RESPONSE.redirect('manage_main')
+        if RESPONSE is not None:
+            RESPONSE.redirect('manage_main')
 
 
     security.declareProtected('View management screens', 'editBasic')
@@ -1392,6 +1244,14 @@
         return pt(identifiedNames=identifiedNames)
 
 
+    def getContent(self, field, filter=None):
+        """Inhalt des Feldes"""
+        val = getattr(self, field, '')
+        if isinstance(val, list):
+            val = val[0]
+            
+        return val
+
 
     def loadNewFile(self, RESPONSE=None):
         """einlesen des neuen files"""
@@ -1416,6 +1276,7 @@
         if RESPONSE is not None:
             RESPONSE.redirect('manage_main')
 
+
     def tagTheProject(self, RESPONSE=None):
         """TAG"""
         id = self.getId();
@@ -1439,8 +1300,7 @@
         
         if(len(publications) > 0):
             ret = False;  # es gibt publicationen in der neuen liste
-      
-        
+              
         logging.debug("len(publ)" + repr(ret))
         
         return ret;
@@ -1448,7 +1308,9 @@
 
     def copyPublicationsToList(self, RESPONSE=None):
         """copy publications in to list"""
-        publicationTxt = self.getRelatedPublications()
+        publicationTxt = getattr(self, 'WEB_related_pub', '')
+        if isinstance(publicationTxt, list):
+            publicationTxt = publicationTxt[0]
 
         pubSplits = publicationTxt.split("<p>")
 
@@ -1459,7 +1321,6 @@
         setattr(self, "WEB_related_pub_copied", True);
         
         if RESPONSE:
-                
             self.redirect(RESPONSE, 'managePublications')
         
 
@@ -1563,41 +1424,21 @@
 
 
     def updateProjectMembers(self, updateResponsibleScientistsList=False):
-        """updates project-member table"""
-        if updateResponsibleScientistsList:
-            # create responsibleScientistsList automatically
-            newScientists = {}
-            names = p.identifyNames(p.getResponsibleScientists())
-            for name in names:
-                logging.debug("updateAllProjectMembers: name=%s" % repr(name))
-                members = names[name]
-                if len(members) > 0:
-                    # take the first matching name
-                    newScientists[name] = {'name': name, 'key' : members[0].key, 'username' : re.sub('@mpiwg-berlin\.mpg\.de', '', members[0].e_mail)}
-                
-            self.setResponsibleScientistsList(newScientists)
-            
-        memberlist = self.getResponsibleScientistsList()
-           
+        """Update project-member table."""
+        # projects are identified by id
+        pid = self.getId()
+
         # clear projects_members table
-        pNum = self.getNumber()
-        if not pNum or not isinstance(pNum, basestring):
-            logging.error("updateProjectMembers: not a valid project number: %s" % repr(pNum))
-            return
+        self.executeZSQL("delete from projects_members where project_id = %s", [pid])
 
-        if len(memberlist) == 0:
-            return
-         
-        # fill projects_members table
-        self.executeZSQL("delete from projects_members where project_number = %s", [pNum])
-        for m in memberlist:
+        for m in self.getResponsibleScientistsList():
             memberKey = m.get('key', None)
             if not memberKey or not isinstance(memberKey, basestring):
                 logging.error("updateProjectMembers: not a valid member key: %s" % repr(memberKey))
                 continue
                         
-            self.executeZSQL("insert into projects_members (project_number, member_key) values (%s, %s)", (pNum, memberKey))
-
+            # fill projects_members table
+            self.executeZSQL("insert into projects_members (project_id, member_key) values (%s, %s)", (pid, memberKey))
     
     
     def addPublicationsFromPubman(self,REQUEST):
@@ -1691,38 +1532,29 @@
             logging.error(escidocid)
             logging.error(value)
         
+
     def getSelectedPublications(self):
         """hole publications aus der datenbank"""
-    
-    
         query="select * from pubmanbiblio_projects where lower(key_main) = lower(%s) order by priority DESC"
-            
-           
         return self.executeZSQL(query,[self.getId()])
- 
-     
+
         
     def hasExtendedPublicationList(self):
         """test if extended publication list exists"""
-        
-    
-    
         query="select count(*) from pubmanbiblio_projects where lower(key_main) = lower(%s)"
-            
-           
         res= self.executeZSQL(query,[self.getId()])
         
         if res[0].count>0:
             return True
         else:
             return False
+
         
     def publicationsFull(self,REQUEST):
         """show publication"""
         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt/project/pubman','show_publications.zpt')).__of__(self)
         return pt()
         
-
         
 def manage_addMPIWGProjectForm(self):
     """form for adding the project"""
@@ -1746,7 +1578,6 @@
         newObj = MPIWGProject(id)
 
     self._setObject(id, newObj)
-
     
     if RESPONSE is not None:
         RESPONSE.redirect('manage_main')
@@ -1760,9 +1591,6 @@
     
     # cached HashTree with project hierarchy
     _v_projectTree = None
-
-    
-   
                     
     def getProjectTree(self):
         """Return the project hierarchy tree (and cache it).
@@ -1908,7 +1736,7 @@
             RESPONSE.redirect(self.en.MPIWGrootURL()+'/admin/showTree')
 
 
-    # TODO: it's broken. is this used?
+    # TODO: this is broken. is this used?
     def getAllProjectsAndTagsAsCSV(self,archived=1,RESPONSE=None):
         """alle projekte auch die nicht getaggten"""
         retList=[]
@@ -1948,7 +1776,6 @@
       
         return "\n".join(retList);
     
-    
         
     security.declareProtected('View management screens', 'updateAllProjectMembers')
     def updateAllProjectMembers(self, updateResponsibleScientistsList=False):
@@ -1984,30 +1811,46 @@
                 project.copyPublicationsToList()
                                 
             #
-            # old format responsibleScientistsList
+            # create responsibleScientistsList automatically
             #
-            memberlist = project.getResponsibleScientistsList()
-            if len(memberlist) > 0 and isinstance(memberlist[0], tuple):
-                log += "%s: updating memberlist!\n"%project.getId()
-                logging.debug("updateAllProjects(%s): updating memberlist" % project.getId())
+            if updateResponsibleScientistsList:
                 newScientists = {}
-                for m in memberlist:
-                    name = m[0]
-                    key = m[1] 
-                    username = None
-                    if key:
-                        if isinstance(key, list):
-                            key = key[0]
-                            
-                        # get username from db
-                        member = self.getMPIWGRoot().getStaffFolder().getMember(key=key)
-                        if member is not None:
-                            username = member.getUsername()
-                            
-                    newScientists[name] = {'name': name, 'key' : key, 'username' : username}
+                names = project.identifyNames(p.getResponsibleScientists())
+                for name in names:
+                    logging.debug("updateAllProjectMembers: name=%s" % repr(name))
+                    members = names[name]
+                    if len(members) > 0:
+                        # take the first matching name
+                        newScientists[name] = {'name': name, 'key' : members[0].key, 'username' : re.sub('@mpiwg-berlin\.mpg\.de', '', members[0].e_mail)}
                     
-                # set new list
                 project.setResponsibleScientistsList(newScientists)
+                
+            else:
+                #
+                # old format responsibleScientistsList
+                #
+                memberlist = project.getResponsibleScientistsList()
+                if len(memberlist) > 0 and isinstance(memberlist[0], tuple):
+                    log += "%s: updating memberlist!\n"%project.getId()
+                    logging.debug("updateAllProjects(%s): updating memberlist" % project.getId())
+                    newScientists = {}
+                    for m in memberlist:
+                        name = m[0]
+                        key = m[1] 
+                        username = None
+                        if key:
+                            if isinstance(key, list):
+                                key = key[0]
+                                
+                            # get username from db
+                            member = self.getMPIWGRoot().getStaffFolder().getMember(key=key)
+                            if member is not None:
+                                username = member.getUsername()
+                                
+                        newScientists[name] = {'name': name, 'key' : key, 'username' : username}
+                        
+                    # set new list
+                    project.setResponsibleScientistsList(newScientists)
 
             #
             # old inline images
--- a/MPIWGProjects_removed.py	Thu May 02 10:14:52 2013 +0200
+++ b/MPIWGProjects_removed.py	Thu May 02 11:26:57 2013 +0200
@@ -249,4 +249,98 @@
             return self        
 
 
+    def getContent(self, field, filter=None):
+        """Inhalt des Feldes"""
+        # logging.debug("getContent field=%s filter=%s"%(field,filter))
+        
+        if field == "short_title":
+                text = self.getContent("xdata_07")
+                if text == "":
+                        text = self.getContent("WEB_title")
+                return text
 
+        text = u''
+
+        f = getattr(self, field)
+        if isinstance(f, list):
+            # compat with old lists
+            for x in f:
+                try:
+                    text += x
+                except:
+                    text = x
+        else:
+            text = f
+
+        try:
+            if text[len(text) - 1] == ";":
+                text = text[0:len(text) - 1]
+                
+        except:
+            pass
+        
+        if text == '':  # # wozu die folgenden Zeilen??
+            text2 = text
+        else:
+            text2 = re.sub(r';([^\s])', '; \g<1>', text)
+       
+        if field == "WEB_project_description":  # #Jedenfalls darf letzteres nicht gemacht werden, falls normaler text
+            text2 = text
+            
+        # teste ob ergebnis leer und header dann nehme title
+        
+        if (text2 == '') and (field == 'WEB_project_header'):
+            return self.getContent('WEB_title')
+
+        if filter:
+            splitted = text2.split("""<p class="picture">""")
+            if len(splitted) > 1:
+                tmp = splitted[1].split("</p>")
+                # return repr(splitted[1])
+                try:
+                        self.imageURL = tmp[0].split("\"")[1].encode('utf-8')
+                except:
+                    try:
+                        self.imageURL = tmp[0].split("src=")[1].split(" ")[0].encode('utf-8')
+                    except:
+                        self.imageURL = ""
+
+                split2 = "</p>".join(tmp[1:])
+
+                text3 = splitted[0] + split2
+
+                splitted = text3.split("""<p class="picturetitle">""")
+                if len(splitted) > 1:
+                    tmp = splitted[1].split("</p>")
+                    self.imagecap = tmp[0].encode('utf-8')
+                
+                    split4 = "".join(tmp[1:])
+
+                    text5 = splitted[0] + split4
+                else:
+                    # keine caption
+                    text5 = text3
+            else:
+                # kein bild
+                text5 = text2
+        else:
+            text5 = text2
+
+        # teste ob WEB_project_description und keine fuehrenden p tags
+        if (len(text5) > 4) and (not text5[0:3] == '<p>') and (field == 'WEB_project_description'):
+            text5 = "<p>" + text5 + "</p>"
+
+
+        # filter image
+        
+        text5 = text5.lstrip().rstrip()  # loescher leerzeichen und einzelndes br
+        if (text5 == "<br>") or (text5 == "<br/>"):
+            text5 = ""
+
+        # logging.debug("getcontent: field=%s filter=%s -> %s"%(field,filter,repr(text5)))
+        return unicodify(text5)
+        # return utf8ify(text5) # return as utf-8 byte string
+
+
+
+
--- a/MPIWGRoot.py	Thu May 02 10:14:52 2013 +0200
+++ b/MPIWGRoot.py	Thu May 02 11:26:57 2013 +0200
@@ -52,25 +52,6 @@
         #{'label':'Edit Historical Persons','action':'editHistoricalPersonsForm'},
         #{'label':'Store Historical Persons','action':'storeHistoricalPersons'},
         )
-
-    # TODO: is this used here?
-    fieldLabels={'WEB_title':'WEB_Title',
-                 'xdata_01':'Responsible Scientists',
-                 'xdata_02':'Department',
-                 'xdata_03':'Historical Persons',
-                 'xdata_04':'Time period',
-                 'xdata_05':'Sorting number',
-                 'xdata_06':'Keywords',
-                 'xdata_07':'Short title',
-                 'xdata_08':'Other involved scholars' ,
-                 'xdata_09':'Disciplines',
-                 'xdata_10':'Themes',
-                 'xdata_11':'Object Digitallibrary',
-                 'xdata_12':'Cooperation partners',
-                 'xdata_13':'Funding institutions',
-                 'WEB_project_header':'WEB_project_header',
-                 'WEB_project_description':'WEB_project_description',
-                 'WEB_related_pub':'WEB_related_pub'}
     
     # (is this used?)
     folders=['MPIWGProject','Folder','ECHO_Navigation']
--- a/MPIWGRoot_deleted_methods.py	Thu May 02 10:14:52 2013 +0200
+++ b/MPIWGRoot_deleted_methods.py	Thu May 02 11:26:57 2013 +0200
@@ -848,5 +848,9 @@
      
         return ret
 
+    def getAttribute(self, field):
+        """get attrbiute"""
+        return getattr(self, field)
+
 
       
--- a/zpt/project/edit_basic.zpt	Thu May 02 10:14:52 2013 +0200
+++ b/zpt/project/edit_basic.zpt	Thu May 02 11:26:57 2013 +0200
@@ -15,7 +15,7 @@
         </tr>
         <tal:block tal:repeat="field here/getEditableFields">
           <tr>
-            <td><b tal:content="python:here.fieldLabels[field]" /></td>
+            <td><b tal:content="python:here.getFieldLabels()[field]" /></td>
             <td><input tal:attributes="name field; value python:here.getContent(field)" size=80 /></td>
           </tr>
         </tal:block>
@@ -29,7 +29,7 @@
             <td tal:condition="python:here.isActiveProject()"><input tal:attributes="name python:'active'" value="true" checked
               type="checkbox"></td>
             <td tal:condition="not:python:here.isActiveProject()"><input tal:attributes="name python:'active'" value="true"
-              type="checkbox"> <tal:x tal:condition="python:hasChildren">
+              type="checkbox"> <tal:x tal:condition="hasChildren">
 			 	 WARNING: This project is not visible, but has visible children.
 			</tal:x></td>
           </tal:x>
@@ -58,7 +58,7 @@
         <tr tal:repeat="identifiedName python:options.get('identifiedNames',{}).items()">
           <tal:x tal:define="global count python:count+1" />
           <td><input type="hidden"
-            tal:attributes="value python:here.decode(identifiedName[0]); name python:'responsibleScientist_name_%s'%count" /> <span
+            tal:attributes="value python:identifiedName[0]; name python:'responsibleScientist_name_%s'%count" /> <span
             tal:replace="python:identifiedName[0]" /> <!-- <pre tal:content="python:repr(identifiedName)"/> --></td>
           <td>
             <table>
--- a/zpt/project/edit_images.zpt	Thu May 02 10:14:52 2013 +0200
+++ b/zpt/project/edit_images.zpt	Thu May 02 11:26:57 2013 +0200
@@ -4,41 +4,56 @@
 <head>
 </head>
 <body>
-<tal:block metal:fill-slot="navsel" tal:define="global menusel string:images" />
-<tal:block metal:fill-slot="body">
-  <table tal:condition="python:here.getImages()">
-    <tr><th/><th>Image</th><th>Caption</th><th/></tr>
-    <tal:block tal:repeat="image here/getImages">
+  <tal:block metal:fill-slot="navsel" tal:define="global menusel string:images" />
+  <tal:block metal:fill-slot="body">
+    <table tal:define="images here/getImageList" tal:condition="images">
       <tr>
-        <td>
-          <a tal:attributes="href python:here.absolute_url()+'/manageImages?imageName='+image[0]+'&op=up'">up</a><br>
-          <a tal:attributes="href python:here.absolute_url()+'/manageImages?imageName='+image[0]+'&op=down'">down</a>
-        </td>
-        <td tal:condition="not:python:image[1].height==''" tal:content="structure python:image[1].tag(scale=250.0 / image[1].height)" />
-	<td tal:condition="python:image[1].height==''" tal:content="python:image[1].height"/>
-        <td tal:content="structure python:getattr(image[1],'caption','')" />
-        <td>
-          <a tal:attributes="href python:image[1].getId()+'/editImage'">Edit</a><br/>
-          <a tal:attributes="href python:'deleteImage?id='+image[1].getId()">Delete</a>
-        </td>
+        <th />
+        <th>Image</th>
+        <th>Caption</th>
+        <th />
       </tr>
-    </tal:block>
-  </table>
-  
-  <h3>Add an Image</h3>
-  
-  <form action="addImage" method="post" enctype="multipart/form-data">
-  <table>
-    <tr><th>Image</th><th>Caption</th></tr>
-    <tr>
-      <td><input name="fileHd" type="file" len="50"/></td>
-      <td><textarea name="caption" rows="3" cols="60"></textarea></td>
-    </tr>
-  </table>
-  <p><input type="submit" value="submit"/></p>
-  </form>
-  
-  <p>(if the marginal image from your current project description is not in this list, click <a href="copyImageToMargin">here</a>.)</p>
-</tal:block>
+      <tal:block tal:repeat="image images">
+        <tr tal:define="imgid image/getId">
+          <td>
+            <a tal:attributes="href python:here.absolute_url()+'/manageImages?imageName='+imgid+'&op=up'">up</a><br/>
+            <a tal:attributes="href python:here.absolute_url()+'/manageImages?imageName='+imgid+'&op=down'">down</a>
+          </td>
+          <td tal:condition="not:python:image.height==''" tal:content="structure python:image.tag(scale=250.0 / image.height)" />
+          <td tal:condition="python:image.height==''" tal:content="python:image.height" />
+          <td tal:content="structure python:getattr(image,'caption','')" />
+          <td><a tal:attributes="href python:imgid+'/editImage'">Edit</a><br /> <a
+            tal:attributes="href python:'deleteImage?id='+imgid">Delete</a></td>
+        </tr>
+      </tal:block>
+    </table>
+
+    <p>
+      The last image in the list is used as the project thumbnail image (140x87px). Preview: <img width="140" height="87"
+        tal:attributes="src here/getThumbUrl" />
+    </p>
+
+    <h3>Add an Image</h3>
+
+    <form action="addImage" method="post" enctype="multipart/form-data">
+      <table>
+        <tr>
+          <th>Image</th>
+          <th>Caption</th>
+        </tr>
+        <tr>
+          <td><input name="fileHd" type="file" len="50" /></td>
+          <td><textarea name="caption" rows="3" cols="60"></textarea></td>
+        </tr>
+      </table>
+      <p>
+        <input type="submit" value="submit" />
+      </p>
+    </form>
+
+    <p>
+      (if the marginal image from your current project description is not in this list, click <a href="copyImageToMargin">here</a>.)
+    </p>
+  </tal:block>
 </body>
 </html>
--- a/zpt/project/edit_publications.zpt	Thu May 02 10:14:52 2013 +0200
+++ b/zpt/project/edit_publications.zpt	Thu May 02 11:26:57 2013 +0200
@@ -7,16 +7,17 @@
 <tal:block metal:fill-slot="navsel" tal:define="global menusel string:publications" />
 <tal:block metal:fill-slot="body">
   <table>
-    <tal:block tal:repeat="publication here/getPublications">
+    <tal:block tal:repeat="publication here/getRelatedPublications">
       <tr>
         <td>
-          <a tal:attributes="href python:here.absolute_url()+'/managePublications?pubName='+publication[0]+'&op=up'">up</a><br>
-          <a tal:attributes="href python:here.absolute_url()+'/managePublications?pubName='+publication[0]+'&op=down'">down</a>
+          <a tal:attributes="href python:here.absolute_url()+'/managePublications?pubName='+publication.getId()+'&op=up'">up</a><br>
+          <a tal:attributes="href python:here.absolute_url()+'/managePublications?pubName='+publication.getId()+'&op=down'">down</a>
         </td>
-        <td tal:content="structure python:getattr(publication[1],'text','')" />
+        <td tal:content="string:[${publication/place}]"/>
+        <td tal:content="structure python:getattr(publication,'text','')" />
         <td>
-          <a tal:attributes="href python:publication[1].getId()+'/editPublication'">Edit</a><br/> 
-          <a tal:attributes="href python:'deletePublication?id='+publication[1].getId()">Delete</a>
+          <a tal:attributes="href python:publication.getId()+'/editPublication'">Edit</a><br/> 
+          <a tal:attributes="href python:'deletePublication?id='+publication.getId()">Delete</a>
         </td>
       </tr>
     </tal:block>
@@ -39,8 +40,8 @@
 		</tal:x>
 </h3>-->
 
-<h3><a href=" addPublicationsFromPubman"> Add publication to extended list</a></h3>
-<h3><a href=" changePublications"> Change publication list</a></h3>
+<h3><a href="addPublicationsFromPubman"> Add publication to extended list</a></h3>
+<h3><a href="changePublications"> Change publication list</a></h3>
 </tal:block>
 </body>
 </html>
--- a/zpt/project/edit_related_projects.zpt	Thu May 02 10:14:52 2013 +0200
+++ b/zpt/project/edit_related_projects.zpt	Thu May 02 11:26:57 2013 +0200
@@ -1,23 +1,24 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html metal:use-macro="here/edit_MPIWGProject_main/macros/page">
+<html metal:use-macro="here/edit_template/macros/page">
 <head>
 </head>
 <body>
 <tal:block metal:fill-slot="navsel" tal:define="global menusel string:relatedProjects" />
 <tal:block metal:fill-slot="body">
   <table>
-    <tal:block tal:repeat="publication here/getRelatedProjects">
+    <tal:block tal:repeat="item here/getRelatedProjects">
       <tr>
         <td>
-          <a tal:attributes="href python:here.absolute_url()+'/manageRelatedProjects?pubName='+publication.getId()+'&op=up'">up</a><br>
-          <a tal:attributes="href python:here.absolute_url()+'/manageRelatedProjects?pubName='+publication.getId()+'&op=down'">down</a>
+          <a tal:attributes="href python:here.absolute_url()+'/manageRelatedProjects?pubName='+item.getId()+'&op=up'">up</a><br>
+          <a tal:attributes="href python:here.absolute_url()+'/manageRelatedProjects?pubName='+item.getId()+'&op=down'">down</a>
         </td>
-        <td tal:content="structure python:getattr(publication,'objid','')" />
-        <td tal:content="structure python:getattr(publication,'projectWEB_title','')" />
+        <td tal:content="string:[${item/place}]"/>
+        <!-- <td tal:content="item/objid" /> -->
+        <td tal:content="item/getProjectTitle" />
         <td>
-          <a tal:attributes="href python:publication.getId()+'/editRelatedProject'">Edit</a><br/> 
-          <a tal:attributes="href python:'deleteRelatedProject?id='+publication.getId()">Delete</a>
+          <a tal:attributes="href python:item.getId()+'/editRelatedProject'">Edit</a><br/> 
+          <a tal:attributes="href python:'deleteRelatedProject?id='+item.getId()">Delete</a>
         </td>
       </tr>
     </tal:block>
--- a/zpt/project/edit_template.zpt	Thu May 02 10:14:52 2013 +0200
+++ b/zpt/project/edit_template.zpt	Thu May 02 11:26:57 2013 +0200
@@ -9,16 +9,16 @@
 </head>
 <body tal:attributes="onload onload">
   <h3 tal:condition="not:here/isActiveProject">(!!Project is not visible!!)</h3>
-  <h2 class="title">Edit project <i tal:content="python:here.getContent('WEB_title')"/></h2>
+  <h2 class="title">Edit project <i tal:content="here/getProjectTitle"/></h2>
   <metal:block metal:define-slot="navsel"/>
   <div class="mainnav">
-    <span tal:attributes="class python:here.getPathStyle('basic', menusel, 'mainmenu')"><a href="editBasic">Basic information</a></span>
-    <span tal:attributes="class python:here.getPathStyle('description', menusel, 'mainmenu')"><a href="edit">Project description</a></span>
-    <span tal:attributes="class python:here.getPathStyle('images', menusel, 'mainmenu')"><a href="manageImages">Images</a></span>
-    <span tal:attributes="class python:here.getPathStyle('publications', menusel, 'mainmenu')"><a href="managePublications">Publications</a></span>
-    <span tal:attributes="class python:here.getPathStyle('relatedProjects', menusel, 'mainmenu')"><a href="manageRelatedProjects">Related Projects</a></span>
-    <span tal:attributes="class python:here.getPathStyle('themes', menusel, 'mainmenu')"><a href="tagTheProject">Tags</a></span>
-    <span class="mainmenu"><a target="_blank" href="index_html">View</a></span>
+    <span tal:attributes="class python:test('basic'==menusel, 'mainmenusel', 'mainmenu')"><a href="editBasic">Basic information</a></span>
+    <span tal:attributes="class python:test('description'==menusel, 'mainmenusel', 'mainmenu')"><a href="edit">Project description</a></span>
+    <span tal:attributes="class python:test('images'==menusel, 'mainmenusel', 'mainmenu')"><a href="manageImages">Images</a></span>
+    <span tal:attributes="class python:test('publications'==menusel, 'mainmenusel', 'mainmenu')"><a href="managePublications">Publications</a></span>
+    <span tal:attributes="class python:test('relatedProjects'==menusel, 'mainmenusel', 'mainmenu')"><a href="manageRelatedProjects">Related Projects</a></span>
+    <span tal:attributes="class python:test('themes'==menusel, 'mainmenusel', 'mainmenu')"><a href="tagTheProject">Tags</a></span>
+    <span class="mainmenu"><a target="_blank" tal:attributes="href python:here.getUrl(baseUrl=here.en.MPIWGrootURL()+'/research/projects')">View</a></span>
   </div>
   <div class="content">
   <tal:block metal:define-slot="body"/>