|
@@ -9,6 +9,7 @@ from sqlalchemy import Table, ForeignKey, Column
|
9
|
9
|
from sqlalchemy.types import Unicode, Integer, DateTime, Text
|
10
|
10
|
from sqlalchemy.orm import relation, synonym
|
11
|
11
|
from sqlalchemy.orm import joinedload_all
|
|
12
|
+import sqlalchemy.orm as sqlao
|
12
|
13
|
import sqlalchemy as sqla
|
13
|
14
|
|
14
|
15
|
from pboard.model import DeclarativeBase, metadata, DBSession
|
|
@@ -82,7 +83,7 @@ class PODUserFilteredApiController(object):
|
82
|
83
|
self._iCurrentUserId = piUserId
|
83
|
84
|
self._iExtraUserIdList = piExtraUserIdList
|
84
|
85
|
self._iUserIdFilteringList = None
|
85
|
|
-
|
|
86
|
+ self._cache_allowed_nodes = None
|
86
|
87
|
|
87
|
88
|
def _getUserIdListForFiltering(self):
|
88
|
89
|
if self._iUserIdFilteringList==None:
|
|
@@ -127,7 +128,7 @@ class PODUserFilteredApiController(object):
|
127
|
128
|
lsNodeIdFiltering = lsSqlSelectQuery % (str(self._iCurrentUserId))
|
128
|
129
|
|
129
|
130
|
if liNodeId!=None and liNodeId!=0:
|
130
|
|
- return DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren"))\
|
|
131
|
+ return DBSession.query(pbmd.PBNode).options(sqlao.joinedload_all("_oParent"), sqlao.joinedload_all("_lAllChildren"))\
|
131
|
132
|
.filter(pbmd.PBNode.node_id==liNodeId)\
|
132
|
133
|
.filter(
|
133
|
134
|
sqla.or_(
|
|
@@ -146,28 +147,75 @@ class PODUserFilteredApiController(object):
|
146
|
147
|
return DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren")).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).order_by(pbmd.PBNode.updated_at.desc()).limit(piMaxNodeNb).all()
|
147
|
148
|
|
148
|
149
|
|
149
|
|
- def getListOfAllowedNodes(self) -> pbmd.PBNode:
|
150
|
|
- lsSqlQuery = """
|
151
|
|
- SELECT
|
152
|
|
- pgn.node_id
|
153
|
|
- FROM
|
154
|
|
- pod_group_node AS pgn
|
155
|
|
- join pod_user_group AS pug ON pug.group_id = pgn.group_id
|
156
|
|
- WHERE
|
157
|
|
- pgn.rights > 0
|
158
|
|
- AND pug.user_id = :owner_id
|
159
|
|
- UNION
|
|
150
|
+ def getListOfAllowedNodes(self, reset_cache=False) -> pbmd.PBNode:
|
|
151
|
+ if self._cache_allowed_nodes==None or reset_cache==True:
|
|
152
|
+ lsSqlQuery = """
|
160
|
153
|
SELECT
|
161
|
|
- node_id
|
|
154
|
+ pn.node_id,
|
|
155
|
+ pn.parent_id,
|
|
156
|
+ pn.node_order,
|
|
157
|
+ pn.node_type,
|
|
158
|
+ pn.created_at,
|
|
159
|
+ pn.updated_at,
|
|
160
|
+ pn.data_label,
|
|
161
|
+ pn.data_content,
|
|
162
|
+ pn.data_datetime,
|
|
163
|
+ pn.node_status,
|
|
164
|
+ pn.data_reminder_datetime,
|
|
165
|
+ pn.parent_tree_path,
|
|
166
|
+ pn.node_depth,
|
|
167
|
+ pn.owner_id,
|
|
168
|
+ pn.is_shared,
|
|
169
|
+ pn.is_public,
|
|
170
|
+ pn.public_url_key
|
162
|
171
|
FROM
|
163
|
|
- pod_nodes
|
|
172
|
+ pod_group_node AS pgn
|
|
173
|
+ join pod_user_group AS pug ON pug.group_id = pgn.group_id
|
|
174
|
+ join pod_nodes AS pn ON pgn.node_id=pn.node_id
|
164
|
175
|
WHERE
|
165
|
|
- owner_id=:owner_id;
|
166
|
|
- """
|
167
|
|
-
|
168
|
|
- loNodeListResult = DBSession.query(pbmd.PBNode).from_statement(lsSqlQuery).params(owner_id=self._iCurrentUserId)
|
169
|
|
-
|
170
|
|
- return loNodeListResult.all()
|
|
176
|
+ pn.node_type='data'
|
|
177
|
+ AND pn.node_status NOT IN ('deleted', 'closed')
|
|
178
|
+ AND pn.node_id=pgn.node_id
|
|
179
|
+ AND pgn.rights > 0
|
|
180
|
+ AND pug.user_id = 3
|
|
181
|
+
|
|
182
|
+ UNION
|
|
183
|
+ SELECT
|
|
184
|
+ pn.node_id,
|
|
185
|
+ pn.parent_id,
|
|
186
|
+ pn.node_order,
|
|
187
|
+ pn.node_type,
|
|
188
|
+ pn.created_at,
|
|
189
|
+ pn.updated_at,
|
|
190
|
+ pn.data_label,
|
|
191
|
+ pn.data_content,
|
|
192
|
+ pn.data_datetime,
|
|
193
|
+ pn.node_status,
|
|
194
|
+ pn.data_reminder_datetime,
|
|
195
|
+ pn.parent_tree_path,
|
|
196
|
+ pn.node_depth,
|
|
197
|
+ pn.owner_id,
|
|
198
|
+ pn.is_shared,
|
|
199
|
+ pn.is_public,
|
|
200
|
+ pn.public_url_key
|
|
201
|
+ FROM
|
|
202
|
+ pod_nodes AS pn
|
|
203
|
+ WHERE
|
|
204
|
+ pn.node_type='data'
|
|
205
|
+ AND pn.node_status NOT IN ('deleted', 'closed')
|
|
206
|
+ AND pn.owner_id=:owner_id
|
|
207
|
+
|
|
208
|
+ ORDER BY node_id ASC
|
|
209
|
+ """
|
|
210
|
+
|
|
211
|
+ loNodeListResult = DBSession.query(pbmd.PBNode).\
|
|
212
|
+ from_statement(lsSqlQuery).\
|
|
213
|
+ params(owner_id=self._iCurrentUserId)
|
|
214
|
+ allowed_nodes = loNodeListResult.all()
|
|
215
|
+
|
|
216
|
+ self._cache_allowed_nodes = allowed_nodes
|
|
217
|
+
|
|
218
|
+ return self._cache_allowed_nodes
|
171
|
219
|
|
172
|
220
|
|
173
|
221
|
def searchNodesByText(self, plKeywordList: [str], piMaxNodeNb=100):
|
|
@@ -197,6 +245,47 @@ class PODUserFilteredApiController(object):
|
197
|
245
|
return DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren")).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_status==psNodeStatus).order_by(pbmd.PBNode.updated_at).limit(piMaxNodeNb).all()
|
198
|
246
|
|
199
|
247
|
|
|
248
|
+ def getChildNodesForMenu(self, poParentNode: pbmd.PBNode, allowed_nodes: [pbmd.PBNode]) -> [pbmd.PBNode]:
|
|
249
|
+ visible_child_nodes = []
|
|
250
|
+
|
|
251
|
+ if poParentNode!=None:
|
|
252
|
+ # standard case
|
|
253
|
+ print(" -------------- BEFORE @@@@@@@@@@@@@@@@ ")
|
|
254
|
+ all_child_nodes = poParentNode.getChildren()
|
|
255
|
+ print("@@@@@@@@@@@@@@@@ AFTER @@@@@@@@@@@@@@@@ ")
|
|
256
|
+ for child_node in all_child_nodes:
|
|
257
|
+ if child_node in allowed_nodes:
|
|
258
|
+ visible_child_nodes.append(child_node)
|
|
259
|
+ else:
|
|
260
|
+ # Root case
|
|
261
|
+ parent_nodes = DBSession
|
|
262
|
+ for allowed_node in allowed_nodes:
|
|
263
|
+ print(" @@@@@@@@@@@@@@@@ BEFORE @@@@@@@@@@@@@@@@ ")
|
|
264
|
+ # loParent = allowed_node._oParent
|
|
265
|
+ # print("@@@@@@@@@@@@@@@@ AFTER @@@@@@@@@@@@@@@@ {0}".format(allowed_node._oParent.node_id if allowed_node._oParent!=None else '0'))
|
|
266
|
+ # print("==== EXTRA {0}".format(allowed_node._oParent.node_id if allowed_node._oParent!=None else '0'))
|
|
267
|
+ print("====> ")
|
|
268
|
+
|
|
269
|
+ if allowed_node._oParent is None or allowed_node._oParent==allowed_node:
|
|
270
|
+ # D.A. - HACK - 2014-05-27
|
|
271
|
+ # I don't know why, but as from now (with use of sqlao.contains_eager in getListOfAllowedNodes()
|
|
272
|
+ # the root items have at first iteration itself as parent
|
|
273
|
+ print("==== EXTRA END")
|
|
274
|
+ # this is a root item => add it
|
|
275
|
+ visible_child_nodes.append(allowed_node)
|
|
276
|
+ else:
|
|
277
|
+ if allowed_node._oParent not in allowed_nodes:
|
|
278
|
+ # the node is visible but not the parent => put it at the root
|
|
279
|
+ visible_child_nodes.append(allowed_node)
|
|
280
|
+ else:
|
|
281
|
+ print("==== EXTRA END 2 {0}".format(allowed_node._oParent.node_id))
|
|
282
|
+
|
|
283
|
+ print(" @@@@@@@@@@@@@@@@ PRE FAILURE @@@@@@@@@@@@@@@@ ")
|
|
284
|
+ return visible_child_nodes
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
200
|
289
|
def buildTreeListForMenu(self, poCurrentNode: pbmd.PBNode, plViewableStatusId: [], plAllowedNodes: [pbmd.PBNode]) -> [pbmd.NodeTreeItem]:
|
201
|
290
|
# The algorithm is:
|
202
|
291
|
# 1. build an intermediate tree containing only current node and parent path
|
|
@@ -209,8 +298,10 @@ class PODUserFilteredApiController(object):
|
209
|
298
|
previous_tree_item = None
|
210
|
299
|
tmp_children_nodes = []
|
211
|
300
|
|
|
301
|
+ print("============================> ",poCurrentNode)
|
212
|
302
|
if poCurrentNode is not None:
|
213
|
303
|
breadcrumb_nodes = poCurrentNode.getBreadCrumbNodes()
|
|
304
|
+ print("====================> NODES", breadcrumb_nodes)
|
214
|
305
|
breadcrumb_nodes.append(poCurrentNode) # by default the current node is not included
|
215
|
306
|
|
216
|
307
|
for breadcrumb_node in reversed(breadcrumb_nodes):
|
|
@@ -218,25 +309,38 @@ class PODUserFilteredApiController(object):
|
218
|
309
|
# First iteration. We add all current_node children
|
219
|
310
|
for child_node in breadcrumb_node.getChildren():
|
220
|
311
|
child_item = pbmd.NodeTreeItem(child_node, [])
|
|
312
|
+ assert(isinstance(child_item, pbmd.NodeTreeItem))
|
221
|
313
|
tmp_children_nodes.append(child_item)
|
222
|
314
|
previous_tree_item = pbmd.NodeTreeItem(breadcrumb_node, tmp_children_nodes)
|
223
|
315
|
else:
|
224
|
316
|
tmp_children_nodes = []
|
225
|
317
|
for child_node in breadcrumb_node.getChildren():
|
226
|
318
|
if child_node == previous_tree_item.node:
|
|
319
|
+ assert(isinstance(previous_tree_item, pbmd.NodeTreeItem))
|
227
|
320
|
tmp_children_nodes.append(previous_tree_item)
|
228
|
321
|
else:
|
229
|
322
|
sibling_node = pbmd.NodeTreeItem(child_node, [])
|
|
323
|
+ assert(isinstance(sibling_node, pbmd.NodeTreeItem))
|
230
|
324
|
tmp_children_nodes.append(sibling_node)
|
231
|
325
|
|
232
|
326
|
previous_tree_item = pbmd.NodeTreeItem(breadcrumb_node, tmp_children_nodes)
|
233
|
327
|
|
234
|
328
|
for node in plAllowedNodes:
|
|
329
|
+ # This part of the algorithm insert root items
|
235
|
330
|
if node.parent_id==0 or node.parent_id is None:
|
236
|
331
|
if previous_tree_item is not None and node == previous_tree_item.node:
|
|
332
|
+ assert(isinstance(previous_tree_item, pbmd.NodeTreeItem))
|
237
|
333
|
node_tree.append(previous_tree_item)
|
238
|
334
|
else:
|
239
|
335
|
node_tree.append(pbmd.NodeTreeItem(node, []))
|
|
336
|
+ else:
|
|
337
|
+ # Try to add nodes shared with me but with a parent which is not shared
|
|
338
|
+ if node.owner_id!=self._iCurrentUserId:
|
|
339
|
+ # this is a node shared with me
|
|
340
|
+ if node._oParent!=None and node._oParent not in plAllowedNodes:
|
|
341
|
+ # the node is shared but not the parent => put it in the root
|
|
342
|
+ node_tree.append(pbmd.NodeTreeItem(node))
|
|
343
|
+
|
240
|
344
|
|
241
|
345
|
return node_tree
|
242
|
346
|
|