Skip to content

Conversation

@vdekrijger
Copy link
Contributor

@vdekrijger vdekrijger commented Nov 21, 2025

Problem

With: #41836 we introduced a fix so that the show legend field was correctly being picked up when Insights were exported to PNGs. However post release, we found out that there are also requests to solve this for subscriptions (e.g.: #40630).

This PR therefore fixes it for both the PNG exports, and for the subscriptions.

Fixes: #40630

Changes

Subscriptions have their own path to generate the ExportAsset object which eventually will be rendered to be exported:

assets = [
ExportedAsset(
team=resource.team,
export_format="image/png",
insight=insight,
dashboard=resource.dashboard,
)
for insight in insights[:max_asset_count]
]
.

In order to avoid having multiple solutions (frontend extracting it from the display options, backend querying the DB), there is now 1 source of truth where the backend will fetch the "showLegend / show_legend" status of the Insight when sending it off to be rendered on the worker.

This means that this PR also cleans up a little bit of the frontend code introduced in the previous PR. This does however mean that a user must save their insight "Show Legend" option before the export will respect it, this is currently a little bit tricky as modifying the "Show Legend" button does not immediatly change the "Edit" -> "Save" button, however for the scope of this issue we will leave that behaviour as is. In order to work around this, users can first hit "Edit" -> "Change Show Legend" -> "Save". This is likely a path that they are familiar with as this hasn't changed.

Screenshot 2025-11-21 at 16 59 23

How did you test this code?

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

  1. Run the Posthog application locally
  2. Create an insight (ensuring there is no legend)
  3. Run the png export and confirm that there is no legend in the export
  4. Adjust the display options, setting the Show Legend to true
  5. Run the png export and confirm that this time, there is a legend on the export
  6. Also ran an export of the dashboards to confirm it's all okay
  7. Ran an export of the shared page for an insight with / without the show legend option enabled.
  8. And finally ran a subscription test. I tried configuring an email with Twilio / mailgun but neither seemed to work for me, so I just retrieved the generated exported image from MinIO instead (see below).

With show_legend: false

Insight > export > png:
Uploading export-test-insights-for-export-fix-without-legend.png…

Share insight:
Screenshot 2025-11-21 at 17 02 10

With show_legend: true

Insight > export > png:
export-test-insights-for-export-fix-with-legend

Share insight:
Screenshot 2025-11-21 at 17 02 38

Dashboard export:
export-this-dashboard-contains-helpful-insights-for-our-product-at-a-glance(4)

Subscription export (fetched from MinIO):
019aa743-8207-0000-9b9d-0ad7afb50788

Changelog: (features only) Is this feature complete?

N/A this is a small fix to an existing feature.

@vdekrijger vdekrijger changed the title chore: Extract the showLegend display option from the DB so that it a… chore: Extract the showLegend display option from the DB so that it also works for subscriptions Nov 21, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Nov 21, 2025

Size Change: -173 B (-0.01%)

Total Size: 3.4 MB

ℹ️ View Unchanged
Filename Size Change
frontend/dist/toolbar.js 3.4 MB -173 B (-0.01%)

compressed-size-action

@vdekrijger vdekrijger changed the title chore: Extract the showLegend display option from the DB so that it also works for subscriptions fix(insights): Retain the legend configuration inside the subscriptions as well Nov 21, 2025
@vdekrijger vdekrijger marked this pull request as ready for review November 21, 2025 16:05
@posthog-bot posthog-bot requested a review from a team November 21, 2025 16:06
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

5 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +300 to +302
for value in source.values():
if isinstance(value, dict) and "showLegend" in value:
return bool(value.get("showLegend", False))
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: iterating through all source.values() and returning the first dict with showLegend is fragile - dict iteration order could cause it to pick up showLegend from an unexpected location if the schema changes

Suggested change
for value in source.values():
if isinstance(value, dict) and "showLegend" in value:
return bool(value.get("showLegend", False))
# Check specific filter fields that contain showLegend
for filter_field in ['trendsFilter', 'lifecycleFilter', 'stickinessFilter']:
if filter_field in source and isinstance(source[filter_field], dict):
if 'showLegend' in source[filter_field]:
return bool(source[filter_field].get('showLegend', False))
Prompt To Fix With AI
This is a comment left during a code review.
Path: posthog/models/insight.py
Line: 300:302

Comment:
**logic:** iterating through all `source.values()` and returning the first dict with `showLegend` is fragile - dict iteration order could cause it to pick up `showLegend` from an unexpected location if the schema changes

```suggestion
                # Check specific filter fields that contain showLegend
                for filter_field in ['trendsFilter', 'lifecycleFilter', 'stickinessFilter']:
                    if filter_field in source and isinstance(source[filter_field], dict):
                        if 'showLegend' in source[filter_field]:
                            return bool(source[filter_field].get('showLegend', False))
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I prefer my implementation as the proposed one is quite brittle when we are adding new filters / have these hidden string dependencies.

In our current structure it is very unlikely that there are multiple showLegend flags, and if there will be, it will return the first one it encounters meaning that it won't break anything.

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it! Your current implementation is indeed more flexible and maintainable. I've noted your preference to avoid hardcoded filter field names when extracting configuration values from dynamic structures.

Here's a link to the new rule that will be applied in future reviews of similar patterns.

@vdekrijger vdekrijger merged commit 7c708e3 into master Nov 21, 2025
204 checks passed
@vdekrijger vdekrijger deleted the vdekrijger-ensure-subscriptions-exports-also-stick-to-legend-flag branch November 21, 2025 21:05
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.

Feature Request: Include legend for Slack subscriptions

3 participants