|  | @@ -12,6 +12,7 @@ order by last_action desc
 | 
	
		
			
			| 12 | 12 |  """
 | 
	
		
			
			| 13 | 13 |  import os
 | 
	
		
			
			| 14 | 14 |  import re
 | 
	
		
			
			|  | 15 | +import datetime as datetimeroot
 | 
	
		
			
			| 15 | 16 |  from datetime import datetime
 | 
	
		
			
			| 16 | 17 |  from hashlib import sha256
 | 
	
		
			
			| 17 | 18 |  __all__ = ['User', 'Group', 'Permission']
 | 
	
	
		
			
			|  | @@ -143,6 +144,8 @@ class PBNodeType(object):
 | 
	
		
			
			| 143 | 144 |    Comment = 'comment'
 | 
	
		
			
			| 144 | 145 |  
 | 
	
		
			
			| 145 | 146 |  
 | 
	
		
			
			|  | 147 | +MINIMUM_DATE = datetimeroot.date(datetimeroot.MINYEAR, 1, 1)
 | 
	
		
			
			|  | 148 | +
 | 
	
		
			
			| 146 | 149 |  class PBNode(DeclarativeBase):
 | 
	
		
			
			| 147 | 150 |  
 | 
	
		
			
			| 148 | 151 |    def __init__(self):
 | 
	
	
		
			
			|  | @@ -188,14 +191,15 @@ class PBNode(DeclarativeBase):
 | 
	
		
			
			| 188 | 191 |  
 | 
	
		
			
			| 189 | 192 |    _oParent = relationship('PBNode', remote_side=[node_id], backref='_lAllChildren')
 | 
	
		
			
			| 190 | 193 |  
 | 
	
		
			
			| 191 |  | -  def getChildrenOfType(self, plNodeTypeList, plSortingCriteria):
 | 
	
		
			
			|  | 194 | +  def getChildrenOfType(self, plNodeTypeList, poKeySortingMethod=None, pbDoReverseSorting=False):
 | 
	
		
			
			| 192 | 195 |      """return all children nodes of type 'data' or 'node' or 'folder'"""
 | 
	
		
			
			| 193 | 196 |      llChildren = []
 | 
	
		
			
			| 194 | 197 |      for child in self._lAllChildren:
 | 
	
		
			
			| 195 | 198 |        if child.node_type in plNodeTypeList:
 | 
	
		
			
			| 196 | 199 |          llChildren.append(child)
 | 
	
		
			
			|  | 200 | +    if poKeySortingMethod!=None:
 | 
	
		
			
			|  | 201 | +      llChildren = sorted(llChildren, key=poKeySortingMethod, reverse=pbDoReverseSorting)
 | 
	
		
			
			| 197 | 202 |      return llChildren
 | 
	
		
			
			| 198 |  | -    # return DBSession.query(PBNode).filter(PBNode.parent_id==self.node_id).filter(PBNode.node_type.in_(plNodeTypeList)).order_by(plSortingCriteria).all()
 | 
	
		
			
			| 199 | 203 |    
 | 
	
		
			
			| 200 | 204 |    def getChildNbOfType(self, plNodeTypeList):
 | 
	
		
			
			| 201 | 205 |      """return all children nodes of type 'data' or 'node' or 'folder'"""
 | 
	
	
		
			
			|  | @@ -211,20 +215,36 @@ class PBNode(DeclarativeBase):
 | 
	
		
			
			| 211 | 215 |  
 | 
	
		
			
			| 212 | 216 |    def getChildren(self):
 | 
	
		
			
			| 213 | 217 |      """return all children nodes of type 'data' or 'node' or 'folder'"""
 | 
	
		
			
			| 214 |  | -    return self.getChildrenOfType([PBNodeType.Node, PBNodeType.Folder, PBNodeType.Data], PBNode.node_order.asc())
 | 
	
		
			
			|  | 218 | +    return self.getChildrenOfType([PBNodeType.Node, PBNodeType.Folder, PBNodeType.Data])
 | 
	
		
			
			| 215 | 219 |  
 | 
	
		
			
			| 216 | 220 |    def getContacts(self):
 | 
	
		
			
			| 217 | 221 |      """return all children nodes of type 'data' or 'node' or 'folder'"""
 | 
	
		
			
			| 218 |  | -    return self.getChildrenOfType([PBNodeType.Contact], PBNode.data_label.asc())
 | 
	
		
			
			|  | 222 | +    return self.getChildrenOfType([PBNodeType.Contact], PBNode.getSortingKeyForContact)
 | 
	
		
			
			|  | 223 | +
 | 
	
		
			
			|  | 224 | +  def getContactNb(self):
 | 
	
		
			
			|  | 225 | +    """return all children nodes of type 'data' or 'node' or 'folder'"""
 | 
	
		
			
			|  | 226 | +    return self.getChildNbOfType([PBNodeType.Contact])
 | 
	
		
			
			|  | 227 | +
 | 
	
		
			
			|  | 228 | +  @classmethod
 | 
	
		
			
			|  | 229 | +  def getSortingKeyBasedOnDataDatetime(cls, poDataNode):
 | 
	
		
			
			|  | 230 | +    return poDataNode.data_datetime or MINIMUM_DATE
 | 
	
		
			
			|  | 231 | +    
 | 
	
		
			
			|  | 232 | +  @classmethod
 | 
	
		
			
			|  | 233 | +  def getSortingKeyForContact(cls, poDataNode):
 | 
	
		
			
			|  | 234 | +    return poDataNode.data_label or ''
 | 
	
		
			
			|  | 235 | +
 | 
	
		
			
			|  | 236 | +  @classmethod
 | 
	
		
			
			|  | 237 | +  def getSortingKeyForComment(cls, poDataNode):
 | 
	
		
			
			|  | 238 | +    return poDataNode.data_datetime or ''
 | 
	
		
			
			| 219 | 239 |  
 | 
	
		
			
			| 220 | 240 |    def getEvents(self):
 | 
	
		
			
			| 221 |  | -    return self.getChildrenOfType([PBNodeType.Event], PBNode.data_datetime.desc())
 | 
	
		
			
			|  | 241 | +    return self.getChildrenOfType([PBNodeType.Event], PBNode.getSortingKeyBasedOnDataDatetime, True)
 | 
	
		
			
			| 222 | 242 |      
 | 
	
		
			
			| 223 | 243 |    def getFiles(self):
 | 
	
		
			
			| 224 |  | -    return self.getChildrenOfType([PBNodeType.File], PBNode.data_datetime.desc())
 | 
	
		
			
			|  | 244 | +    return self.getChildrenOfType([PBNodeType.File])
 | 
	
		
			
			| 225 | 245 |  
 | 
	
		
			
			| 226 | 246 |    def getComments(self):
 | 
	
		
			
			| 227 |  | -    return self.getChildrenOfType([PBNodeType.Comment], PBNode.data_datetime.desc())
 | 
	
		
			
			|  | 247 | +    return self.getChildrenOfType([PBNodeType.Comment], PBNode.getSortingKeyBasedOnDataDatetime, True)
 | 
	
		
			
			| 228 | 248 |  
 | 
	
		
			
			| 229 | 249 |    def getIconClass(self):
 | 
	
		
			
			| 230 | 250 |      laIconClass = dict()
 |