Skip to content

feat(portal-framework-core, portal-plugin-dashboard): add visibility hook and simplify widget definition#488

Merged
pcfreak30 merged 1 commit intodevelopfrom
libs/portal-plugin-dashboard
Sep 1, 2025
Merged

feat(portal-framework-core, portal-plugin-dashboard): add visibility hook and simplify widget definition#488
pcfreak30 merged 1 commit intodevelopfrom
libs/portal-plugin-dashboard

Conversation

@pcfreak30
Copy link
Copy Markdown
Member

@pcfreak30 pcfreak30 commented Sep 1, 2025

  • Introduce visibilityHook to conditionally render widgets
  • Simplify WidgetDefinition by extending WidgetRegistration
  • Optimize WidgetArea to filter out invisible widgets
  • Spread widget properties directly into definition
  • Add visibility hook for email verification banner widget

Summary by CodeRabbit

  • New Features
    • Widgets now support per-item visibility, allowing sections to appear or hide dynamically based on user context.
    • The email verification banner now only shows for signed-in users who haven’t verified their email, and remains hidden for verified or unsigned-in users.
    • Improved dashboard rendering performance by skipping non-visible widgets, reducing empty space and unnecessary layout work.

…hook and simplify widget definition

- Introduce `visibilityHook` to conditionally render widgets
- Simplify `WidgetDefinition` by extending `WidgetRegistration`
- Optimize `WidgetArea` to filter out invisible widgets
- Spread widget properties directly into definition
- Add visibility hook for email verification banner widget
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Sep 1, 2025

⚠️ No Changeset found

Latest commit: 721df58

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Sep 1, 2025

Walkthrough

Adds per-widget visibility via an optional visibilityHook in WidgetRegistration, updates WidgetArea to evaluate and filter widgets by visibility, refactors WidgetDefinition to extend WidgetRegistration (minus componentName), and adjusts Framework.registerWidget to spread registration into the stored definition. Dashboard plugin adds a visibilityHook for the email verification widget.

Changes

Cohort / File(s) Summary of Changes
Widget typing and registration
libs/portal-framework-core/src/api/framework.ts, libs/portal-framework-core/src/types/widget.ts, libs/portal-framework-core/src/types/plugin.ts
Framework.registerWidget now spreads the incoming registration into WidgetDefinition and sets component via remote loader. WidgetDefinition now extends Omit<WidgetRegistration, 'componentName'> with component. WidgetRegistration gains optional visibilityHook?: () => boolean. Plugin type imports PluginWidgets (no API change).
Widget rendering logic
libs/portal-framework-core/src/components/WidgetArea.tsx
Evaluates each widget’s visibilityHook, short-circuits when none visible, renders only widgets with true visibility, preserving existing grid/size logic. Public component API unchanged.
Dashboard plugin visibility
libs/portal-plugin-dashboard/src/widgetRegistrations.ts
Adds visibilityHook to core:dashboard:email-verification widget using useGetIdentity(); returns visible when identity exists and is not verified. Additional imports added.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant WidgetArea
  participant WidgetReg as Widget Registration
  participant Visibility as visibilityHook()
  participant Framework
  participant Loader as Remote Component Loader

  User->>WidgetArea: Render area
  WidgetArea->>WidgetReg: For each widget, check visibilityHook?
  alt visibilityHook present
    WidgetArea->>Visibility: Call hook
    Visibility-->>WidgetArea: boolean
  else no hook
    Note over WidgetArea: Default visible
  end
  WidgetArea->>WidgetArea: Filter to visible widgets
  alt Any visible?
    WidgetArea->>Framework: Request component for widget
    Framework->>Loader: createRemoteComponentLoader(pluginId, componentPath)
    Loader-->>Framework: Component
    Framework-->>WidgetArea: Component
    WidgetArea-->>User: Render visible widgets
  else None visible
    WidgetArea-->>User: Render nothing (null)
  end
Loading
sequenceDiagram
  autonumber
  participant Dashboard as Dashboard Plugin
  participant EmailWidget as Email Verification Widget
  participant Identity as useGetIdentity()
  Dashboard->>EmailWidget: visibilityHook()
  EmailWidget->>Identity: Fetch identity
  Identity-->>EmailWidget: { verified: boolean } | undefined
  alt identity exists and not verified
    EmailWidget-->>Dashboard: true (show)
  else otherwise
    EmailWidget-->>Dashboard: false (hide)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A nibble of logic, a hop through the DOM,
I peek with a hook—should I show, should I stay home?
Widgets now whisper, “visible, maybe not,”
I filter the meadow, display the best spot.
With types all tidied, I thump in delight—
Verified? Not yet? Then bring on the light! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch libs/portal-plugin-dashboard

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (5)
libs/portal-framework-core/src/types/plugin.ts (1)

9-9: Use a type-only import for PluginWidgets

Prevents emitting a runtime import from a types-only module.

-import { PluginWidgets } from "./widget";
+import type { PluginWidgets } from "./widget";
libs/portal-framework-core/src/api/framework.ts (1)

279-288: Avoid leaking componentName into WidgetDefinition; spread only allowed fields

Spreading ...widget can inadvertently include componentName (and any future extras) into the stored definition. Destructure to omit it and explicitly pass it to the loader.

-    const definition: WidgetDefinition = {
-      ...widget,
-      component: createRemoteComponentLoader(
-        {
-          componentPath: widget.componentName,
-          pluginId: widget.pluginId,
-        },
-        this,
-        defaultRemoteOptions,
-      ),
-    };
+    const { componentName, ...rest } = widget as any;
+    const definition: WidgetDefinition = {
+      ...rest,
+      component: createRemoteComponentLoader(
+        {
+          componentPath: componentName,
+          pluginId: widget.pluginId,
+        },
+        this,
+        defaultRemoteOptions,
+      ),
+    };

If pluginId isn’t part of WidgetDefinition, ensure rest excludes it too:

-    const { componentName, ...rest } = widget as any;
+    const { componentName, pluginId, ...rest } = widget as any;

Please confirm the intended WidgetDefinition shape so we can finalize the exact destructuring.

libs/portal-plugin-dashboard/src/widgetRegistrations.ts (1)

6-8: Remove unused import

useFramework isn’t used.

-import { Identity, useFramework } from "@lumeweb/portal-framework-core";
+import { Identity } from "@lumeweb/portal-framework-core";
libs/portal-framework-core/src/types/widget.ts (2)

35-35: Consistency nit: prefer double quotes inside Omit key

Matches the file’s prevailing quote style.

-export interface WidgetDefinition extends Omit<WidgetRegistration, 'componentName'> {
+export interface WidgetDefinition extends Omit<WidgetRegistration, "componentName"> {

61-63: Type name vs. shape mismatch

WidgetRegistrationWithComponent doesn’t include component despite the name. Consider extending WidgetDefinition (which has component) instead of WidgetRegistration, or add the component field here.

-export interface WidgetRegistrationWithComponent extends WidgetRegistration {
+export interface WidgetRegistrationWithComponent extends WidgetDefinition {
   pluginId: NamespacedId;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 246374b and 721df58.

📒 Files selected for processing (5)
  • libs/portal-framework-core/src/api/framework.ts (1 hunks)
  • libs/portal-framework-core/src/components/WidgetArea.tsx (2 hunks)
  • libs/portal-framework-core/src/types/plugin.ts (1 hunks)
  • libs/portal-framework-core/src/types/widget.ts (2 hunks)
  • libs/portal-plugin-dashboard/src/widgetRegistrations.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
libs/portal-framework-core/src/components/WidgetArea.tsx (1)
libs/portal-framework-core/src/util/grid.ts (6)
  • getResponsiveGridColumnSpanClass (282-302)
  • getGridRowSpanClass (215-218)
  • getMinWidthClass (278-280)
  • getMinHeightClass (274-276)
  • getMaxWidthClass (270-272)
  • getMaxHeightClass (266-268)
libs/portal-framework-core/src/types/widget.ts (1)
libs/portal-framework-core/src/index.ts (2)
  • WidgetDefinition (59-59)
  • WidgetRegistration (60-60)
libs/portal-plugin-dashboard/src/widgetRegistrations.ts (1)
libs/portal-framework-core/src/types/portal.ts (1)
  • Identity (1-9)
🔇 Additional comments (1)
libs/portal-framework-core/src/types/widget.ts (1)

35-37: Destructure componentName before spreading or update WidgetDefinition
WidgetDefinition omits componentName, but registerWidget spreads the full widget (including componentName) into an object typed as WidgetDefinition, causing a TypeScript error.

  • Destructure out componentName (e.g. const { componentName, ...rest } = widget) before spreading, or remove 'componentName' from the Omit in WidgetDefinition.

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.

1 participant