Skip to content

Confluence multiple pages #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions plugins/confluence-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,30 @@ Your Confluence instance URL should look like `https://something.atlassian.net`.

### Set your Confluence credentials

If you are using username and password authentication, type them in to a text editor with a colon (`:`) between them. If you are using SSO, use an API token in place of the password. To create an API token in Confluence, follow the [instructions provided by Atlassian](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/). Once you have your text in your text editor like `[email protected]:MySecretPassWordOrToken`, you need to base64 encode it. You can do this using an online tool like [this](https://www.base64encode.org). You will add the base64 encoded value to Cortex as a secret. Copy the base64 encoded value. In Cortex, click on Settings > Secrets > Add secret. In Secret name, type `confluence_secret`, paste the base64 encoded secret into Secret value, and click on Create secret.
1. If you are using username and password authentication, type them in to a text editor with a colon (`:`) between them. If you are using SSO, use an API token in place of the password. To create an API token in Confluence, follow the [instructions provided by Atlassian](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/).
2. Once you have your text in your text editor like `[email protected]:MySecretPassWordOrToken`, you need to base64 encode it. You can do this using an online tool like [this](https://www.base64encode.org).
3. You will add the base64 encoded value to Cortex as a secret. Copy the base64 encoded value. In Cortex, click on Settings > Secrets > Add secret. In Secret name, type `confluence_secret`, paste the base64 encoded secret into Secret value, and click on Create secret.

### Set up a Plugin Proxy

After you've saved the secret, we will set up a proxy to use that secret to communicate with Confluence. In Cortex, click on Plugins > Proxies > Create Proxy. In Name, type `Confluence Proxy`. Click on Add URL, and put in your Confluence Instance URL, like `https://something.atlassian.net`. Click Save. Next, click on "Add header to https://something.atlassian.net". In the dialog box that appears, type `Authorization` in the Name field, and in the Value field, type `Basic {{{secrets.confluence_secret}}}`. Make sure you include the three curly braces, and make sure the secret name matches the secret you created above, with `secrets.` in front of it. Click Save, then click on the Create Proxy button.
After you've saved the secret, we will set up a proxy to use that secret to communicate with Confluence.

### Associate the plugin with the plugin proxy
1. In Cortex, click on Plugins > Proxies > Create Proxy.
2. In Name, type `Confluence Proxy`.
3. Click on Add URL, and put in your Confluence Instance URL, like `https://something.atlassian.net`. Click Save.
4. Next, click on "Add header to https://something.atlassian.net". In the dialog box that appears, type `Authorization` in the Name field, and in the Value field, type `Basic {{{secrets.confluence_secret}}}`. Make sure you include the three curly braces, and make sure the secret name matches the secret you created above, with `secrets.` in front of it. Click Save, then click on the Create Proxy button.

Create or edit your Confluence Plugin. In the dropdown under the Associated Proxy heading, choose the Confluence proxy you created above. Next, click Save plugin at the bottom of the page.
### Associate the plugin with the plugin proxy and set entity types

1. Create or edit your Confluence Plugin.
2. In the Plugin Context section, find the dropdown under the Associated Proxy heading, choose the Confluence proxy you created above.
3. At the bottom of Plugin Context section, click on **"Add another context"** and add the `entity types` you want to display your plugin. (eg. `service`)
4. Next, click Save plugin at the bottom of the page.

### Create a plugin configuration entity

- Consider creating a new entity type, so that any existing scorecards are not affected by ths configuration entity. In this example, we have created a new entity type called `plugin-configuration`
- Create a new entity with the tag `confluence-plugin-config`
- Consider creating a new **entity type**, so that any existing scorecards are not affected by ths configuration entity. In this example, we have created a new entity type called `plugin-configuration`
- Create a new **entity** with the tag `confluence-plugin-config`
- Set `x-cortex-definition.confluence-url` to the value of your Confluence Instance URL. For example, if my Confluence Instance URL was `https://martindstone.service-now.com`, my `confluence-plugin-config` entity would look like this:

```
Expand All @@ -43,18 +53,38 @@ info:

### Adding Confluence content to entities

Entities can be associated with Confluence Page IDs by adding a PageID tag to the `x-cortex-confluence` object. In the Entity yaml for the entity to the Page ID that you'd like to view inside of Cortex, such as:
To associate confluence pages with entities you will require `id` for each page in which you can find by following the instructions on [here](https://confluence.atlassian.com/confkb/how-to-get-confluence-page-id-648380445.html).

Entities can be associated with Confluence Page IDs in two ways:

1. If there is only one confluence page, adding a PageID tag to the `x-cortex-confluence` object will be ok. In the Entity yaml for the entity to the Page ID that you'd like to view inside of Cortex, such as:

```
x-cortex-confluence:
pageID: "123456"
```

2. If there are multiple confluence pages, adding pages under `x-cortex-confluence` and then under `pages` you can enter multiple `id`s and `title`s as well to describe the corresponding confluence page. Entity yaml should look like this:

```
x-cortex-confluence:
pages:
- id: "327681"
title: Page Title 1
- id: "65718"
title: Page Title 2
- id: "1179675"
title: ""
- id: "1277954"
```

The `id` field is mandatory but `title` filed is optional for each page.

You can do this for Custom Entities, as well as any Service entity.

### Done!

Now when you load the Confluence plugin on an entity that has a Confluence page ID in `x-cortex-confluence.pageID`, you should see the content of that page in Cortex!
Now when you load the Confluence plugin on an entity, you should see the contents of associated pages in Cortex!

## Building the plugin

Expand Down
4 changes: 4 additions & 0 deletions plugins/confluence-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@chakra-ui/react": "^2.10.2",
"@cortexapps/plugin-core": "^2.0.0",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"framer-motion": "^11.15.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down
8 changes: 0 additions & 8 deletions plugins/confluence-plugin/src/api/Cortex.ts

This file was deleted.

5 changes: 4 additions & 1 deletion plugins/confluence-plugin/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { PluginProvider } from "@cortexapps/plugin-core/components";
import "../baseStyles.css";
import ErrorBoundary from "./ErrorBoundary";
import PageContent from "./PageContent";
import { ChakraProvider } from "@chakra-ui/react";

const App: React.FC = () => {
return (
<ErrorBoundary>
<PluginProvider>
<PageContent />
<ChakraProvider toastOptions={{ defaultOptions: { position: "top" } }}>
<PageContent />
</ChakraProvider>
</PluginProvider>
</ErrorBoundary>
);
Expand Down
18 changes: 18 additions & 0 deletions plugins/confluence-plugin/src/components/Loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Box, Spinner, Text } from "@chakra-ui/react";

export default function Loading(): JSX.Element {
return (
<Box
w={"full"}
minH={400}
display={"flex"}
justifyContent={"center"}
alignItems={"center"}
flexDirection={"column"}
gap={6}
>
<Spinner color="purple" size="xl" />
<Text fontSize="2xl">Loading...</Text>
</Box>
);
}
11 changes: 11 additions & 0 deletions plugins/confluence-plugin/src/components/Notice.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { render, waitFor } from "@testing-library/react";
import Notice from "./Notice";

describe("Notice component", () => {
it("renders children correctly", async () => {
const { getByText } = render(<Notice>Test Notice</Notice>);
await waitFor(() => {
expect(getByText("Test Notice")).toBeInTheDocument();
});
});
});
14 changes: 14 additions & 0 deletions plugins/confluence-plugin/src/components/Notice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Box, Text } from "@chakra-ui/react";
import type { ReactNode } from "react";

export default function Notice({
children,
}: {
children: ReactNode;
}): JSX.Element {
return (
<Box bg="gray.200" p={3} borderRadius={4}>
<Text m={0}>{children}</Text>
</Box>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ describe("PageContent", () => {

await waitFor(() => {
expect(
screen.getByText("No Confluence details exist on this entity.")
screen.getByText(
"We could not find any Confluence pages associated with this entity."
)
).toBeInTheDocument();
});
});
Expand Down
Loading
Loading