This tutorial describes how to create a Forge app that displays the number of macros in a Confluence page. The app retrieves the body of the page, counts the number of macros, then displays the result in a modal dialog. A user triggers the action from an entry in the more actions (...) menu.
The final app looks like the following:
This tutorial assumes you're already familiar with the basics of Forge development. If this is your first time using Forge, see Getting started first.
To complete this tutorial, you need the following:
npm install -g @forge/cli@latest
on the command line.An Atlassian cloud developer site lets you install and test your app on Confluence and Jira products set up for you. If you don't have one yet, set it up now:
You can install your app to multiple Atlassian sites. However, app data won't be shared between separate Atlassian sites, products, or Forge environments.
The limits on the numbers of users you can create are as follows:
The Atlassian Marketplace doesn't currently support cross-product apps. If your app supports multiple products, you can publish two separate listings on the Marketplace, but your app won't be able to make API calls across different products and instances/installations.
The app retrieves the body of the page, counts the number of macros, then displays the result in a modal dialog.
1 2forge create
To register the functionality of your app, add confluence:contentAction
and function
modules to
the manifest. The confluence:contentAction
module adds an entry to the more actions (...) menu,
with the value of title
. The function
module contains the logic to count and display the number
of macros.
In the app's top-level directory, open the manifest.yml
file.
Replace the macro
entry under modules
with the following confluence:contentAction
.
1 2confluence:contentAction: - key: macro-counter title: Macro count resource: main render: native resolver: function: resolver
Add the follow permissions to the end of manifest.yml
1 2permissions: scopes: - 'read:confluence-content.summary'
Your manifest.yml
should look like the following, with your value for the app ID:
1 2modules: confluence:contentAction: - key: macro-counter resource: main render: native resolver: function: resolver title: Macro Count function: - key: resolver handler: index.handler resources: - key: main path: src/frontend/index.jsx app: id: '<your-app-id>' permissions: scopes: - 'read:confluence-content.summary'
Build, deploy, and install the app to see it in your Confluence site.
Navigate to the app's top-level directory and deploy your app by running:
1 2forge deploy
Install your app by running:
1 2forge install
Select your Atlassian product using the arrow keys and press the enter key.
Enter the URL for your development site. For example, example.atlassian.net. View a list of your active sites at Atlassian administration.
Once the successful installation message appears, your app is installed and ready
to use on the specified site.
You can always delete your app from the site by running the forge uninstall
command.
Running the forge install
command only installs your app onto the selected product.
To install onto multiple products, repeat these steps again, selecting another product each time.
Note that the Atlassian Marketplace
does not support cross-product apps yet.
You must run forge deploy
before running forge install
in any of the Forge environments.
With the app installed, it's time to see the entry in the more actions (...) menu.
You'll see the Macro Count entry from the app.
When you select the menu item you will see, the following modal.
Add UI Kit components that render when a user views the app. You'll use a static value for the number of macros in the page.
Start tunneling to view your local changes by running:
1 2forge tunnel
Open the src/frontend/index.jsx
file.
Replace the contents of the file with:
1 2import React, {useEffect, useState} from 'react'; // Import required components from UI Kit import ForgeReconciler, { Text, useProductContext } from '@forge/react'; // Import required for calling resolver import { invoke } from '@forge/bridge'; // You'll implement countMacros later const countMacros = (data) => { return 10; }; const App = () => { const [data, setData] = useState(); const context = useProductContext(); const contentId = context?.extension?.content?.id; useEffect(() => { if(contentId){ // You'll implement getContent later invoke('getContent', { contentId }).then(setData); } }, [contentId]); const macroCount = countMacros(data); return ( <Text>{`Number of macros on this page: ${macroCount}`}</Text> ); }; ForgeReconciler.render( <React.StrictMode> <App /> </React.StrictMode> );
Refresh a Confluence page on your site, open the more actions (...) menu, and select Macro Count.
A modal dialog displays with:
1 2Number of macros on this page: 10
In the code from this step:
setData
awaits the asynchronous getContent
function to complete. This function does not yet exist.useProductContext
.Turn the static app into a dynamic app by making an API call to Confluence to retrieve the contents of the page.
1 2npm install @forge/api
src/resolvers/index.js
file.getContent
function with:
1 2import Resolver from '@forge/resolver'; import { route, asUser } from '@forge/api'; const resolver = new Resolver(); resolver.define('getContent', async ({ payload }) => { const response = await asUser().requestConfluence(route`/wiki/rest/api/content/${payload.contentId}?expand=body.atlas_doc_format`); if (!response.ok) { const err = `Error while getContent with contentId ${payload.contentId}: ${response.status} ${response.statusText}`; console.error(err); throw new Error(err); } return await response.json(); }); export const handler = resolver.getDefinitions();
countMacros
function with:
1 2const countMacros = (data) => { if (!data || !data.body || !data.body.atlas_doc_format || !data.body.atlas_doc_format.value) { return 0; } const { body: { atlas_doc_format: { value } } } = data; const { content: contentList } = JSON.parse(value); const macros = contentList.filter((content) => { return content.type = "extension"; }); return macros.length; };
Edit the page to add macros (e.g. type /blog post) and select Macro count again to see the number update.
After confirming the app works locally, deploy the app so that it continues to work when you close the tunnel.
1 2forge deploy
That’s it. You've built an app that retrieves the contents of a page, counts the number of macros, then displays the result in a modal dialog.
Check out an example app, continue to one of the other tutorials, or read through the reference pages to learn more.
Rate this page: