Skip to content

add docs for custom chart sections#1140

Open
ruipbatista wants to merge 1 commit intomainfrom
custom-chart-sections
Open

add docs for custom chart sections#1140
ruipbatista wants to merge 1 commit intomainfrom
custom-chart-sections

Conversation

@ruipbatista
Copy link
Copy Markdown
Contributor

@ruipbatista ruipbatista requested a review from a team as a code owner April 14, 2026 10:10
@ruipbatista ruipbatista force-pushed the custom-chart-sections branch from e2d00c6 to cf78460 Compare April 15, 2026 15:54
Comment on lines +142 to +153
### `templates/my_section.html`

```html
<ul>
{% for item in items %}
<li>{{ item.title }}</li>
{% empty %}
<li>No items on record.</li>
{% endfor %}
</ul>
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I noticed the web preview didnt run so when I locally checked this out to see the page I got Liquid Exception: Liquid syntax error (line 141): Unknown tag 'empty' in /Users/reba_magier/Canvas/repos/documentation/collections/_sdk/handlers/patient-chart-summary-custom-section-handler.md

and claude did this because it said "Wrapped the HTML template block in {% raw %}...{% endraw %} so Jekyll's Liquid parser stops trying to evaluate the Django template tags ({% for %}, {% empty %}, {% endfor %}) inside the code sample."

Suggested change
### `templates/my_section.html`
```html
<ul>
{% for item in items %}
<li>{{ item.title }}</li>
{% empty %}
<li>No items on record.</li>
{% endfor %}
</ul>
```
### `templates/my_section.html`
{% raw %}
```html
<ul>
{% for item in items %}
<li>{{ item.title }}</li>
{% empty %}
<li>No items on record.</li>
{% endfor %}
</ul>

{% endraw %}


## Overview

Custom chart summary sections are registered through [`PatientChartSummaryConfiguration`](/sdk/patient-chart-summary-configuration-effect/) and served by a `PatientChartSummaryCustomSectionHandler` subclass. Each handler is responsible for exactly one section, identified by its `SECTION_KEY`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What happens if someone were to try to create a handler in one plugin but then have a different plugin installed for the PatientChartSummaryConfiguration? Is the name of the custom section being validated in the same plugin or is it another plugins model that we are saving the custom sections to?

- **`handle()`**
Called when Canvas requests the content for this section. Must return a list containing a single `PatientChartSummaryCustomSection` effect.

## Registering the Section
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
## Registering the Section
## Configuring Chart Summary Sections


## Registering the Section

A custom section handler alone is not enough — the section must also be included in the chart summary layout. Use `PatientChartSummaryConfiguration` to declare which sections appear in the chart summary and in what order.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would link to sdk/layout-effect/#patient-summary as a reference for the other sections you can configure with this effect

]
```

Both handlers must be registered in `CANVAS_MANIFEST.json`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would move this to the ## Overview section instead after you call out the 2 handlers

entries = (
CommandMetadata.objects.filter(
key="my_section",
command__patient__id=self.target,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This makes me think in the## Creating a Custom Section Handler section we should call out what the self.target and self.context stuff the user has in this handler specifically

Comment thread collections/_sdk/effects/patient-chart-summary-custom-section.md
class MySectionHandler(PatientChartSummaryCustomSectionHandler):
SECTION_KEY = "my_section"

def handle(self) -> list[Effect]:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lets add doc string to this example of what this handle is actually doing for the end user. Love the example to use CommandMetadata since customers want to be able to visualize those values

Comment on lines +173 to +181
## Accessing Patient Data

The patient key is available via `self.target`. Use it to scope database queries to the current patient.

```python
from canvas_sdk.v1.data.patient import Patient

patient = Patient.objects.get(id=self.target)
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oh its down here. Yeah lets move it to the other section I commented about and also include the self.context

A unique string identifier for the section. Must match the key passed to `PatientChartSummaryConfiguration.CustomSection`. Omitting or leaving it empty will raise an `ImproperlyConfigured` error when the plugin loads.

- **`handle()`**
Called when Canvas requests the content for this section. Must return a list containing a single `PatientChartSummaryCustomSection` effect.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Link to the effect documentation here

hidden: false
---

## Overview
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we add a link in /sdk/layout-effect/#patient-summary to this page (or the handler page?) so that not only you can configure builtin sections, you can define custom ones

Comment on lines +38 to +41
| `content` | required (if `url` is not provided) | `str \| None` | Inline HTML content to render in the section. Mutually exclusive with `url`. |
| `url` | required (if `content` is not provided) | `str \| None` | URL of the page to load in the section iframe. Mutually exclusive with `content`. |
| `icon` | required (if `icon_url` is not provided) | `str \| None` | Text or emoji displayed as the section icon when collapsed. Mutually exclusive with `icon_url`. |
| `icon_url` | required (if `icon` is not provided) | `str \| None` | URL of an image to use as the section icon when collapsed. Mutually exclusive with `icon`. |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

extra character in the Type column

# Serve content from a hosted URL
PatientChartSummaryCustomSection(
url="/plugin-io/api/my_plugin/my-section",
icon_url="/plugin-io/api/my_plugin/icon.png",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the icon is really a path not a url

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants