0 Votes

Changes for page Hierarchy Macro

Last modified by Ruud de Jong on 2024/12/17 19:47

From version 2.1
edited by Dongxu Lu
on 2023/07/04 10:30
Change comment: Migrated property [type] from class [XWiki.WikiMacroParameterClass]
To version 3.1
edited by Ruud de Jong
on 2024/12/17 19:47
Change comment: Install extension [org.xwiki.contrib:xwiki-macro-hierarchy/1.3.1]

Summary

Details

Page properties
Author
... ... @@ -1,1 +1,1 @@
1 -XWiki.DongxuLu
1 +XWiki.RuuddeJong
Default language
... ... @@ -1,1 +1,0 @@
1 -en
Content
... ... @@ -1,6 +1,7 @@
1 1  Document that defines the hierarchy macro, which displays and allows to edit the documents hierarchy in a specific space (the standard parent-child relation) along with a special information, children order, which is saved in each parent to allow ordering its children as set by the user when displayed with this macro (and whenever some code which is aware of this information uses it).
2 2  
3 3  Note that the children order information should be used as a relative order, since a document can have additional children which are not present in the order information, as the order information is not updated when the parent parents / children are changed through other means than this macro. In such situations, hierarchy macro uses the stored children order for a document as follows:
4 +
4 4  * for all the documents which are in the stored order, if they are an actual child of the document, they are displayed, as they appear in the stored order
5 5  * for all the actual children of the document in alphabetic order of their display values (with a special case for the displayTitle), if they have not been yet displayed, they are displayed.
6 6  Thus, children in the stored order will appear first, as dictated by the order, followed by the children for which there is no order information.
XWiki.JavaScriptExtension[0]
Code
... ... @@ -447,8 +447,8 @@
447 447   if (parentLi) {
448 448   var sublist = parentLi.down('ul');
449 449   if (sublist && sublist.parentNode == parentLi) {
450 - sublist.toggle();
451 - handler.toggleClassName('open');
450 + sublist.toggleClassName('hidden');
451 + handler.toggleClassName('open');
452 452   }
453 453   }
454 454   },
XWiki.WikiMacroClass[0]
Macro code
... ... @@ -19,11 +19,28 @@
19 19   #if ($hasChildrenList || (($editable || $reorderable) && $context.action != "export"))
20 20   #set($showChildrenList = true)
21 21   #end
22 - <div class="hierarchynode">
22 + ##
23 + ## we need to mark the opened node, @$openNode, using a CSS class called 'open-node' in order to target it in the DOM tree
24 + #set($markOpenNode = '')
25 + #if($isOpenNodeMode && $openNode.equals($parent))
26 + #set($markOpenNode = 'open-node')
27 + #end
28 + <div class="hierarchynode ${markOpenNode}">
23 23   ## display the toggle button only if it has children list and we're not in export action (exporting pdf)
24 24   ## actually we should put this button from js, when loading the handlers, since it can only be used with js. FIXME: move
25 25   #if($showChildrenList && $context.action != "export")
26 - <span class="togglenodehandler hidden open">toggle</span>
32 + #set($classAttributeValue = "togglenodehandler hidden")
33 + ## if the pathToRootNode array contains at least 1 element then the tree must be collapsed except for one node
34 + ## the array holds the path from that node to the root node
35 + ## if the current processed node, @$parent, is in the array which holds the ancestor hierarchy of the document specified in the @$openNode parameter
36 + ## and @$collapsed is false, we display it
37 + #if(($isOpenNodeMode && $pathToRootNode.contains($parent)) && !$collapsed)
38 + #set($classAttributeValue = "${classAttributeValue} open")
39 + ## otherwise, if there are no elements in the @$pathToRootNode array and there is no explicit collapse set, then display the nodes expanded
40 + #elseif(!$isOpenNodeMode && !$collapsed)
41 + #set($classAttributeValue = "${classAttributeValue} open")
42 + #end
43 + <span class="${classAttributeValue}">toggle</span>
27 27   #else
28 28   ## for other cases, display anyway a toggle span, for layouting purposes
29 29   <span class="togglenodehandlerplaceholder"></span>
... ... @@ -45,7 +45,7 @@
45 45   ## don't display link if we're in edit mode since dragging a link is a pain since you'll too often click it.
46 46   ## Don't display link if doesn't have right to view
47 47   #if(!$editable && !$reorderable && $hasRightToView)<a href="${xwiki.getURL($parent)}">#end
48 - <span class="documentlabel">${titleToDisplay}</span> #if(!$hasRightToView)*#end
65 + <span class="documentlabel">$titleToDisplay</span> #if(!$hasRightToView)*#end
49 49   #if(!$editable && !$reorderable && $hasRightToView)</a>#end
50 50   ## display reference of this element, to be able to catch it with js and perform the operation
51 51   <input type="hidden" name="docreference" value="$parent" />
... ... @@ -68,7 +68,12 @@
68 68   </div>
69 69   ## and now the children
70 70   #if ($showChildrenList)
71 - <ul>
88 + #set($ulClassAttribute = '')
89 + ## we hide the sublists if the node is not on the hierarchical path, not contained in the ancestor array of the document @$openNode, or if the collapse is set explicitly
90 + #if(($isOpenNodeMode && !$pathToRootNode.contains($parent)) || $collapsed)
91 + #set($ulClassAttribute = 'hidden')
92 + #end
93 + <ul class="$ulClassAttribute">
72 72   #if ($hasChildrenList)
73 73   ## prepare the children list, in the order given by the ChildrenOrder object in the parent
74 74   #set($childrenListToDisplay = [])
... ... @@ -120,6 +120,35 @@
120 120  #set($discard = $xwiki.jsx.use("$xcontext.macro.doc", {'defer' : false, 'minify': false}))
121 121  ## get the parameters, the space to show hierarchy for
122 122  #set($space = "$!xcontext.macro.params.space")
145 +## get the node value (a document's full name) for which we want to display the path expanded from the root node to the specified node
146 +## collapsing all the other branches
147 +#set($openNode = "$!xcontext.macro.params.openNode")
148 +## we need to recursively get all the ancestors of the specified node @$openNode
149 +#set($pathToRootNode = [])
150 +#if(!$openNode.isEmpty() && $xwiki.exists($openNode))
151 + #macro(getPathToRoot $document)
152 + #set($documentParent = $document.getParent())
153 + #if(!$documentParent.equals(''))
154 + #set($discard = $pathToRootNode.add($documentParent))
155 + #getPathToRoot($xwiki.getDocument($documentParent))
156 + #end
157 + #end
158 + ##
159 + #getPathToRoot($xwiki.getDocument($openNode))
160 +#end
161 +#set($isOpenNodeMode = $pathToRootNode.size() > 0)
162 +## specify if the tree should be collapsed
163 +#set($collapsed = "$!xcontext.macro.params.collapsed" == 'true' || "$!xcontext.macro.params.collapsed" == 'yes')
164 +## get the list of spaces that will be excluded
165 +#set($excludedSpacesString = "$!xcontext.macro.params.excludespaces")
166 +#set($excludedSpacesRaw = $excludedSpacesString.split(','))
167 +#set($excludedSpaces = [])
168 +#foreach($excludedSpacesElt in $excludedSpacesRaw)
169 + #set($excludedSpacesElt = $excludedSpacesElt.trim())
170 + #if("$!excludedSpacesElt" != "")
171 + #set($discard = $excludedSpaces.add($excludedSpacesElt))
172 + #end
173 +#end
123 123  ## the list of documents to exclude, if any
124 124  #set($excludeListString = "$!xcontext.macro.params.excludes")
125 125  #set($excludeListRaw = $excludeListString.split(','))
... ... @@ -131,6 +131,16 @@
131 131   #set($discard = $excludeList.add($excludedElt))
132 132   #end
133 133  #end
185 +## the list of the doccuments that will be displayed
186 +#set($displayedDocumentsString = "$!xcontext.macro.params.doclist")
187 +#set($displayedDocumentsRaw = $displayedDocumentsString.split(','))
188 +#set($displayedDocuments = [])
189 +#foreach($displayedDocElt in $displayedDocumentsRaw)
190 + #set($displayedDocElt = $displayedDocElt.trim())
191 + #if("$!displayedDocElt" != "")
192 + #set($discard = $displayedDocuments.add($displayedDocElt))
193 + #end
194 +#end
134 134  ## whether only roots of the tree should be shown or not
135 135  #set($onlyRoots = false)
136 136  #if("$!xcontext.macro.params.onlyroots" == "true" || "$!xcontext.macro.params.onlyroots" == "yes")
... ... @@ -191,6 +191,22 @@
191 191   #set($where = "doc.space = ?")
192 192   #set($discard = $paramsList.add($space))
193 193  #end
255 +## exclude spaces
256 +#if($excludedSpaces.size() > 0)
257 + #if($where.length() > 0)
258 + set($where = $where + ' and ')
259 + #end
260 + #set($where = $where + 'doc.space not in (')
261 + #foreach($excluded in $excludedSpaces)
262 + #if($velocityCount > 1)
263 + #set($where = $where + ', ')
264 + #end
265 + #set($where = $where + '?')
266 + #set($discard = $paramsList.add($excluded))
267 + #end
268 + #set($where = $where + ')')
269 +#end
270 +## exclude doccuments
194 194  #if($excludeList.size() > 0)
195 195   #if ($where.length() > 0)
196 196   #set($where = $where + ' and ')
... ... @@ -205,12 +205,49 @@
205 205   #end
206 206   #set($where = $where + ')')
207 207  #end
285 +
286 +#set($docLanguage = "$!xcontext.macro.params.documentLanguage")
287 +#if($docLanguage != '')
288 + #if ($where.length() > 0)
289 + #set($where = $where + ' and ')
290 + #end
291 + #if($docLanguage == $xwiki.getXWikiPreference('default_language'))
292 + #set($where = "${where} (doc.language = ? OR doc.language='') ")
293 + #else
294 + #set($where = "${where} doc.language = ? ")
295 + #end
296 + #set($discard = $paramsList.add($docLanguage))
297 +#end
208 208  #if($where.length() > 0)
209 209   #set($where = " where ${where}")
210 210  #end
211 211  #set($sql = "$selectFrom $where $order")
212 212  ## get the results
213 -#set($resultDocs = $xwiki.search($sql, $paramsList))
303 +#if("$!displayedDocuments" != "[]")
304 + #set($displayedDocumentsDoc = [])
305 + #foreach($element in $displayedDocuments)
306 + #set($buffer = [])
307 + #set($bufferDoc = $xwiki.getDocument($element))
308 + #set($discard = $buffer.add("$!bufferDoc"))
309 + #set($discard = $buffer.add("$!bufferDoc.parent"))
310 + #if($displayValue == 'fullName')
311 + #set($discard = $buffer.add("$!bufferDoc.fullName"))
312 + #elseif($displayValue == 'name')
313 + #set($discard = $buffer.add("$!bufferDoc.name"))
314 + #elseif($displayValue == 'title')
315 + #set($discard = $buffer.add("$!bufferDoc.title"))
316 + #end
317 + #set($discard = $displayedDocumentsDoc.add($buffer))
318 + #end
319 + #set($resultDocs = $displayedDocumentsDoc)
320 +#else
321 + #set($displayHidden = "$!xcontext.macro.params.displayHidden")
322 + #set($query = $services.query.hql($sql).bindValues($paramsList))
323 + #if($displayHidden != "true")
324 + #set($query = $query.addFilter("hidden"))
325 + #end
326 + #set($resultDocs = $query.execute())
327 +#end
214 214  ## prepare the tree
215 215  #set($childrenMap = {})
216 216  ## compute the title to be displayed and put it in the map
... ... @@ -227,7 +227,8 @@
227 227   ## filter the docs in the passed space and filter out the excludes from parents
228 228   #set($currentParent = $resultDoc.get(1))
229 229   #set($currentParentReference = $services.model.resolveDocument($currentParent, 'currentmixed', $currentReference))
230 - #if("$!currentParent" != "" && !$excludeList.contains($currentParent) && $currentParentReference.wikiReference.name.equals($xcontext.wiki) && ("$!space" == "" || $currentParentReference.lastSpaceReference.name.equals($space)))
344 + #set($currentParentSpace = $xwiki.getDocument("$currentParent").space)
345 + #if("$!currentParent" != "" && !$excludeList.contains($currentParent) && !$excludedSpaces.contains($currentParentSpace) && ($displayedDocuments.contains($currentParent) || $displayedDocuments.size() == 0 ) && $currentParentReference.wikiReference.name.equals($xcontext.wiki) && ("$!space" == "" || $currentParentReference.lastSpaceReference.name.equals($space)))
231 231   ## it's not an orphan, it has non-excluded parent in the current wiki and in the passed space
232 232   ## put it in his parent's children list
233 233   ## we'll get the parent by re-serializing the resolved reference,
XWiki.WikiMacroParameterClass[12]
Parameter name
... ... @@ -1,0 +1,1 @@
1 +documentLanguage
Parameter description
... ... @@ -1,0 +1,1 @@
1 +This parameter's value is used to display a tree of documents in the desired language.
Parameter mandatory
... ... @@ -1,0 +1,1 @@
1 +No
XWiki.WikiMacroParameterClass[13]
Parameter name
... ... @@ -1,0 +1,1 @@
1 +openNode
Parameter description
... ... @@ -1,0 +1,1 @@
1 +This parameter's value is used to restrict the hierarchy tree from displaying the whole tree expanded, instead it expands only the path from the root node to the specified document's node. 'openNode' parameter's value should specify the full name of the document for which the tree should expand its branch.
Parameter mandatory
... ... @@ -1,0 +1,1 @@
1 +No
XWiki.WikiMacroParameterClass[14]
Parameter default value
... ... @@ -1,0 +1,1 @@
1 +false
Parameter name
... ... @@ -1,0 +1,1 @@
1 +collapsed
Parameter description
... ... @@ -1,0 +1,1 @@
1 +This parameter's value is used to collapse the tree of documents.
Parameter mandatory
... ... @@ -1,0 +1,1 @@
1 +No
XWiki.WikiMacroParameterClass[15]
Parameter name
... ... @@ -1,0 +1,1 @@
1 +excludespaces
Parameter description
... ... @@ -1,0 +1,1 @@
1 +Comma separated list of spaces to exclude from the hierarchy display.
Parameter mandatory
... ... @@ -1,0 +1,1 @@
1 +No
XWiki.WikiMacroParameterClass[16]
Parameter name
... ... @@ -1,0 +1,1 @@
1 +doclist
Parameter description
... ... @@ -1,0 +1,1 @@
1 +Document list that will be displayed
Parameter mandatory
... ... @@ -1,0 +1,1 @@
1 +No
XWiki.WikiMacroParameterClass[17]
Parameter default value
... ... @@ -1,0 +1,1 @@
1 +false
Parameter name
... ... @@ -1,0 +1,1 @@
1 +displayHidden
Parameter description
... ... @@ -1,0 +1,1 @@
1 +Display the hidden documents
Parameter mandatory
... ... @@ -1,0 +1,1 @@
1 +No