How to archive pages with dynamic content

Description

It is easy to provide pages with lots of dynamic content using a variety of techniques including SQL for Confluence, Reporting Add-on, Scaffolding Add-on, and other add-ons. Pages can always reflect the latest information (smile)! However, in some cases, it would be nice to have a snapshot of the page and its dynamic content at various points in time. This is possible with just a little bit of additional work and the run macro.

Dependencies

Run macro - used to capture the content in an attachment

Optional dependencies

In order to provide a better user experience for viewing the archived data, the following add-ons can be used

  1. Composition Add-on - deck and card macros
  2. Scripting for Confluence - groovy macro to automatically create decks/cards from the attachments
  3. HTML for Confluence - used to display the captured HTML in a nice way on a Confluence page

Steps

  1. Create your main page
  2. On the main page, add the run macro surrounding the content that needs to be archived similar to the following

    Example main page
    {run:exportFile=Example - Archive^example-$current_time.html
    |titleExport=Save page snapshot
    |exportVersion=replace
    |attachmentComment=Example-archive-$current_time
    |dateFormat=yyyy.MM.dd
    |autoRun=true
    |hideRun=true}
    
    {sql-query:datasource=testDS}
    select * from address
    {sql-query}
    
    {run}
  3. Create another page with the name equal to the original page suffixed by " - archive", suggest making it a child page of the main page. A simple alternative is to just use the attachments macro on this page - not as nice, but provides access to the data as straight html.

    Example - archive page
    {composition-setup}{composition-setup} 
    
    {archive-deck} 

How to archive charts

Charts can be handled by saving each chart as an attachment by adding some parameters to the chart macro similar to the following:

{chart:...
|attachment=Example - Archive^example-$current_time.png
|attachmentVersion=replace}

Results

    4. Create a user macro to display the archived data in a nice way (optional)

  • No macro body
  • Output format wiki
archive-deck user macro
{groovy:output=wiki}
// Looks through all attachments for the current page and finds those that match the pattern 
// Create a tab for each year and under the year, a tab for each matching attachment
// Include the attachment via the html macro
attachmentNameRegex = /(2\d\d\d)\.(\d\d)\.(\d\d)\..*htm/  // 3 group regex - name contains a date like 2012.05.04
def attachments = attachmentManager.getAttachments(context.getEntity())
def cardList = []
attachments.each { attachment ->
    name = attachment.getDisplayTitle()
    def matcher = name =~ attachmentNameRegex
    if (matcher.find()) {
        cardList << [
            attachmentName: name,
            year: matcher.group(1),
            month: matcher.group(2),
            day: matcher.group(3)
        ]
    }
}
cardList = cardList.sort { a, b -> 
    def result = b.year.compareTo(a.year)   // sort by year first, desc order
    if (result == 0) {
        result = a.month.compareTo(b.month) // sort by month
    }
    if (result == 0) {
        result = a.day.compareTo(b.day) // sort by day
    }
    return result
}
def br = '\n'

out << '{deck:id=by_year}'
out << br
def year = ''
cardList.each { card ->
    if (card.year != year) {  // need a new year card
        if (year != '') {  // first time through
            out << '{card}'  // end previous card
            out << br
            out << '{deck}'  // end previous deck
            out << br
        }
        year = card.year 
        out << "{card:label=${year}}"
        out << br
        out << "{deck:id=year_${card.year}}"
        out << br
    }    
    out << "{card:label=${card.month}/${card.day}}"   
    out << br
    out << "{html:script=${context.getPageTitle()}^${card.attachmentName}|tidy=true} {html}"
    out << br
    out << '{card}'
    out << br
}
out << '{card}'
out << br
out << '{deck}'
out << br
out << '{deck}'
out << br
{groovy}