feat(signals): add team-wide Slack channel picker to inbox settings - #69908
Conversation
The team-default inbox notification channel (default_slack_notification_channel) had no UI. It was only ever set automatically during Slack-app onboarding (find-or-create #posthog-inbox) or via the API, so teams whose Slack app predates that onboarding, or who want a specific channel, had no self-serve way to route every report to one team channel regardless of the suggested reviewer. Add a 'Notify the whole team' channel picker to the Slack section of inbox settings, alongside the existing per-user 'Notify me directly' card. It writes default_slack_notification_channel via signalTeamConfigLogic; clearing the channel disables the team default. Targets the team's first Slack workspace to mirror the backend's _get_team_slack_integration routing.
🤖 CI report✅ Bundle size — 🟢 -5.73 MiB (-8.2%)Uncompressed size of every built Total: 64.33 MiB · 🟢 -5.73 MiB (-8.2%)
Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report ✅ Eager graph — within budgetHow much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy
🟢 Largest files eagerly shipped from
|
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 789 B | src/scenes/ChunkLoadErrorBoundary.tsx |
| 668 B | src/index.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 278.6 KiB | ../node_modules/.pnpm/posthog-js@1.399.2/node_modules/posthog-js/dist/rrweb.js |
| 266.9 KiB | ../node_modules/.pnpm/@posthog+icons@0.37.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 234.9 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 221.5 KiB | ../node_modules/.pnpm/posthog-js@1.399.2/node_modules/posthog-js/dist/module.js |
| 164.0 KiB | src/queries/validators.js |
| 154.3 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.9 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Dist folder size — 🟢 -157.15 MiB (-10.9%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1280.79 MiB · 🟢 -157.15 MiB (-10.9%)
Dedupe the per-field optimistic-update triplet in signalTeamConfigLogic into a single patchTeamConfig(patch), reuse the POST response instead of refetching after every update, share the Slack card header markup, and skip duplicate channel fetches when multiple pickers mount for the same workspace.
Mirror the per-user card's switch: toggling off clears the team channel, toggling on reveals the picker. The picker now only renders while enabled or picking.
The Connections rail widget only checked the personal reviewer channel, so a team with only the team-wide channel configured was nagged to set up notifications it already had. Either channel now marks it done, and the status names each configured target (Team #a · You #b).
🦔 Hogbox preview · ❌ build failedThe preview didn't come up for commit |
|
| useMountedLogic(userAutonomyLogic) | ||
| const { slackIntegrations, integrationsLoading } = useValues(integrationsLogic) | ||
| const { autonomyConfig } = useValues(userAutonomyLogic) | ||
| const { teamConfig } = useValues(signalTeamConfigLogic) |
There was a problem hiding this comment.
NotificationsWidget reads teamConfig, but this component tree does not mount signalTeamConfigLogic, so the logic's afterMount fetch may never run here. When a team has only default_slack_notification_channel configured, the widget can keep teamChannel as null and show Not connected even though team-wide Slack notifications are enabled.
There was a problem hiding this comment.
Looks like it's false positive useValues(logic) mounts it
There was a problem hiding this comment.
You're right, my mistake. In Kea, useValues(logic) mounts the logic automatically if it isn't already mounted, which triggers afterMount and the fetch. The comment was a false positive.
Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.
|
|
||
| return ( | ||
| <div className="flex flex-col gap-3"> | ||
| <TeamChannelCard integration={integrations[0]} /> |
There was a problem hiding this comment.
Workspace Selection Can Diverge
TeamChannelCard always uses integrations[0], but delivery uses the backend's own first Slack integration lookup. For teams with multiple Slack workspaces, the frontend can save a channel ID from one workspace while the backend posts through another, so a valid selected channel fails at Slack delivery time.
Rule Used: When implementing new features, ensure that owners... (source)
Learned From
PostHog/posthog#31236
There was a problem hiding this comment.
true, but not security issue, it would just end up with channel not found, it requires some DB model changes, will do a follow up PR
Problem
Came up from support ticket https://posthoghelp.zendesk.com/agent/tickets/61892
The team-default inbox Slack channel (
SignalTeamConfig.default_slack_notification_channel) had no UI. It was only ever set automatically during Slack-app onboarding, or via the REST API. Teams that installed Slack before that onboarding shipped (or that want reports in a specific existing channel) had no self-serve way to route every report to one team channel. Surfaced by a support ticket.Changes
Adds a "Notify the whole team" card to the Slack section of inbox settings, above the per-user "Notify me directly" card: an enable toggle (mirroring the per-user card) plus a channel picker. Toggling off clears the team channel.
signalTeamConfigLogicgets a genericpatchTeamConfig(patch)action with an optimistic reducer. It reuses the POST response instead of refetching, and resyncs on error.SlackNotificationsSectionis split intoTeamChannelCard+PerUserChannelCardwith a shared card header and a single "connect Slack" empty state.SlackChannelPickernow skips duplicate channel fetches when multiple pickers mount for the same workspace.Team #reports · You #vojta.Showcase
Screen.Recording.2026-07-13.at.10.38.29.mov
How did you test this code?
SlackChannelPicker.test.tsx,slackIntegrationLogic.test.ts).tsgotypecheck with zero errors in the changed files.Automatic notifications
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Model: Claude Code (Opus 4.8, Fable 5)