Dashboard > Atlassian Plugins > ... > Macros > report-on
  Atlassian Plugins Log In | Sign Up   View a printable version of the current page.  
  report-on

Added by David Peterson , last edited by David Peterson on Mar 04, 2008  (view change) show comment
Labels: 

{report-on}

Plugin: Reporting Plugin

Sets the report item context to the item/key value specified.

Description

This is useful when you wish to display several key values from a sub-item of the item currently being reported on. For example, you may wish to the full name and email address of the current page's last modifier:

{report-on:content:modifier}
Last Modifier: {report-info:user:full name|link=true} ({report-info:user:email|link=true})
{report-on}

Also, it will automatically loop multiple values if the supplied key is a collection or iterator, rendering the contents against each item.

Usage

{report-on:item:key}
Sub-Item 1: {report-info:item:subkey 1}<br/>
Sub-Item 2: {report-info:item:subkey 2}<br/>
{report-on}

Parameters

Name Required Default Description
[default]/key
@self
The key value to display. Defaults to '@self' (Since 2.0.0).
default
The contents of this parameter will be used if the item/key is empty. It will be rendered as wiki text. Alternately, the body of macro can also be used, if more complex wiki text is required.
separator
comma
If the item/key points to a list of results, the type of separator to display between each item. May be one of the following:
  • bracket - Square brackets ('[', ']') surrounding each item.
  • brace - Braces ('{', '}') surrounding each item.
  • comma - A comma (',') between each item.
  • paren - Parentheses ('(', ')') surrounding each item.
  • pipe - A pipe ('|') between each item.
  • newline - A line break after each item.
  • "custom" - Any other character you wish, specified between quotes.
injected
false
(Since 2.0.0) If set to true, the body will have any '%prefix:keychain%' values injected with values from the current item prior to being rendered. If the current value being reported on is a collection, the injection will happen on each collection item as it is processed.

See Also

A quick question:

I have yet to work out how to do what traditional MIS programmers refer to as "breaks" – the interruption of the flow of a report to print subheadings when higher-level sort-field values change.

Example: For a report on wiki users that I want to sort by ZIP code so as to enable geographic groupings, I might do something that looked like

{report-block}
    {user-reporter:group=mygroup-users}
      {text-sort:personal space > home page > data:zip code}
      {text-sort:full name}
    {user-reporter}
    {report-header}|| ZIP Code || Name ||{report-header}
    {report-body}
      | {report-info:personal space > home page > data:zip code} | {report-user:full name} |
    {report-body}
  {report-block}

(and why does the first line of a {code} macro body _never line up right?)

Now, if I wanted to put the zip code field in a subheader displayed only when the value changed instead of on every line, where do I begin? Do I have a way to express a key value naming the list of users whose home pages contain a metadata value named zip code?

I can't think of any way at present. Two yet-to-be implemented features would probably help you out - allowing report variables and allowing keychains in regular parameter values. Then you could do something like (syntax yet to be defined):

{report-block}
    {user-reporter:group=mygroup-users}
      {text-sort:personal space > home page > data:zip code}
      {text-sort:full name}
    {user-reporter}
    {report-header}|| ZIP Code || Name ||{report-header}

    {text-filter:report:variables > last zip code|exclude=%personal space > home page > data:zip code%}
    {report-body}
      | {report-info:personal space > home page > data:zip code} | {report-user:full name} |
      {report-variable:last zip code|value=%personal space > home page > data:zip code%}
    {report-body}

    {text-filter:report:variables > last zip code|include=%personal space > home page > data:zip code%}
    {report-body}
      |  | {report-user:full name} |
    {report-body}

{report-block}

Even looking at the above it's pretty ugly. I'm still working on exactly how some of the conditional/variable code should work...

Eeewww...

Ugglissimo. I wouldn't mind if you deleted this series of comments to save embarassment; that would be a major step backwards, and I do mean major. Are you guys all so young, and so CS-oriented, that you never worked with database report languages like Informix's ACE, and haven't even heard of RPG?

For that matter, what about your "legendary" commitment to de-geeking your user interfaces? It had to be compromised to a degree to get something as useful as these plugins (Reporting, Scaffolding et al), and I'm grateful that you did it, or I'd have torn all my hair out by now. But you needn't compromise it further for this.

This problem was canned decades ago; as a C programmer on Unix systems 20-odd years ago, I earned the gratitude of the former mainframe-applications people I worked with on one project when I created a simple library routine that took an ordered list of structures with pointers to the sort fields and functions to call when their values changed – they were relieved that finally, someone had given this dark and dangerous world of lower-case programming languages, pointers and serial terminals some of the comforts of home they had enjoyed for years.

Enough chastising and bragging (especially since it may just be based on misunderstanding you ); it's very simple – put all that variable glop inside the plugin:

  • create a new macro, e.g. {break-header}, with the sort field's keychain as a required parameter, whose body will be rendered as the heading text before the next record just as {report-header} does before the entire report.
    • Some thought may need to be given to how to specify the behavior in a {report-table} context.
    • perhaps an error should result if the key does not appear in an {xxx-sort} macro call in a reporter currently in context...?
  • wherever individual records are output, arrange to keep copies of the {break-header} key values and, starting from the highest-level sort key:
    • compare to previous value
    • if different (not necessarily in this order):
      • store the new value
      • render the associated body
      • clear the value of the next-lower-level sort key to force it to do the same

Simple, n'est-ce pas? As a little bit of syntactic sugar for further de-geeking, create yet another macro to do nothing but create an alias for that cognitive offense you call a keychain - possibly nothing more than something that creates another temporary keychain with a non-required prefix (checking first to see if it duplicates an existing one) so as to pass Radeox's syntactic gates into macro-parameterland without getting shredded. Maybe make a version with a body, and you can even fulfill your masochistic death wish for arbitrary variable declarations, although now that I think of it you've already got that with scaffolding {xxx-data} macros, 'aven'tcher?

A final note: My question about referring to referring to a path back from a key value to objects that contained it may have thrown you off – my approach to a solution entailed a report that began by listing only ZIP codes, which would (hopefully, though experimentally it seems otherwise) render the report body only once for each distinct ZIP code value. From there, I would attempt to use {report-on} to set the context to that report item, but of course there was no user associated with that value...

Hi Brian,

I can't speak for the rest of the company, but I personally hadn't ever heard of ACE or RPG (at least not in a database/reporting context). I like to think of the reasons being more related to opportunity and need rather than age and orientation. And it's Atlassian who makes the legendary commitments - we just do our best given time and resource constraints.

In any case, essentially what you're suggesting is building 'group by' functionality into the reports. How about something like this (I've taken the liberty of converting your code to a report-table, since that's what you seem to be generating anyway):

{report-table}
    {user-reporter:group=mygroup-users}
      {text-sort:personal space > home page > data:zip code}
      {text-sort:full name}
    {user-reporter}

    {report-column:title=ZIP Code|groupBy=personal space > home page > data:zip code}{report-info:personal space > home page > data:zip code}{report-column}

    {report-column:title=Name}{report-info:full name}{report-column}

{report-block}

