Skip to content

Documentation for customizing snap-in configuration page #63

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 15 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from 14 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
2 changes: 1 addition & 1 deletion fern/docs/pages/references/inputs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ inputs:
- value-2
- value-3
is_required: true
default_value: value-1
default_value: [value-1]
ui:
display_name: Enum List Picker
```
209 changes: 209 additions & 0 deletions fern/docs/pages/references/snap-in-configuration.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# Customizing snap-in configuration pages

The DevRev snap-ins platform allows developers to define custom configuration pages for their snap-ins.

While the default configuration page automatically renders input fields for keyrings and inputs, there may be cases where a custom configuration page is more suitable:

- Improved user experience: Developers can design the configuration page to provide a more intuitive and streamlined experience for users setting up the snap-in.
- Advanced input handling: Custom configuration pages enable developers to handle complex input scenarios, such as fetching data from external systems to populate dropdown options or validating user input.
- Branding and styling: Developers can align the configuration page with their Snap-in's branding and style guidelines, ensuring a consistent look and feel.

## Defining Custom Configuration Pages

To create a custom configuration page for a Snap-in, developers need to define the following in the Snap-in manifest:

```yaml
snap_kit_actions:
- name: org_snap_kit_action
function: snap_in_configuration_handler
- name: user_snap_kit_action
function: snap_in_configuration_handler

functions:
- name: snap_in_configuration_handler
description: Handler for processing organization and user configuration options.
- name: config_initializer
description: Generates the initial configuration options for both organization and user.

configuration_handler:
organization:
initializer: config_initializer
snap_kit_action_name: org_snap_kit_action
user:
initializer: config_initializer
snap_kit_action_name: user_snap_kit_action
```

The `configuration_handler` section in the manifest connects the functions responsible for generating and processing the custom configuration page.

- `config_initializer`: Generates the initial configuration options for both organization and user. It is called when the configuration page is first loaded.
- `snap_in_configuration_handler`: This function processes the user and organization configuration options. It is triggered when actions are performed on the organization or user configuration snap-kit.

## Configuration functions

The configuration functions should return a valid snap-kit JSON that defines the layout and elements of the custom configuration page. Here's an example of a snap-kit JSON:

```json
{
"snap_kit_body": {
"body": {
"snaps": [
{
"elements": [
{
"action_id": "user_snap_kit_action",
"action_type": "remote",
"elements": [
{
"element": {
"action_id": "select",
"action_type": "client",
"initial_selected_option": {
"text": {
"text": "Ticket",
"type": "plain_text"
},
"value": "ticket"
},
"options": [
{
"text": {
"text": "Ticket",
"type": "plain_text"
},
"value": "ticket"
},
{
"text": {
"text": "Conversation",
"type": "plain_text"
},
"value": "conversation"
}
],
"type": "static_select"
},
"type": "input_layout"
}
],
"submit_action": {
"action_id": "next",
"style": "primary",
"text": {
"text": "Next",
"type": "plain_text"
},
"type": "button",
"value": "next"
},
"type": "form"
}
],
"type": "card"
}
]
}
}
}
```

In this example, the snap-kit renders a dropdown select for choosing between "Ticket" and "Conversation," along with a "Next" button. When the "Next" button is clicked, the `user_snap_in_configuration_handler` function is invoked to process the user's selection.
In the snap-kit action handler, the `event.payload.action.id` can be used to determine the form being submitted and call the `snap-ins.update` API to update the configuration.

## Update snap-in inputs (BETA)

Updates the inputs of a snap-in based on the inputs defined in the snap-in configuration.

**Note: This endpoint is currently in BETA and may be subject to change in the future. Reach out to us via PLuG to subscribe to changes to BETA endpoints.**

### Request Payload

The request payload should be a JSON object with the following properties:

- `id` (string, required): The ID of the snap-in to update.
- `inputs_values` (object, required): An object containing the input values to update. The properties of this object should match the input names defined in the snap-in configuration.

Example payload:
```json
{
"id": "snap_in_id",
"inputs_values": {
"part_picker": "don:core:dvrv-us-1:devo/XXXX/product:XXXX",
"enum_list_picker": ["value-1", "value-2"]
}
}
```

In the example above, the `part_picker` and `enum_list_picker` are the input names defined in the snap-in configuration, and their corresponding values are provided in the `inputs_values` object.

### Response

#### Success response

- Status Code: 200 OK
- Content-Type: application/json

Response body:
```json
{
"data": {},
"message": "Snap-in updated successfully",
"success": true
}
```

#### Error response

If an error occurs while updating the snap-in, the response has the following format:

- Status Code: 4xx or 5xx
- Content-Type: application/json

Response body:
```json
{
"data": {},
"success": false
}
```

## Example usage

Here's an example of how to update the input values:

```typescript
async updateSnapInInputs(snapInId: string, inputsValues: Record<string, any>): Promise<HTTPResponse> {
const payload: SnapInsUpdateRequest = {
id: snapInId,
inputsValues,
};
return this.updateSnapInInputs(payload);
}

async updateSnapInInputs(payload: SnapInsUpdateRequest): Promise<HTTPResponse> {
try {

await devrevSDK.snapInsUpdate(payload);
return { data: {}, message: 'Snap-in updated successfully', success: true };
} catch (error: any) {
if (error.response) {
const err = `Failed to update the snap-in. Err: ${JSON.stringify(error.response.data)}, Status: ${error.response.status}`;
return { ...defaultResponse, message: err };
} else {
return { ...defaultResponse, message: error.message };
}
}
}
```

In this example, the `updateSnapInInputs` function takes the `snapInId` and `inputsValues` as parameters. The `inputsValues` object should contain the input names and their corresponding values as defined in the snap-in configuration.

The function constructs the payload object with the `snapInId` and `inputsValues`, and then calls the `updateSnapInInputs` function to make the POST request to the `snap-ins.update` endpoint.

If the request is successful, it returns a success response with a status code of 200 and a message indicating that the snap-in was updated successfully.

If an error occurs, it catches the error and returns an error response with an appropriate status code and an error message containing the error details.

Please keep in mind that this endpoint is currently in BETA, and its functionality or parameters may change in future updates.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking out loud - Should we have some sort of subscribe to beta changes button in our documentation which can help us keep track of who all external parties which are using a beta feature? It can help us in the future when we need to track down who all are depending on this feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally we should be doing this based on the endpoint and our logging. But I can put a note here.


For more details on the snap-kit JSON format and available elements, refer to the [DevRev Snap-kit documentation](/snapin-development/references/snapkit).
4 changes: 2 additions & 2 deletions fern/docs/pages/tutorials/timer-ticket-creator.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ export const run = async (events: any[]) => {
const ticketName = `Ticket created at ${date.toLocaleString()}`;
const ticketBody = `This ticket was created by a snap-in at ${date.toLocaleString()}`;

const reponse = await devrevSDK.worksCreate({
const response = await devrevSDK.worksCreate({
title: ticketName,
body: ticketBody,
// The ticket is created in the PROD-1 part. Rename this to match your part.
Expand All @@ -225,7 +225,7 @@ export const run = async (events: any[]) => {
type: publicSDK.WorkType.Ticket,
});

console.log(reponse);
console.log(response);
}
};

Expand Down
3 changes: 3 additions & 0 deletions fern/versions/public.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ navigation:
- page: Snap-in resources
slug: snap-in-resources
path: ../docs/pages/references/snap-in-resources.mdx
- page: Customizing snap-in configuration
slug: customizing-snap-in-configuration
path: ../docs/pages/references/snap-in-configuration.mdx
- page: Development best practices
slug: best-practices
path: ../docs/pages/best_practices.mdx
Expand Down
Loading