Изменения документа Document Tree Macros
Редактировал(а) Андрей Ганьков 2026/01/23 10:50
От версии 3.1
отредактировано Андрей Ганьков
на 2023/04/03 09:34
на 2023/04/03 09:34
Изменить комментарий:
Install extension [org.xwiki.platform:xwiki-platform-index-tree-macro/15.2]
К версии 8.1
отредактировано Андрей Ганьков
на 2026/01/23 10:50
на 2026/01/23 10:50
Изменить комментарий:
Install extension [org.xwiki.platform:xwiki-platform-index-tree-macro/17.10.2]
Сводка
-
Свойства страницы (1 изменено, 0 добавлено, 0 удалено)
Подробности
- Свойства страницы
-
- Содержимое
-
... ... @@ -31,9 +31,15 @@ 31 31 #end 32 32 ## Handle relative references 33 33 #makeNodeReferencesAbsolute($docTreeConfig ['root', 'openTo']) 34 - ## Sort the child documents by (raw) title when the node label is the document title. 35 - #if ($docTreeConfig.showDocumentTitle) 36 - #set ($docTreeConfig.orderBy = 'title') 34 + ## FIXME: The 'orderBy' property of the tree API is shared by all tree node types, which means we can't indicate a 35 + ## different sort field per tree node type (e.g. sort wiki nodes by name and document nodes by last modification 36 + ## date). At the same time, this property is currently taken into account only for sorting document tree nodes, so for 37 + ## now we set its value to the specified document sort. In the future we may want to convert this into a map, where 38 + ## the key is the node type. 39 + #set ($docTreeConfig.orderBy = $docTreeConfig.sortDocumentsBy) 40 + ## Sort the child documents by (raw) title when the node label is the document title and there's no sort specified. 41 + #if ($docTreeConfig.showDocumentTitle && "$!docTreeConfig.orderBy" == '') 42 + #set ($docTreeConfig.orderBy = 'title:asc') 37 37 #end 38 38 ## Determine which hierarchy needs to be used. 39 39 #if ($docTreeConfig.showSpaces) ... ... @@ -76,7 +76,11 @@ 76 76 #macro (handleDocumentTreeRequest) 77 77 #if ($request.action) 78 78 #if ($services.csrf.isTokenValid($request.form_token)) 79 - $response.sendError(400, 'The specified action is not supported.') 85 + #if ($request.action == 'create' && $request.type == 'addDocument') 86 + #handleNewNodeCreationRequest() 87 + #else 88 + $response.sendError(400, 'The specified action is not supported.') 89 + #end 80 80 #elseif ($isAjaxRequest) 81 81 $response.sendError(403, 'The CSRF token is missing.') 82 82 #else ... ... @@ -102,6 +102,22 @@ 102 102 #end 103 103 #end 104 104 115 +#macro (handleNewNodeCreationRequest) 116 + #set ($cleanId = $stringtool.substring($request.id, $stringtool.length('document:'))) 117 + #set ($parentReference = $services.model.resolveDocument($cleanId)) 118 + #set ($requestedName = $request.name) 119 + #set ($transformedName = $services.modelvalidation.transformName($requestedName)) 120 + #set ($spaceReference = $services.model.createSpaceReference($transformedName, $parentReference.lastSpaceReference)) 121 + #set ($documentReference = $services.model.createDocumentReference('WebHome', $spaceReference)) 122 + #set ($data = []) 123 + #addDocumentNode($documentReference, $data) 124 + ## We want to allow opening the node to add another hierarchy. 125 + #set ($data[0].children = true) 126 + ## We want to display the actual requested name as node name. 127 + #set ($data[0].text = $requestedName) 128 + #jsonResponse($data) 129 +#end 130 + 105 105 #macro (postProcessDocumentTreeData $data) 106 106 ## This is just a hook to allow post processing the document tree data. 107 107 #end ... ... @@ -126,6 +126,8 @@ 126 126 #set ($limit = $mathtool.max($numbertool.toNumber($request.limit).intValue(), 1)) 127 127 #if ("$!limit" == '') 128 128 #set ($limit = 15) 155 + #else 156 + #validateQueryLimit($limit) 129 129 #end 130 130 #if ($nodeId == '#' && $docTreeConfig.showRoot) 131 131 #maybeAddNode($actualNodeId $children) ... ... @@ -179,6 +179,7 @@ 179 179 180 180 #macro (maybeAddFarmNode $nodeReference $siblings) 181 181 #set ($farmHomeReference = $services.model.resolveDocument('', 'default')) 210 + #set ($isOpened = $docTreeConfig.expandToLevel > 0) 182 182 #set ($discard = $siblings.add({ 183 183 'id': 'farm:*', 184 184 'text': 'Farm', ... ... @@ -188,6 +188,9 @@ 188 188 'type': 'farm', 189 189 'validChildren': ['wiki', 'pagination'] 190 190 }, 220 + 'state': { 221 + 'opened': $isOpened 222 + }, 191 191 'a_attr': { 192 192 'href': $xwiki.getURL($farmHomeReference) 193 193 } ... ... @@ -216,6 +216,7 @@ 216 216 #else 217 217 #set ($label = $wiki.id) 218 218 #end 251 + #set ($isOpened = $docTreeConfig.expandToLevel > 0) 219 219 #set ($discard = $siblings.add({ 220 220 'id': "wiki:$wiki.id", 221 221 'text': $label, ... ... @@ -227,6 +227,9 @@ 227 227 'validChildren': ['space', 'document', 'pagination'], 228 228 'canDelete': $canDeleteWiki 229 229 }, 263 + 'state': { 264 + 'opened': $isOpened 265 + }, 230 230 'a_attr': { 231 231 'href': $xwiki.getURL($wiki.mainPageReference) 232 232 } ... ... @@ -252,6 +252,7 @@ 252 252 253 253 #macro (addSpaceNode $spaceReference $siblings) 254 254 #set ($spaceId = $services.model.serialize($spaceReference, 'default')) 291 + #set ($spaceNodeId = "space:$spaceId") 255 255 #set ($hasSpaceAdmin = $services.security.authorization.hasAccess('admin', $spaceReference)) 256 256 #set ($canViewSpace = $services.security.authorization.hasAccess('view', $spaceReference)) 257 257 #if ($docTreeConfig.showTerminalDocuments) ... ... @@ -259,10 +259,21 @@ 259 259 #set ($hasChildren = true) 260 260 #else 261 261 ## We display only the nested spaces. This space might contain only documents. 262 - #set ($hasChildren = $tree.getChildCount( "space:$spaceId") > 0)299 + #set ($hasChildren = $tree.getChildCount($spaceNodeId) > 0) 263 263 #end 301 + #set ($isOpened = false) 302 + #if ("$!docTreeConfig.expandToLevel" != '') 303 + #set ($rootNode = "wiki:$services.wiki.currentWikiId") 304 + #if ("$!docTreeConfig.root" != '') 305 + #set ($rootNode = "wiki:$services.wiki.currentWikiId") 306 + #else 307 + #set ($rootNode = $docTreeConfig.root) 308 + #end 309 + #set ($rootDistance = $tree.getPath($spaceNodeId).size()) 310 + #set ($isOpened = ($rootDistance != -1 && $docTreeConfig.expandToLevel >= $rootDistance)) 311 + #end 264 264 #set ($discard = $siblings.add({ 265 - 'id': "space:$spaceId",313 + 'id': $spaceNodeId, 266 266 'text': $spaceReference.name, 267 267 'icon': 'fa fa-folder-o', 268 268 'iconOpened': 'fa fa-folder-open-o', ... ... @@ -280,6 +280,9 @@ 280 280 'createDocumentURL': $xwiki.getURL($spaceReference, 'create', $NULL), 281 281 'deleteURL': $xwiki.getURL($spaceReference, 'deletespace', $NULL) 282 282 }, 331 + 'state': { 332 + 'opened': $isOpened 333 + }, 283 283 'a_attr': { 284 284 'href': $xwiki.getURL($spaceReference) 285 285 } ... ... @@ -305,6 +305,7 @@ 305 305 306 306 #macro (addDocumentNode $documentReference $siblings) 307 307 #set ($documentId = $services.model.serialize($documentReference, 'default')) 359 + #set ($docNodeId = "document:$documentId") 308 308 #set ($label = $documentReference.name) 309 309 #if (!$docTreeConfig.showSpaces && 310 310 $documentReference.name == $services.model.getEntityReference('DOCUMENT', 'default').name) ... ... @@ -321,9 +321,11 @@ 321 321 #set ($label = $plainTitle) 322 322 #end 323 323 #end 324 - #set ($hasChildren = $tree.getChildCount("document:$documentId") > 0) 376 + #set ($hasChildren = $tree.getChildCount($docNodeId) > 0) 377 + #set ($isOpened = false) 378 + #computeIsOpened($docNodeId $isOpened) 325 325 #set ($discard = $siblings.add({ 326 - 'id': "document:$documentId",380 + 'id': $docNodeId, 327 327 'text': $label, 328 328 'icon': 'fa fa-file-o', 329 329 'children': $hasChildren, ... ... @@ -338,6 +338,9 @@ 338 338 'canCopy': $canViewDoc, 339 339 'createDocumentURL': $xwiki.getURL($documentReference, 'create', $NULL) 340 340 }, 395 + 'state': { 396 + 'opened': $isOpened 397 + }, 341 341 'a_attr': { 342 342 'href': $xwiki.getURL($documentReference) 343 343 } ... ... @@ -352,14 +352,18 @@ 352 352 #end 353 353 354 354 #macro (addAddDocumentNode $documentReference $siblings) 412 + ## FIXME: This URL is wrong, it should use the $documentReference as the parent for creation of the node: 413 + ## the reference is already an existing doc, so it shouldn't be the one used for creation. 355 355 #set ($discard = $siblings.add({ 356 356 'id': "addDocument:$services.model.serialize($documentReference, 'default')", 357 - 'text': 'New page...',416 + 'text': $services.localization.render('index.documentTree.addDocument'), 358 358 'icon': 'fa fa-plus-circle', 359 359 'children': false, 360 360 'data': { 361 361 'type': 'addDocument', 362 - 'validChildren': [] 421 + 'validChildren': [], 422 + 'hasContextMenu': true, 423 + 'canRename': true 363 363 }, 364 364 'a_attr': { 365 365 'href': $xwiki.getURL($documentReference, 'create') ... ... @@ -378,9 +378,27 @@ 378 378 #end 379 379 #end 380 380 442 +#macro (computeIsOpened $docNodeId $result) 443 + #set ($isOpened = false) 444 + #if ("$!docTreeConfig.expandToLevel" != '') 445 + #set ($rootNode = "wiki:$services.wiki.currentWikiId") 446 + #if ("$!docTreeConfig.root" != '') 447 + #set ($rootNode = "wiki:$services.wiki.currentWikiId") 448 + #else 449 + #set ($rootNode = $docTreeConfig.root) 450 + #end 451 + #set ($rootDistance = $tree.getPath($docNodeId).size()) 452 + #set ($isOpened = ($rootDistance != -1 && $docTreeConfig.expandToLevel >= $rootDistance)) 453 + #end 454 + #setVariable("$result" $isOpened) 455 +#end 456 + 381 381 #macro (addTranslationsNode $documentReference $siblings) 382 - #set ($discard = $children.add({ 383 - 'id': "translations:${documentReference}", 458 + #set ($isOpened = false) 459 + #set ($docNodeId = "translations:${documentReference}") 460 + #computeIsOpened($docNodeId $isOpened) 461 + #set ($discard = $siblings.add({ 462 + 'id': $docNodeId, 384 384 'text': 'Translations', 385 385 'icon': 'fa fa-language', 386 386 'children': true, ... ... @@ -388,6 +388,9 @@ 388 388 'type': 'translations', 389 389 'validChildren': ['translation'], 390 390 'canDelete': $services.security.authorization.hasAccess('delete', $documentReference) 470 + }, 471 + 'state': { 472 + 'opened': $isOpened 391 391 } 392 392 })) 393 393 #end ... ... @@ -404,8 +404,11 @@ 404 404 405 405 #macro (addTranslationNode $translationReference $siblings) 406 406 #set ($currentLocale = $services.localization.currentLocale) 489 + #set ($isOpened = false) 490 + #set ($docNodeId = "translation:$services.model.serialize($translationReference, 'default')_$translationReference.locale") 491 + #computeIsOpened($docNodeId $isOpened) 407 407 #set ($discard = $siblings.add({ 408 - 'id': "translation:$services.model.serialize($translationReference, 'default')_$translationReference.locale",493 + 'id': $docNodeId, 409 409 'text': $translationReference.locale.getDisplayName($currentLocale), 410 410 'icon': 'fa fa-file-text-o', 411 411 'children': false, ... ... @@ -416,6 +416,9 @@ 416 416 }, 417 417 'a_attr': { 418 418 'href': $xwiki.getURL($translationReference) 504 + }, 505 + 'state': { 506 + 'opened': $isOpened 419 419 } 420 420 })) 421 421 #end ... ... @@ -432,8 +432,11 @@ 432 432 #end 433 433 434 434 #macro (addAttachmentsNode $documentReference $siblings) 523 + #set ($isOpened = false) 524 + #set ($docNodeId = "attachments:${documentReference}") 525 + #computeIsOpened($docNodeId $isOpened) 435 435 #set ($discard = $siblings.add({ 436 - 'id': "attachments:${documentReference}",527 + 'id': $docNodeId, 437 437 'text': 'Attachments', 438 438 'icon': 'fa fa-paperclip', 439 439 'children': true, ... ... @@ -445,6 +445,9 @@ 445 445 }, 446 446 'a_attr': { 447 447 'href': $xwiki.getURL($documentReference, 'view', 'viewer=attachments') 539 + }, 540 + 'state': { 541 + 'opened': $isOpened 448 448 } 449 449 })) 450 450 #end ... ... @@ -464,8 +464,11 @@ 464 464 #set ($attachmentId = $services.model.serialize($attachmentReference, 'default')) 465 465 #set ($canEditDoc = $services.security.authorization.hasAccess('edit', $attachmentReference.parent)) 466 466 #getAttachmentIcon($attachment $icon) 561 + #set ($isOpened = false) 562 + #set ($docNodeId = "attachment:$attachmentId") 563 + #computeIsOpened($docNodeId $isOpened) 467 467 #set ($discard = $siblings.add({ 468 - 'id': "attachment:$attachmentId",565 + 'id': $docNodeId, 469 469 'text': $attachment.filename, 470 470 'icon': $icon, 471 471 'children': false, ... ... @@ -484,6 +484,9 @@ 484 484 }, 485 485 'a_attr': { 486 486 'href': $attachment.document.getAttachmentURL($attachment.filename) 584 + }, 585 + 'state': { 586 + 'opened': $isOpened 487 487 } 488 488 })) 489 489 #end ... ... @@ -562,8 +562,11 @@ 562 562 #end 563 563 564 564 #macro (addClassPropertiesNode $documentReference $siblings) 565 - #set ($discard = $children.add({ 566 - 'id': "classProperties:${documentReference}", 665 + #set ($isOpened = false) 666 + #set ($docNodeId = "classProperties:${documentReference}") 667 + #computeIsOpened($docNodeId $isOpened) 668 + #set ($discard = $siblings.add({ 669 + 'id': $docNodeId, 567 567 'text': 'Class Properties', 568 568 'icon': 'fa fa-gears', 569 569 'children': true, ... ... @@ -571,6 +571,9 @@ 571 571 'type': 'classProperties', 572 572 'validChildren': ['classProperty'], 573 573 'canDelete': $services.security.authorization.hasAccess('edit', $documentReference) 677 + }, 678 + 'state': { 679 + 'opened': $isOpened 574 574 } 575 575 })) 576 576 #end ... ... @@ -603,8 +603,11 @@ 603 603 #if (!$icon) 604 604 #set ($icon = 'gear') 605 605 #end 712 + #set ($isOpened = false) 713 + #set ($docNodeId = "classProperty:$classPropertyId") 714 + #computeIsOpened($docNodeId $isOpened) 606 606 #set ($discard = $siblings.add({ 607 - 'id': "classProperty:$classPropertyId",716 + 'id': $docNodeId, 608 608 'text': $property.name, 609 609 'icon': "fa fa-$icon", 610 610 'children': false, ... ... @@ -612,6 +612,9 @@ 612 612 'id': $classPropertyId, 613 613 'type': 'classProperty', 614 614 'validChildren': [] 724 + }, 725 + 'state': { 726 + 'opened': $isOpened 615 615 } 616 616 })) 617 617 #end ... ... @@ -628,8 +628,11 @@ 628 628 #end 629 629 630 630 #macro (addObjectsNode $documentReference $siblings) 631 - #set ($discard = $children.add({ 632 - 'id': "objects:${documentReference}", 743 + #set ($isOpened = false) 744 + #set ($docNodeId = "objects:${documentReference}") 745 + #computeIsOpened($docNodeId $isOpened) 746 + #set ($discard = $siblings.add({ 747 + 'id': $docNodeId, 633 633 'text': 'Objects', 634 634 'icon': 'fa fa-cubes', 635 635 'children': true, ... ... @@ -637,6 +637,9 @@ 637 637 'type': 'objects', 638 638 'validChildren': ['objectsOfType'], 639 639 'canDelete': $services.security.authorization.hasAccess('edit', $documentReference) 755 + }, 756 + 'state': { 757 + 'opened': $isOpened 640 640 } 641 641 })) 642 642 #end ... ... @@ -647,8 +647,11 @@ 647 647 #set ($documentReference = $services.model.resolveDocument($parts.get(0))) 648 648 #set ($classReference = $services.model.resolveDocument($parts.get(1))) 649 649 #if ($services.security.authorization.hasAccess('view', $documentReference)) 650 - #set ($discard = $children.add({ 651 - 'id': "objectsOfType:$documentReference/$classReference", 768 + #set ($isOpened = false) 769 + #set ($docNodeId = "objectsOfType:$documentReference/$classReference") 770 + #computeIsOpened($docNodeId $isOpened) 771 + #set ($discard = $siblings.add({ 772 + 'id': $docNodeId, 652 652 'text': $services.model.serialize($classReference, 'local'), 653 653 'icon': 'fa fa-cubes', 654 654 'children': true, ... ... @@ -656,6 +656,9 @@ 656 656 'type': 'objectsOfType', 657 657 'validChildren': ['object', 'pagination'], 658 658 'canDelete': $services.security.authorization.hasAccess('edit', $documentReference) 780 + }, 781 + 'state': { 782 + 'opened': $isOpened 659 659 } 660 660 })) 661 661 #end ... ... @@ -682,8 +682,11 @@ 682 682 683 683 #macro (addObjectNode $object $objectReference $siblings) 684 684 #set ($objectId = $services.model.serialize($objectReference, 'default')) 685 - #set ($discard = $children.add({ 686 - 'id': "object:$objectId", 809 + #set ($isOpened = false) 810 + #set ($docNodeId = "object:$objectId") 811 + #computeIsOpened($docNodeId $isOpened) 812 + #set ($discard = $siblings.add({ 813 + 'id': $docNodeId, 687 687 'text': "[$object.number]", 688 688 'icon': 'fa fa-cube', 689 689 'children': true, ... ... @@ -692,6 +692,9 @@ 692 692 'type': 'object', 693 693 'validChildren': ['objectProperty'], 694 694 'canDelete': $services.security.authorization.hasAccess('edit', $objectReference.parent) 822 + }, 823 + 'state': { 824 + 'opened': $isOpened 695 695 } 696 696 })) 697 697 #end ... ... @@ -716,8 +716,11 @@ 716 716 #end 717 717 #set ($objectPropertyReference = $services.model.createEntityReference($property.name, 'OBJECT_PROPERTY', $objRef)) 718 718 #set ($objectPropertyId = $services.model.serialize($objectPropertyReference, 'default')) 849 + #set ($isOpened = false) 850 + #set ($docNodeId = "objectProperty:$objectPropertyId") 851 + #computeIsOpened($docNodeId $isOpened) 719 719 #set ($discard = $siblings.add({ 720 - 'id': "objectProperty:$objectPropertyId",853 + 'id': $docNodeId, 721 721 'text': $property.name, 722 722 'icon': "fa fa-$icon", 723 723 'children': false, ... ... @@ -725,6 +725,9 @@ 725 725 'id': $objectPropertyId, 726 726 'type': 'objectProperty', 727 727 'validChildren': [] 861 + }, 862 + 'state': { 863 + 'opened': $isOpened 728 728 } 729 729 })) 730 730 #end ... ... @@ -1122,6 +1122,7 @@ 1122 1122 #macro (searchAttachmentsSolr $text $limit $return) 1123 1123 #set ($params = [ 1124 1124 'fq=type:ATTACHMENT', 1261 + 'fq=locale:*', 1125 1125 'qf=filename^4 attcontent', 1126 1126 'fl=type wiki spaces name filename' 1127 1127 ])