This would then have the column generator check the 'groupBy' key chain to monitor changes and will automatically 'row span' (or at least output blank rows - row spanning will be tricky with the current output algorithm, which doesn't really allow for reading ahead) until the 'groupBy' value changes. In the case of other report types, the {report-body} would simply not be output for repeat occurrences of the 'groupBy' value.

Yes, the long keychain to get to the zip code is still ugly, but I would argue that is an artifact of the data storage mechanism, not reporting per-sê.

And with regards to the 'cognitive offense' which are keychains, I'm happy to hear suggestions for less offensive alternatives. Aliases are a possibility, although I'm not sure they actually make things that much clearer anyway. If you'd like to see them, create a feature request with the details.

Variables are still a suggestion I'm not convinced about either. The initial suggestion was that they allow some more complex reporting to take place (eg. collating the values for a bunch of items, etc). I can see some value in them, but agree that your use case is common enough that making it simple is a good idea. Scaffolding values don't work here, since they are stored at the page level, while these values are only useful within a specific report. Performance-wise using Scaffolding would be a pretty big hit also.

With regards to your final note, what you're after there is adding a 'uniqueness' filter to reporters, so that they only list each value once. Again, not unreasonable, feel free to create a feature request. Finding the user again would have to be done with an internal report listing all users and filtering to only those who's zip matches the current one in the outer report. Not exactly efficient. But there is no way to back-track a keychain lookup - once you have the final value, there is no way to tell how we found it...

View the rest of this thread  |  3 more comments by 2 persons

Further to this I've created a couple of feature requests related to the above issues:

I'll let you add the alias idea. Feel free to post a request to improve the keychain situation - practical suggestions on how are most appreciated.

Hi,
got a problem with these markup.

{list-data:ldTEST}
{content-options:parent=markets}
{list-data}
{report-on:injected=true}{add-label:%data:ldTEST%}{report-on}

This should add a label out of a list. Now it only adds the reference. I tried sth. like that:

{report-on:injected=true}{add-label:%data:ldTEST>reference:value%}{report-on}

but it doesn't work.
What i'am doing wrong ?

I know that i can use replace-and-render but that's not what i want.

I'm not quite sure what you mean by it 'only adds the reference'. However, the 'reference:value' will be a ContentEntityObject, specifically a page, so I'm not certain what will be displayed. I would have expected that it would be the page title, but I'm not 100% certain. If you want to be sure, try this:

%data:ldTEST>reference:value>content:title%

You will still potentially have the issue of page titles not being valid label names, which could also be a contributing issue.

ah great, that works

 i got the pageid instead of the title. e.g. 2233021

I've used the following syntax to retrieve data from the parent page:

 {report-on:content:parent|injected=true}%data:VariableName%{report-on}

Is there an equivalent syntax which uses a named page rather than the content:parent key.  I'm trying to display a variable that the report-info macro is refusing to pick up (for no known reason) and I thought this might be a solution.

Sure. Try something like this:

{report-on:@self|source=Some Other Page|injected=true}%data:VariableName%{report-on}

The '@self' is just saying use the page itself as the base context to work in. You could supply any other supported key in that context if you so desired.



Updated by Jon Want
May 28, 2008 18:39

Thanks, that seems to work, although I'm getting the same issue I was getting with report-info in that some variables work, some do not.

I have a page that is referencing 10 eval-data variables from another page. 5 work correctly, 4 return no values at all and the other returns an incorrect value - this particular one is a combination of two of the other referenced variables which is evaluated in the source page correctly, but in the reporting page it seems to be treating one of the underlying values as zero.

This is very frustrating - any help would be appreciated.

Hmm. It's possible that the {eval-data} values are being calculated in an arbitrary order. That would potentially screw up any evaluations which are dependent on the results of other evaluations.

Could you please create a bug report with the details of your page containing the {eval-data} macros and we'll take it from there.

Hi

I'm trying to report on a data page that has a nested table-data within a repeating-data group.  I think I need to use a report-on macro within the column of a report-table, but I'm not sure of the syntax to use.

The repeating-data provides details of Actions and the table-data provides the progress made on those actions (ActionProgress) and I'd like to list out the data from ActionProgress for each Action in a column in my report-table.

Thanks

Jon

If you're not interested in specific data about each 'table-data' row being displayed individually, you can use the expand-on macro to drill down to the table-data. Eg, in your reporter, something like this:

{report-block}
{local-reporter:data:Action|source=Page Containing Data}
  {expand-on:data:ActionProgress|as=progress}
{local-reporter}

{report-body}
*Action:* {report-info:expanded:item|link=true}
*Progress:* {report-info:expanded:progress > data:Sub Field Of Some Sort}
{report-body}
{report-block}

Alternately, you could use the report-on macro. Essentially, it drills down into each item in the specified key. In your case, something like:

{report-on:data:ActionProgress}
*Progress:*  {report-info:data:Sub Field Of Some Sort}
{report-on}

Thanks David

The expand-on option works after a fashion, but it creates a separate row in the report-table for every sub-item - what I'm trying to do is loop all the items in ActionProgress in one field within the report-table row, so I get something like:

ID Description Progress
1 Description of action 1 Action 1 first progress
Action1 second progress
2 Description of action 2 Action 2 first progress
Action 2 second progress
Action 2 third progress

In that case report-on should do the trick. Eg, in your 'Progress' column:

{report-on:data:ActionProgress|separator=newline}
  {report-info:data:Some Sub-Field of ActionProgress}
{report-on}
View the rest of this thread  |  3 more comments by 2 persons

Can any filters or sorts be included within a report-on?

Thanks

Jon

No, you can't filter or sort with report-on. You will need to put in a sub-report which uses local-reporter. local-reporter will always default to the current report item as its context, so you can just do something like:

{report-block}
{local-reporter:data:ActionProgress}
  {text-filter:data:Whatever|include=xxxxx}
{local-reporter}

{report-body}{report-info:data:Whatever}{report-body}

{report-block}

Hi

This is doing my head in, and I'm sure there's an easy answer to this, but I've been searching everywhere and can't find it. I would like to display, in a Report, a list of pages that match a certain label, with who created the page and when, then how many comments have been added, who add the last comment and when ... and possibly even an excerpt from the latest message.

 So far all I have is this:

{report-block}
{content-reporter:types=page}
{content-filter:label=open-issue}
{date-sort:content:creation date\|order=descending}
{content-reporter}
{report-body}
{div:style=padding:3px 0px;border-bottom:1px solid #F0F0F0}{report-image:content:icon}  {span:style=vertical-align:top;}*{report-info:content:title\|link=true}*{span}       {span:class=smalltext}Posted {report-info:content:creation date > date:"dd MMM yyyy"} by {report-info:content:modifier\|link=true} \| {report-link:content:url\|postfix=#comments}{report-info:content:all comments > collection:size} Comments{report-link} by .... ... on ....   {div}
{report-body}
{report-block}

I can't figure out how to get the last comment's details (ie who posted, when and maybe even an excerpt). I was trying things like

{report-info:content:all comments > collection:last:user:full name}

 but this doesn't work, probablty because I don't actually understand the whol supplier and collection concepts.
Any helps would be appreciated.

Thanks

M

Hi Martin,

What you have looks close. To fix your example, you need to put a '>' between each section of the keychain, as well as reference the comment creator. Eg:

{report-info:content:all comments > collection:last > content:creator > user:full name}

Essentially, get all comments, then get the last item in the collection, then get the user who was the creator of that comment, then get their full name.

You could do the same thing to get the excerpt, however this isn't going to be terribly efficient. Well, no matter what you do it won't be terribly efficient, since it's getting the comment collection twice at best. However, you can improve it a bit, like this:

{report-on:content:all comments > collection:last}by {report-info:content:creator|link=true} on {report-on:content:creation date|format=dd MMM, yyyy}: {report-info:content:body > first 50|render=wiki}{report-on}

This will first find the last item in 'all comments', and then get the creator, creation date and first 50 characters of the message (rendered as wiki).

As another tip, use the 'label' parameter in the content-reporter macro itself rather than the content-filter. That will let content-reporter optimise its query better.



Updated by Martin M
Jun 27, 2008 21:23

Hi David

 Thanks for the quick response. I tried both suggestions and neither seemed to work?! They returned nothing? I am running 2.6.0 ... am I missing something else?

This is what my code looks like:

{report-block}
{content-reporter:types=page}
{content-filter:label=open-issue}
{date-sort:content:creation date|order=descending}
{content-reporter}
{report-body}
{div:style=padding:3px 0px;border-bottom:1px solid #F0F0F0}{report-image:content:icon}  {span:style=vertical-align:top;}*{report-info:content:title|link=true}*{span}\\       {span:style=font-size:7pt}Posted {report-info:content:creation date > date:"dd MMM yyyy"} by {report-info:content:creator} | *{report-link:content:url|postfix=#comments}{report-info:content:all comments > collection:size} Comments{report-link}* {report-info:content:all comments > collection:last > content:creator > user:full name}
{span}{div}
{report-body}
{report-block}

Many thanks

M

Hi,

 I am using a report table, trying to pull metadata into the columns. For some reason it is not being populated with my metadata.

Please help.

Thanks,

Crystal

 {report-column:title=Hardware}
{report-on:@self|scope=2009 Business Cases|injected=true}%data:HWline1%}
{report-info:data:HWline1}
{report-on}
{report-column}

Hi Crystal,

There are two possibilities. Firstly is that you have a slight typo (there shouldn't be an extra '}' after %data:HWline1%). However, I don't think that would be causing your problems. The 'data:' supplier comes from the Scaffolding Plugin, so my guess is you don't have that plugin installed...

David

That would be it, we don't have the plugin. I guess it is not compatible with 2.8.
Is there any other route I could take, so I am able to pull metadata into a table?
Thanks,
Crystal

You can use the Metadata plugin's own macros. Anything inside a {report-column} or {report-on} macro will be rendered in the context of the page being reported on. However, it won't work for sorting or filtering - for that you'll need Scaffolding.

We are scheduled to release an updated Scaffolding for Confluence 2.8 by the end of the month, so you might want to check in again then.



Updated by David Peterson
Sep 03, 2008 19:30

hi,

i'm trying to show the post's comments

{report-info:content:summary\|render=wiki}
\_No. of comments {report-info:content:all comments > collection:size\|render=wiki}\_
Latest Comments:
{report-info:content:all comments >collection:last> content:creator > user:full name\|link=true\|render=wiki} says: {report-info:content:all comments >collection:last> content:body\|render=wiki}

i want to show only the last 2 comments

thanx,

Hi there,

For this, you will need to use a report, probably report-block. Something like this:

{report-block:maxResults=2}
{local-reporter:content:all comments}
  {date-sort:content:modification date|order=descending}
{local-reporter}

{report-header}Latest Comments:{report-header}

{report-body}{report-info:content:creator > user:full name|link=true} says: {report-info:content:body|render=wiki}{report-body}

{report-block}

This will list the most recent first, then the second-most recent.

When using injection, is there any way to escape % signs used for other purposes? Here is an example:

{report-on:@self|injected=true}
  {card:label=%data:ClarityLink%}
    {link-window:href=%data:ClarityLinkData%}Open in New Window{link-window}
    {iframe:src=%data:ClarityLinkData%|width=100%|height=800px}
  {card}
{report-on}

The width=100% is throwing an error because it is interpreted as an incomplete keychain. I tried backslashes, surrounding it with curly brackets and using html entities. None of these worked.

A simple yes or no answer would suffice, and I can come up with a workaround if the answer is no.

Thanks!

Shawn

Use double % to escape a single one.

{iframe:src=%data:ClarityLinkData%|width=100%%|height=800px}

That did it. Thanks!

Copyright(c) CustomWare Asia Pacific Pty Ltd
Powered by Atlassian Confluence 2.7.3, the Enterprise Wiki. Bug/feature request - Atlassian news - Contact administrators