Writing User Macro to list children of page limited by label - Where can I find Confluence Methods?

I'm attempting to write a user macro that creates a table of children pages limited by a label parameter. Here's the outline that I have so far:

## @param Label:title=Label|type=string|desc=Label|required=true

<table>
#foreach (CHID OF THE CURRENT PAGE)
	#if ($child.label == $parmlabel)
		<tr>
			<td>
				$child.TITLE
			</td>
			<td>
				$child.AUTHOR
			</td>
			<td>
				$child.DATEMODIFIED
			</td>
		</tr>
	#end
#end
</table>

The stuff in caps are just placeholders, as I can't find any documentation on confluence methods that might help me loop through each child of the current page. Additionally, I'm not sure of the exact terminology to access the information for those children. I'm new to coding, so I'm excited to kind of figure it out myself... Could someone point me in the right direction?

Thanks,

Alana

6 answers

1 accepted

This widget could not be displayed.
I'm not an expert but here's something I've come up with.
  1. Take a look at https://confluence.atlassian.com/display/DOC/Guide+to+User+Macro+Templates
  2. There's $content object of type ContentEntityObject and link to API docs.
  3. Traverse direct known subclasses: SpaceContentEntityObject > AbstractPage > Page.
  4. There're getChildren() and getLabels() methods there.

This will hopefully list chidlren and labels.

#foreach ($child in $content.children)
  <p>${child.title}: ${child.labels}</p>
#end

${content.children} is shortcut for ${content.getChildren()}

Do you think something like this would work to filter the children by label?

## @param Label:title=Label|type=string|desc=Label|required=true
 
<table>
#foreach ($child in $content.children)
	#if ($parmlabel in $child.labels)
		<tr>
			<td>${child.getTitle()}</td>
		</tr>
	#end
#end
</table>

Also, any insight on the methods to get author and date-modified?

Thanks again!

## @param label:title=Label|type=string|desc=Label|required=true

<table>
#foreach ($child in $content.children)
  #foreach ($label in $child.labels)
    #if ($label.name == $paramlabel)
      <tr>
        <td>${child.title}</td>
        <td>${child.creator.fullName}</td>
        <td>${child.lastModificationDate}</td>
      </tr>
    #end
  #end
#end
</table>

This may work. But I'm not an expert. I'm not sure about all the edge cases and implications like page restrictions and personal labels and so on.

Thanks! Very helpful! Now the only thing I need to figure out is how to get the title to link to the actual page and the author's name to link to their profile...

Something like this?

## @param label:title=Label|type=string|desc=Label|required=true
<table>
#foreach ($child in $content.children)
  #foreach ($label in $child.labels)
    #if ($label.name == $paramlabel)
      <tr>
        <td><ac:link><ri:page ri:content-title="${generalUtil.escapeXml($child.title)}" /></ac:link></td>
        <td><ac:link><ri:user ri:username="${child.creator.name}" /></ac:link></td>
        <td>${child.lastModificationDate}</td>
      </tr>
    #end
  #end
#end
</table>

This widget could not be displayed.

I've been working on something similar lately.

My macro however uses a list in stead of a table, but this could easily be fixed.

My macro has extra parameters, so you can create a list based on another page's childpages.

It also allows to look at decendants.

Here is the macro:

## Macro name: tbh_pagelist_by_label

## Macro title: Page list by label

## Macro has a body: N

## Body processing: Selected body processing option

## Output: Selected output option

##

## Developed by: Tom Birch Hansen 

## Date created: 2014-04-30

## Installed by:  ---

## Use this to list pages from children or decendents of a page that match specified labels. 

## @param Label:title=Label|type=string|required=true|desc=type label(s) to be present in child pages. Use comma to list multiple labels (pages with any of the labels will be shown)

## @param page:title=Page|type=confluence-content|required=false|desc=type page to start from. Leave blank for current page.

## @param from:title=From|type=enum|enumValues=decendants,children,children_sorted|required=true|desc=Show pages from

## @param showicon:title=Show icon|type=boolean|desc=Show icon next to page link?

## @param showspace:title=Show spacename|type=boolean|desc=Show spacename in list?

## @param class:title=Class|type=string|desc=Optional formatting using a http class for the html ul element 

##PROCESS THE label PARAMETER:

#set($pLabelArray=$paramLabel.split(","))







## PROCESS THE page PARAMETER, if empty then set to current page

#if (!$parampage || $parampage=="")

	#set($ppage=$content.getEntity())

