OUT-3981 | Client UI: dynamic Studio app rows in Your Actions - #223
Merged
arpandhakal merged 7 commits intoJul 27, 2026
Conversation
New installed-apps feature module (CLEAN: service + controller + route) that returns Studio app installs eligible for "Your Actions". - Service filters out disabled/draft/internal installs, then fans out getInstallNotificationSettings per install in parallel, keeping only those with a complete registered actionLabel - A single notification-settings failure skips that install, not the request - GET /api/installed-apps (withErrorHandler), authorized for IU and client - useInstalledApps React Query hook ([KEY, workspaceId], Zod-validated) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…endpoint' into arpandhakal/out-3981-client-ui-dynamic-studio-app-rows-in-your-actions
Synthesize ActionDefinition-shaped rows at runtime from the actionable-installs
discovery endpoint (OUT-3979) and merge them into useEnabledActions after the
built-ins (no drag-order participation in v1), filtered by actions.hiddenAppIds
(OUT-3978, deny-list by appId).
- New DynamicActionDefinition + toDynamicActionDefinition: verb <- actionLabel.verb,
label <- pluralNoun, singularLabel <- singularNoun, icon mapped onto the design
system Icon (fallback CustomApps when the install icon isn't a valid IconType)
- icon-names: runtime allow-list of design-system IconType names, since the package
does not expose its icon registry at runtime
- ActionItem/ActionsCard render the RenderableAction union: dynamic count from the
per-app map (OUT-3980), navigation via postMessage history.push { id: installId,
route: 'apps' }; dynamic rows never render a zero/empty state in any mode
- Widen ActionDefinition.icon to IconType so built-in and dynamic rows share the field
Built-in rows unchanged in behavior and appearance.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryAdds workspace-scoped discovery and rendering of actionable Studio app installs.
Confidence Score: 5/5The PR appears safe to merge, with no concrete changed-code-triggered failures established. The new endpoint is authenticated, dynamic install metadata is validated before rendering, empty app actions are suppressed, and navigation retains the install-specific identifier. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[ActionsCard] --> B[useEnabledActions]
B --> C[useInstalledApps]
C --> D[GET /api/installed-apps]
D --> E[InstalledAppsService]
E --> F[Assembly installs and notification settings]
B --> G[Dynamic action definitions]
H[Notification counts by appId] --> A
G --> A
A --> I[Visible action rows]
I --> J[Parent portal history.push by installId]
Reviews (1): Last reviewed commit: "feat(OUT-3981): render dynamic Studio ap..." | Re-trigger Greptile |
Internal users control each Studio app's presence in Your Actions from
the existing Actions sidebar panel. Apps appear automatically once
installed and registered, defaulted to on.
- useActions merges dynamic apps (keyed by appId) after built-ins;
toggle checked = !hiddenAppIds.includes(appId); flipping mutates
actions.hiddenAppIds, saved via the existing Save Changes flow.
- AppToggleItem renders a non-draggable toggle row (Studio-app rows are
excluded from dnd reorder in v1).
- Editor preview now shows every enabled dynamic row regardless of
count, matching built-in behavior, with the {{N}} placeholder chip.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Built-ins and dynamic Studio-app rows now share one drag-orderable list in the Actions sidebar; `order` holds a mix of ActionKeys and appIds, and useEnabledActions renders in that unified order (drops the v1 "apps last, non-draggable" restriction). Removes AppToggleItem; ActionItem icon widened to IconType. - Exclude the Tasks app (appId === TASKS_APP_ID) from actionable-installs discovery so it doesn't duplicate the built-in Tasks row. - Fan out notification-settings via mapWithConcurrency (limit 5) instead of Promise.all, avoiding a TLS-connection burst that tripped undici connect timeouts in dev. - Log both the raw platform installs and the final actionable list to aid debugging why an app does/doesn't surface. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the temporary logger.info calls for the raw platform installs and the final actionable list; keep the error log for failed notification-settings fetches. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…studio-app-toggles-in-actions-sidebar-preview-rows OUT-3982 | Editor: Studio app toggles in Actions sidebar + preview rows
arpandhakal
merged commit Jul 27, 2026
461a46c
into
arpandhakal/out-3980-api-per-app-unread-notification-counts
7 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
Renders a "Your Actions" row for each registered Studio app the signed-in client has unread notifications from — as
[Verb] [count] [noun](e.g. "Review 3 documents"), visually indistinguishable from built-in rows.installed-apps/lib/dynamic-action.ts—DynamicActionDefinition+toDynamicActionDefinition()synthesizes a row from anActionableInstallDto(OUT-3979):verb ← actionLabel.verb,label ← pluralNoun,singularLabel ← singularNoun,iconmapped onto the design-systemIcon(fallbackCustomApps), plusinstallId/appId. Also exports theRenderableActionunion andisDynamicAction()guard.installed-apps/lib/icon-names.ts— runtime allow-list of valid design-systemIconTypenames +isIconType(). The package does not expose its icon registry at runtime (itsexportsmap blocks the subpath), so we snapshot the names to validate arbitrary installiconstrings before rendering.useEnabledActions— merges dynamic definitions after the built-ins (no drag-order participation in v1), filtered byactions.hiddenAppIds(OUT-3978, deny-list byappId).ActionItem/ActionsCard— render theRenderableActionunion: dynamic count from the per-appappsmap (OUT-3980); navigation viapostMessage({ type: 'history.push', id: installId, route: 'apps' }); dynamic rows never render a zero/empty state in any mode.ActionDefinition.icontoIconTypeso built-in and dynamic rows share the field. Built-in rows unchanged in behavior and appearance.Testing Criteria
[verb] [count] [noun], styled identically to built-in rows.history.push→appswith the install id).appIdis inactions.hiddenAppIdsdoes not render.iconfalls back to theCustomAppsglyph.pnpm typecheckandpnpm lintpass.Notes
hiddenAppIds, already infeature/studio-apps-action). Merge order: 3979 → 3980 → 3981 intofeature/studio-apps-action.icon-names.tsis a snapshot of the design-system icon set; regenerate if the design system adds icons. Staleness is safe — a newly-added icon simply falls back toCustomApps.Impact & Surface Area of Change
useEnabledActionsnow depends onuseInstalledApps(a workspace-scoped React Query) and returns aRenderableAction[]union instead ofActionDefinition[]. Only consumer isActionsCard; the editor sidebar uses its ownuseActionsand is unaffected.ActionDefinition.iconwidened from the 4-valueActionItemIcontoIconType— verify built-in action icons still render.🤖 Generated with Claude Code