|  | @@ -9,6 +9,7 @@ from hashlib import sha256
 | 
	
		
			
			| 9 | 9 |  import bs4
 | 
	
		
			
			| 10 | 10 |  from sqlalchemy import Table, ForeignKey, Column, Sequence
 | 
	
		
			
			| 11 | 11 |  from sqlalchemy.types import Unicode, Integer, DateTime, Text, LargeBinary
 | 
	
		
			
			|  | 12 | +import sqlalchemy.types as sqlat
 | 
	
		
			
			| 12 | 13 |  from sqlalchemy.orm import relation, synonym, relationship
 | 
	
		
			
			| 13 | 14 |  from sqlalchemy.orm import backref
 | 
	
		
			
			| 14 | 15 |  import sqlalchemy.orm as sqlao
 | 
	
	
		
			
			|  | @@ -18,40 +19,7 @@ from tg.i18n import ugettext as _, lazy_ugettext as l_
 | 
	
		
			
			| 18 | 19 |  
 | 
	
		
			
			| 19 | 20 |  import tg
 | 
	
		
			
			| 20 | 21 |  from pboard.model import DeclarativeBase, metadata, DBSession
 | 
	
		
			
			| 21 |  | -
 | 
	
		
			
			| 22 |  | -# This is the association table for the many-to-many relationship between
 | 
	
		
			
			| 23 |  | -# groups and permissions.
 | 
	
		
			
			| 24 |  | -"""pod_node_table = Table('pod_nodes', metadata,
 | 
	
		
			
			| 25 |  | -    Column('node_id', Integer, Sequence('pod_nodes__node_id__sequence'), primary_key=True),
 | 
	
		
			
			| 26 |  | -    Column('parent_id', Integer, ForeignKey('pod_nodes.node_id'), nullable=True, default=None),
 | 
	
		
			
			| 27 |  | -    Column('node_order', Integer, nullable=True, default=1),
 | 
	
		
			
			| 28 |  | -    Column('node_type',   Unicode(16), unique=False, nullable=False, default='data'),
 | 
	
		
			
			| 29 |  | -    Column('node_status', Unicode(16), unique=False, nullable=False, default='new'),
 | 
	
		
			
			| 30 |  | -
 | 
	
		
			
			| 31 |  | -    Column('created_at', DateTime, unique=False, nullable=False),
 | 
	
		
			
			| 32 |  | -    Column('updated_at', DateTime, unique=False, nullable=False),
 | 
	
		
			
			| 33 |  | -
 | 
	
		
			
			| 34 |  | -    Column('data_label',   Unicode(1024), unique=False, nullable=False, default=''),
 | 
	
		
			
			| 35 |  | -    Column('data_content', Text(), unique=False, nullable=False, default=''),
 | 
	
		
			
			| 36 |  | -    Column('data_datetime', DateTime, unique=False, nullable=False),
 | 
	
		
			
			| 37 |  | -    Column('data_reminder_datetime', DateTime, unique=False, nullable=True),
 | 
	
		
			
			| 38 |  | -    
 | 
	
		
			
			| 39 |  | -    Column('data_file_name', Unicode(255), unique=False, nullable=False, default=''),
 | 
	
		
			
			| 40 |  | -    Column('data_file_mime_type', Unicode(255), unique=False, nullable=False, default=''),
 | 
	
		
			
			| 41 |  | -    Column('data_file_content', LargeBinary(), unique=False, nullable=False, default=None),
 | 
	
		
			
			| 42 |  | -)
 | 
	
		
			
			| 43 |  | -"""
 | 
	
		
			
			| 44 |  | -"""
 | 
	
		
			
			| 45 |  | -- node_type
 | 
	
		
			
			| 46 |  | -
 | 
	
		
			
			| 47 |  | -- node_created_at
 | 
	
		
			
			| 48 |  | -- node_updated_at
 | 
	
		
			
			| 49 |  | -
 | 
	
		
			
			| 50 |  | -- data_label
 | 
	
		
			
			| 51 |  | -- data_content
 | 
	
		
			
			| 52 |  | -- data_source_url
 | 
	
		
			
			| 53 |  | -- data_status_id
 | 
	
		
			
			| 54 |  | -"""
 | 
	
		
			
			|  | 22 | +from pboard.model import auth as pma
 | 
	
		
			
			| 55 | 23 |  
 | 
	
		
			
			| 56 | 24 |  class PBNodeStatusItem(object):
 | 
	
		
			
			| 57 | 25 |    def __init__(self, psStatusId, psStatusLabel, psStatusFamily, psIconId, psCssClass): #, psBackgroundColor):
 | 
	
	
		
			
			|  | @@ -143,8 +111,7 @@ class PBNodeStatus(object):
 | 
	
		
			
			| 143 | 111 |        PBNodeStatus.StatusList['closed'],
 | 
	
		
			
			| 144 | 112 |        PBNodeStatus.StatusList['deleted']
 | 
	
		
			
			| 145 | 113 |      ]
 | 
	
		
			
			| 146 |  | -    
 | 
	
		
			
			| 147 |  | -    PBNodeStatus.StatusList.values()
 | 
	
		
			
			|  | 114 | +
 | 
	
		
			
			| 148 | 115 |      
 | 
	
		
			
			| 149 | 116 |    @classmethod
 | 
	
		
			
			| 150 | 117 |    def getStatusItem(cls, psStatusId):
 | 
	
	
		
			
			|  | @@ -182,6 +149,7 @@ class PBNode(DeclarativeBase):
 | 
	
		
			
			| 182 | 149 |      return len(self._lStaticChildList)
 | 
	
		
			
			| 183 | 150 |  
 | 
	
		
			
			| 184 | 151 |    __tablename__ = 'pod_nodes'
 | 
	
		
			
			|  | 152 | +
 | 
	
		
			
			| 185 | 153 |    node_id          = Column(Integer, Sequence('pod_nodes__node_id__sequence'), primary_key=True)
 | 
	
		
			
			| 186 | 154 |    parent_id        = Column(Integer, ForeignKey('pod_nodes.node_id'), nullable=True, default=None)
 | 
	
		
			
			| 187 | 155 |    node_depth       = Column(Integer, unique=False, nullable=False, default=0)
 | 
	
	
		
			
			|  | @@ -195,6 +163,21 @@ class PBNode(DeclarativeBase):
 | 
	
		
			
			| 195 | 163 |    created_at = Column(DateTime, unique=False, nullable=False)
 | 
	
		
			
			| 196 | 164 |    updated_at = Column(DateTime, unique=False, nullable=False)
 | 
	
		
			
			| 197 | 165 |  
 | 
	
		
			
			|  | 166 | +  """
 | 
	
		
			
			|  | 167 | +    if 1, the document is available for other users logged into pod.
 | 
	
		
			
			|  | 168 | +    default is 0 (private document)
 | 
	
		
			
			|  | 169 | +  """
 | 
	
		
			
			|  | 170 | +  is_shared = Column(sqlat.Boolean, unique=False, nullable=False, default=False)
 | 
	
		
			
			|  | 171 | +  """
 | 
	
		
			
			|  | 172 | +    if 1, the document is available through a public - but obfuscated, url
 | 
	
		
			
			|  | 173 | +    default is 0 (document not publicly available)
 | 
	
		
			
			|  | 174 | +  """
 | 
	
		
			
			|  | 175 | +  is_public = Column(sqlat.Boolean, unique=False, nullable=False, default=False)
 | 
	
		
			
			|  | 176 | +  """
 | 
	
		
			
			|  | 177 | +    here is the hash allowing to get the document publicly
 | 
	
		
			
			|  | 178 | +  """
 | 
	
		
			
			|  | 179 | +  public_url_key = Column(Unicode(1024), unique=False, nullable=False, default='')
 | 
	
		
			
			|  | 180 | +
 | 
	
		
			
			| 198 | 181 |    data_label   = Column(Unicode(1024), unique=False, nullable=False, default='')
 | 
	
		
			
			| 199 | 182 |    data_content = Column(Text(),        unique=False, nullable=False, default='')
 | 
	
		
			
			| 200 | 183 |    
 | 
	
	
		
			
			|  | @@ -207,6 +190,7 @@ class PBNode(DeclarativeBase):
 | 
	
		
			
			| 207 | 190 |  
 | 
	
		
			
			| 208 | 191 |  
 | 
	
		
			
			| 209 | 192 |    _oParent = relationship('PBNode', remote_side=[node_id], backref='_lAllChildren')
 | 
	
		
			
			|  | 193 | +  _oOwner = relationship('User', remote_side=[pma.User.user_id], backref='_lAllNodes')
 | 
	
		
			
			| 210 | 194 |  
 | 
	
		
			
			| 211 | 195 |    def getChildrenOfType(self, plNodeTypeList, poKeySortingMethod=None, pbDoReverseSorting=False):
 | 
	
		
			
			| 212 | 196 |      """return all children nodes of type 'data' or 'node' or 'folder'"""
 | 
	
	
		
			
			|  | @@ -230,9 +214,15 @@ class PBNode(DeclarativeBase):
 | 
	
		
			
			| 230 | 214 |    def getChildNb(self):
 | 
	
		
			
			| 231 | 215 |      return self.getChildNbOfType([PBNodeType.Data])
 | 
	
		
			
			| 232 | 216 |  
 | 
	
		
			
			| 233 |  | -  def getChildren(self):
 | 
	
		
			
			|  | 217 | +  def getChildren(self, pbIncludeDeleted=False):
 | 
	
		
			
			| 234 | 218 |      """return all children nodes of type 'data' or 'node' or 'folder'"""
 | 
	
		
			
			| 235 |  | -    return self.getChildrenOfType([PBNodeType.Node, PBNodeType.Folder, PBNodeType.Data])
 | 
	
		
			
			|  | 219 | +    # return self.getChildrenOfType([PBNodeType.Node, PBNodeType.Folder, PBNodeType.Data])
 | 
	
		
			
			|  | 220 | +    items = self.getChildrenOfType([PBNodeType.Node, PBNodeType.Folder, PBNodeType.Data])
 | 
	
		
			
			|  | 221 | +    items2 = list()
 | 
	
		
			
			|  | 222 | +    for item in items:
 | 
	
		
			
			|  | 223 | +      if pbIncludeDeleted==True or item.node_status!='deleted':
 | 
	
		
			
			|  | 224 | +        items2.append(item)
 | 
	
		
			
			|  | 225 | +    return items2
 | 
	
		
			
			| 236 | 226 |  
 | 
	
		
			
			| 237 | 227 |    def getContacts(self):
 | 
	
		
			
			| 238 | 228 |      """return all children nodes of type 'data' or 'node' or 'folder'"""
 | 
	
	
		
			
			|  | @@ -343,13 +333,23 @@ class PBNode(DeclarativeBase):
 | 
	
		
			
			| 343 | 333 |            break
 | 
	
		
			
			| 344 | 334 |        return PBNodeStatus.getStatusItem(lsRealStatusId)
 | 
	
		
			
			| 345 | 335 |  
 | 
	
		
			
			| 346 |  | -  def getTruncatedLabel(self, piCharNb):
 | 
	
		
			
			| 347 |  | -    lsTruncatedLabel = ''
 | 
	
		
			
			|  | 336 | +  def getTruncatedLabel(self: PBNode, piCharNb: int):
 | 
	
		
			
			|  | 337 | +    """
 | 
	
		
			
			|  | 338 | +    return a truncated version of the data_label property.
 | 
	
		
			
			|  | 339 | +    if piCharNb is not > 0, then the full data_label is returned
 | 
	
		
			
			|  | 340 | +    note: if the node is a file and the data_label is empty, the file name is returned
 | 
	
		
			
			|  | 341 | +    """
 | 
	
		
			
			|  | 342 | +    lsTruncatedLabel = self.data_label
 | 
	
		
			
			|  | 343 | +
 | 
	
		
			
			|  | 344 | +    # 2014-05-06 - D.A. - HACK
 | 
	
		
			
			|  | 345 | +    # if the node is a file and label empty, then use the filename as data_label
 | 
	
		
			
			|  | 346 | +    if self.node_type==PBNodeType.File and lsTruncatedLabel=='':
 | 
	
		
			
			|  | 347 | +      lsTruncatedLabel = self.data_file_name
 | 
	
		
			
			|  | 348 | +
 | 
	
		
			
			| 348 | 349 |      liMaxLength = int(piCharNb)
 | 
	
		
			
			| 349 |  | -    if len(self.data_label)>liMaxLength:
 | 
	
		
			
			| 350 |  | -      lsTruncatedLabel = self.data_label[0:liMaxLength-1]+'…'
 | 
	
		
			
			| 351 |  | -    else:
 | 
	
		
			
			| 352 |  | -      lsTruncatedLabel = self.data_label
 | 
	
		
			
			|  | 350 | +    if liMaxLength>0 and len(lsTruncatedLabel)>liMaxLength:
 | 
	
		
			
			|  | 351 | +      lsTruncatedLabel = lsTruncatedLabel[0:liMaxLength-1]+'…'
 | 
	
		
			
			|  | 352 | +
 | 
	
		
			
			| 353 | 353 |      return lsTruncatedLabel
 | 
	
		
			
			| 354 | 354 |  
 | 
	
		
			
			| 355 | 355 |    def getTruncatedContentAsText(self, piCharNb):
 | 
	
	
		
			
			|  | @@ -387,29 +387,3 @@ class PBNode(DeclarativeBase):
 | 
	
		
			
			| 387 | 387 |      # Does not match @@ at end of content.
 | 
	
		
			
			| 388 | 388 |  
 | 
	
		
			
			| 389 | 389 |  
 | 
	
		
			
			| 390 |  | -
 | 
	
		
			
			| 391 |  | -"""from sqlalchemy.orm import mapper
 | 
	
		
			
			| 392 |  | -mapper(
 | 
	
		
			
			| 393 |  | -  PBNode,
 | 
	
		
			
			| 394 |  | -  pod_node_table,
 | 
	
		
			
			| 395 |  | -  properties = {'_lAllChildren' : relationship(PBNode, backref=backref('_oParent', remote_side=PBNode.parent_id)) }
 | 
	
		
			
			| 396 |  | -)"""
 | 
	
		
			
			| 397 |  | -
 | 
	
		
			
			| 398 |  | -
 | 
	
		
			
			| 399 |  | -
 | 
	
		
			
			| 400 |  | -"""    children = relationship('TreeNode',
 | 
	
		
			
			| 401 |  | -
 | 
	
		
			
			| 402 |  | -                        # cascade deletions
 | 
	
		
			
			| 403 |  | -                        cascade="all",
 | 
	
		
			
			| 404 |  | -
 | 
	
		
			
			| 405 |  | -                        # many to one + adjacency list - remote_side
 | 
	
		
			
			| 406 |  | -                        # is required to reference the 'remote' 
 | 
	
		
			
			| 407 |  | -                        # column in the join condition.
 | 
	
		
			
			| 408 |  | -                        backref=backref("parent", remote_side='TreeNode.id'),
 | 
	
		
			
			| 409 |  | -
 | 
	
		
			
			| 410 |  | -                        # children will be represented as a dictionary
 | 
	
		
			
			| 411 |  | -                        # on the "name" attribute.
 | 
	
		
			
			| 412 |  | -                        collection_class=attribute_mapped_collection('name'),
 | 
	
		
			
			| 413 |  | -                    ) 
 | 
	
		
			
			| 414 |  | -"""
 | 
	
		
			
			| 415 |  | -
 |