#else

        ## get page object deducted from the page parameter

	#set ($colonpos=$parampage.indexOf(":",0))

	#if($colonpos==-1)

		#set ($xspacekey=$content.spaceKey)

		#set ($xpagename=$parampage)

	#else

		#set ($namepos=$colonpos+1)

		#set ($xspacekey=$parampage.substring(0,$parampage.indexOf(":",0)))

		#set ($xpagename=$parampage.substring($namepos))

		#end

	## get page manager...

	#set($containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager'))

	#set($getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null))

	#set($containerManager=$getInstanceMethod.invoke(null,null))

	#set($containerContext=$containerManager.containerContext)

	#set($pageManager=$containerContext.getComponent('pageManager'))

	## find page...

	#if ($pageManager)

		#set ($ppage= $pageManager.getPage($xspacekey, $xpagename))

		#end

	#end



## PROCESS THE from PARAMETER:

#if ($paramfrom=="children_sorted")

       #set ($objfrom=$ppage.getSortedChildren())

#elseif ($paramfrom=="children")

       #set ($objfrom=$ppage.getChildren())

#elseif ($paramfrom=="decendants")

       #set ($objfrom=$ppage.getDescendents())

       #end



## PROCESS THE class PARAMETER. set default if empty

#if (!$paramclass)

	#set($pclass="content-by-label")

        #end

#set($count = 0)

#set($showpage = 0)

<ul class="$pclass">

    #foreach ($child in $objfrom)

      #if ($count < 100) ## just display the 1st 100

                #set ($showpage=0)

		#foreach ( $label in $child.getLabels() )

			#foreach($pLabel in $pLabelArray)

                            #if  ( ($label==$pLabel) )

				#set ($showpage=1)

			        #end

                            #end

                            ## END FOR EACH labelarray

                        ##if  ( ($label==$pLabel) )

				##set ($showpage=1)

			##end

		#end

		## END FOR EAACH LABEL

		

		#if ($showpage==1)

		    <li>

			##<a href="$req.contextPath$child.urlPath"><strong>$webwork.htmlEncode($child.displayTitle)</strong></a>

			#contentLink2($child $paramshowicon $paramshowspace)

        </li>

		#end

        #set($count = $count + 1)

      #end

    #end

</ul>

Hi Tom,

thank you for that handy macro. While using it (unchanged at the moment) i stumbled over a stange behaviour that I can't explain.

Wenn reporting on a page (in that case the space homepage) and all it's descendant I only get a list of some, but some are missing.

If the same thing is applied via the regular search (with same parameters, search in the space, with the space homepage as root and in all descendant pages that have a certain label) I get more results.

Do you know any occurence of that behaviour or do you have any idea where to look to fix this?

Best regards,
Ben

This widget could not be displayed.

Hi Alana,

maybe you want something like that. You can modify it up to your requirements:

{report-block}
  {content-filter:type=page,comment,news}
  {content-reporter:scope=@self > children}
    {text-sort:content:title}
  {content-reporter}
  {report-body}
h2. {report-info:content:title|link=true}
    {expand:title=Show more...}
        {report-info:content:body|render=wiki}
    {expand}
  {report-body}
{report-block}

You should be able to get author and datemodified, but I'm not sure at the moment.

Hope this helps,

Mario

This widget could not be displayed.

Hi Alana,

I don't think what you desire can be achieved with a user macro since you don't have the required context available. Instead, you should write a Confluence Macro like described in the official documentation.

Regards, Felix

This widget could not be displayed.

Mario,

Can you explain what's going on in that code? Does it require an additional plugin to work?

Thanks,

Alana

This widget could not be displayed.

Hi Alana,

sorry for the late reply.

Yes. You require the "Reporting Plugin". https://marketplace.atlassian.com/plugins/net.customware.confluence.plugin.reporting/versions

But i am not sure, if this can display author and modified-date. Maybe you can find something in the documentation:
https://docs.servicerocket.com/display/REPORT/Include+All+Child+Pages

The script above includes all child pages with title(+link) and expandable page content.

Cheers,

Mario

Suggest an answer

Log in or Sign up to answer
Community showcase
Posted Monday in Confluence

Why start from scratch? Introducing four new templates for Confluence Cloud

Hi my Community friends!  For those who don't know me, I'm a product marketer on the Confluence Cloud team - nice to meet you! For those of you who do, you know that I've been all up in your Co...

400 views 4 6
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you