Last updatedJun 3, 2020

Rate this page:

Custom HTML content

This is a continuation of the work started in 3. Using extension API.

In this section you will learn:

  • How you can add custom HTML content using extensions.

Panel extension

So far, your extension has been rendered entirely by the product, and you've only been able to modify some of its aspects via attributes. But, sometimes your extension might be more than a button or a link, and you would like to render your own content.

For those cases, Client-side Extensions (CSE) provides an extension type called Panel.

For panel extensions, CSE executes the onAction method when it's ready to receive your content, and provides a Panel API object that you can use to render your content.

Remember that the onAction method behaves differently for each type of extension. For more info, see Extension API reference.

Creating a pull request comment

Bitbucket provides an extension points that supports panels only inside a pull request, in the comments section of a diff. To continue, you'll need to add a comment to the diff of your pull request:

  1. In your pull request, open the Diff tab.
  2. In the toolbar, click Add comment to this file.
  3. Write a comment and save it.

onMount

Use onMount to get a container created by CSE and use it to render your content in it.

Add a panel extension and render your content

After creating a comment in the diff section, change your extension to be a panel, and then use the onMount method as follows.

In the /src/my-app/extensions/first-extension.js file:

  1. Use the bitbucket.ui.pullrequest.comment.extra extension point.
  2. Import PanelExtension from @atlassian/clientside-exstensions.
  3. Change your extension to use the PanelExtension factory.
  4. Use onAction to receive the PanelAPI object.
  5. Use onMount to get a container and render your content in it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// #/src/my-app/extensions/first-extension.js
import { PanelExtension } from '@atlassian/clientside-extensions';

/**
 * @clientside-extension
 * @extension-point bitbucket.ui.pullrequest.comment.extra
 */
export default PanelExtension.factory((extensionAPI, context) => {
    return {
        onAction: panelAPI => {
            panelAPI.onMount(container => {
                container.innerHTML = `
                    <h2>Look!</h2>
                    <p>this is the panel content</p>
                `;
            });
        },
    };
});

After refreshing the diff page, you should see the content rendered in the bottom part of the comment.

onUnmount

You can use onUnmount to specify the cleanup code you'd like to run when your panel is about to be destroyed or re-rendered.

Unmount after your content is destroyed

Using the same example with intervals, create an extension that updates its content every 3 seconds and clears the interval after you navigate away from the page.

In the /src/my-app/extensions/first-extension.js file:

  1. In onMount, create an interval that updates your content every 3 seconds.
  2. Use onUnmount to clear the interval and the container where you rendered your content.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// #/src/my-app/extensions/first-extension.js
import { PanelExtension } from '@atlassian/clientside-extensions';

/**
 * @clientside-extension
 * @extension-point bitbucket.ui.pullrequest.comment.extra
 */
export default PanelExtension.factory((extensionAPI, context) => {
    return {
        onAction: panelAPI => {
            let interval;
            let count = 1;

            const getContent = () => `
                <h2>Look!</h2>
                <p>this panel has been rendered ${count} times</p>
            `;

            panelAPI.onMount(container => {
                interval = setInterval(() => {
                    console.log('interval executed');
                    count++;
                    container.innerHTML = getContent();
                }, 3000);

                container.innerHTML = getContent();
            });

            panelAPI.onUnmount(container => {
                console.log('interval cleared');
                clearInterval(interval);
                container.innerHTML = '';
            });
        },
    };
});

Refresh the diff page and check that the content of your panel is updated every 3 seconds. Now, navigate to the commits page and check that the interval is cleared and no longer running.

Custom content with React

Client-side Extensions (CSE) provides a utility that makes it easier to use React with the Modal extension. For more info, see Rendering elements as React.

Recap and next steps

You've learned how to use the APIs available to create extensions that render your content.

Next, you'll learn how to create modals.

Rate this page: