Skip to main content

Core Features

This guide covers the essential functionality for your widget including API integration, notifications, React Query for data management, and platform metadata access. These features form the core capabilities that enable widgets to communicate with backend services, provide user feedback, share data efficiently, and integrate with the platform's dashboard system.

Table of Contents

  1. Implementing API Integration
  2. Adding Notifications
  3. Implementing React Query Integration
  4. Dashboard Navigation and Platform Meta

11. Implementing API Integration

Reference:

11.1 HTTP Client Usage

The httpClient is provided as a prop and automatically includes:

  • JWT token in Authorization header
  • User role in x-user-role header
  • Trace ID for request tracking
const response = await httpClient("API_URL", {
traceId: "TRACE_ID_STRING",
method: "get",
params: {
queryParams: {
key: "value",
},
},
});

11.2 Getting Context Data from URL

Reference: Required API Data

// Get query parameters from URL
const searchParams = new URLSearchParams(window.location.search);
const accountId = searchParams.get("accountId");
const userId = searchParams.get("userId");

// Use in API calls
const getAccountInfo = async (accountId: string) =>
await httpClient(`${apiUrl}/accounts/info`, {
traceId: "kpi-tracker-account-info",
params: {
queryParams: {
accountId: accountId,
},
},
});

11.3 Third-Party API Integration

const thirdPartyApiUrl = "https://api.thirdparty.com";

const fetchThirdPartyData = async () => {
const response = await httpClient(`${thirdPartyApiUrl}/data`, {
method: "get",
traceId: "kpi-tracker-third-party",
params: {
queryParams: {
apiKey: "YOUR_API_KEY",
},
},
});
return response;
};

11.4 Custom Token Authentication

const response = await httpClient("API_URL", {
traceId: "TRACE_ID",
token: "CUSTOM_TOKEN",
});

12. Adding Notifications

Reference: Host application (wlabel) API

The platform provides a notification system using react-toastify. For a complete list of options, refer to the react-toastify API documentation.

12.1 Show Notification Function

export type InfoNotificationTypeT = "info" | "error" | "warning" | "success";
export type ShowNotificationT = (
type: InfoNotificationTypeT,
content: ToastContent,
options?: ShowNotificationOptionsT
) => void;

12.2 Essential Notification Examples

import React from "react";
import type { IWidgetProps } from "../types/widget-props";

const KpiTrackerWithNotifications: React.FC<IWidgetProps> = ({
showNotification,
httpClient,
apiUrl,
}) => {
const fetchData = async () => {
try {
const data = await httpClient(`${apiUrl}/kpi`, {
traceId: "kpi-fetch",
});

// Success notification
showNotification("success", "KPI data loaded successfully", {
position: "bottom-right",
autoClose: 3000,
});

return data;
} catch (error) {
// Error notification
showNotification("error", "Failed to load KPI data", {
position: "top-center",
autoClose: 5000,
});
}
};

const saveSettings = () => {
// Info notification
showNotification("info", "Settings saved", {
position: "bottom-right",
autoClose: 2000,
});
};

const validateData = () => {
// Warning notification
showNotification("warning", "Please review your data", {
position: "top-right",
autoClose: 4000,
});
};

return (
<div>
<button onClick={fetchData}>Load Data</button>
<button onClick={saveSettings}>Save</button>
<button onClick={validateData}>Validate</button>
</div>
);
};

export default KpiTrackerWithNotifications;

12.3 Common Options

// Auto-close after timeout
showNotification("success", "Operation completed", {
autoClose: 3000, // milliseconds
});

// Position options
showNotification("info", "Message", {
position:
"top-left" |
"top-center" |
"top-right" |
"bottom-left" |
"bottom-center" |
"bottom-right",
});

// Persistent notification (no auto-close)
showNotification("error", "Critical error", {
autoClose: false,
});

For additional customization options such as custom icons, transitions, progress bars, and more, consult the react-toastify documentation.


13. Implementing React Query Integration

Reference: Host application (wlabel) API

13.1 Using useQueryData Hook

The useQueryData hook allows widgets to access cached query data from other widgets.

import { useQuery } from "react-query";
import type { IWidgetProps } from "../types/widget-props";

// Widget A: Creates the query
const WidgetA: React.FC<IWidgetProps> = ({ httpClient, apiUrl }) => {
const defaultDashboardQuery = useQuery<{ result: string }, unknown, string>(
["navigation", "defaultDashboard"],
() =>
httpClient(`${apiUrl}/dashboards/default-dashboard`, {
traceId: "default-dashboard",
}),
{
select: (data) => data?.result,
staleTime: 5 * 60 * 1000, // 5 minutes
}
);

return <div>Dashboard: {defaultDashboardQuery.data}</div>;
};

// Widget B: Accesses the cached query
const WidgetB: React.FC<IWidgetProps> = ({ useQueryData }) => {
const defaultDashboardQueryData = useQueryData([
"navigation",
"defaultDashboard",
]);

return (
<div>
{defaultDashboardQueryData ? (
<p>Cached dashboard: {defaultDashboardQueryData}</p>
) : (
<p>No cached data available</p>
)}
</div>
);
};

13.2 Complete React Query Example

import React from "react";
import { useQuery, useQueryClient } from "react-query";
import type { IWidgetProps } from "../types/widget-props";

interface IUserProfile {
id: string;
name: string;
email: string;
}

const UserProfileWidget: React.FC<IWidgetProps> = ({
httpClient,
apiUrl,
useQueryData,
showNotification,
}) => {
// Create a query
const { data, isLoading, error, refetch } = useQuery<IUserProfile>(
["userProfile", apiUrl],
async () => {
const response = await httpClient(`${apiUrl}/user/profile`, {
traceId: "user-profile",
});
return response;
},
{
staleTime: 10 * 60 * 1000, // 10 minutes
cacheTime: 30 * 60 * 1000, // 30 minutes
refetchOnWindowFocus: false,
}
);

// Access cached query from another widget
const cachedDashboardData = useQueryData(["navigation", "currentDashboard"]);

if (isLoading) {
return <div>Loading profile...</div>;
}

if (error) {
showNotification("error", "Failed to load user profile", {
position: "top-center",
autoClose: 5000,
});
return <div>Error loading profile</div>;
}

return (
<div>
<h3>User Profile</h3>
<p>Name: {data?.name}</p>
<p>Email: {data?.email}</p>

{cachedDashboardData && (
<p>Current Dashboard: {cachedDashboardData.name}</p>
)}

<button onClick={() => refetch()}>Refresh Profile</button>
</div>
);
};

export default UserProfileWidget;

13.3 Query Key Conventions

Use consistent query keys for shared data:

// User-related queries
["user", "profile"][("user", "settings")][("user", "permissions")][
// Dashboard-related queries
("navigation", "defaultDashboard")
][("navigation", "currentDashboard")][("dashboard", dashboardId, "widgets")][
// Data queries
("kpi", "revenue")
][("kpi", "users")][("accounts", accountId)];

14. Dashboard Navigation and Platform Meta

Reference: @invent/platform-api

14.1 usePlatformMeta Hook

The usePlatformMeta hook from @invent/platform-api provides access to platform metadata including dashboard and widget information.

Import:

import { usePlatformMeta } from "@invent/platform-api";
import type { IPlatformMeta } from "@invent/shared-types";

IPlatformMeta Interface:

interface IPlatformMeta {
storeWidgetsById: Record<string, IWidgetMetadata<Record<string, unknown>>>;
platformWidgetsById: Record<string, IPlatformWidget>;
currentDashboardId?: string;
currentDashboard: IDashboard | undefined;
}

interface IDashboard {
meta: {
id: string;
creatorId: string;
name: string;
version: string;
group: string;
imageUrl: string;
};
widgets: Record<string, IDashboardWidget>;
}

14.2 Using Platform Meta

import React from "react";
import { usePlatformMeta } from "@invent/platform-api";
import type { IWidgetProps } from "../types/widget-props";

const NavigationWidget: React.FC<IWidgetProps> = () => {
const platformMeta = usePlatformMeta();

const currentDashboard = platformMeta.currentDashboard;
const currentDashboardId = platformMeta.currentDashboardId;
const storeWidgets = platformMeta.storeWidgetsById;
const platformWidgets = platformMeta.platformWidgetsById;

return (
<div>
<h3>Dashboard Information</h3>
{currentDashboard ? (
<div>
<p>Dashboard Name: {currentDashboard.meta.name}</p>
<p>Dashboard ID: {currentDashboardId}</p>
<p>Creator: {currentDashboard.meta.creatorId}</p>
<p>Widgets Count: {Object.keys(currentDashboard.widgets).length}</p>
</div>
) : (
<p>No dashboard loaded</p>
)}

<h4>Available Store Widgets</h4>
<ul>
{Object.entries(storeWidgets).map(([id, widget]) => (
<li key={id}>{widget.name}</li>
))}
</ul>
</div>
);
};

export default NavigationWidget;

14.3 Accessing Dashboard Widgets

const DashboardWidgetsViewer: React.FC = () => {
const platformMeta = usePlatformMeta();
const currentDashboard = platformMeta.currentDashboard;

if (!currentDashboard) {
return <div>No dashboard selected</div>;
}

return (
<div>
<h3>Widgets on Current Dashboard</h3>
<ul>
{Object.entries(currentDashboard.widgets).map(
([instanceId, widget]) => (
<li key={instanceId}>
<strong>{widget.name}</strong>
<pre>{JSON.stringify(widget, null, 2)}</pre>
</li>
)
)}
</ul>
</div>
);
};

14.4 Complete Platform Meta Example

import React, { useEffect } from "react";
import { usePlatformMeta } from "@invent/platform-api";
import { generatePath } from "react-router-dom";

const DASHBOARD_LIGHTBOX_PATH = "/dashboard/:dashboardId/widget/:widgetId";

const KpiTrackerWithPlatformMeta: React.FC<IWidgetProps> = ({
dashboardWidgetInstanceId,
}) => {
const platformMeta = usePlatformMeta();

// Generate link to widget detail view
const widgetDetailLink = platformMeta.currentDashboardId
? generatePath(DASHBOARD_LIGHTBOX_PATH, {
dashboardId: platformMeta.currentDashboardId,
widgetId: dashboardWidgetInstanceId,
})
: null;

useEffect(() => {
console.log("Platform Meta:", {
dashboardId: platformMeta.currentDashboardId,
dashboardName: platformMeta.currentDashboard?.meta.name,
widgetCount: Object.keys(platformMeta.currentDashboard?.widgets || {})
.length,
storeWidgetsCount: Object.keys(platformMeta.storeWidgetsById).length,
platformWidgetsCount: Object.keys(platformMeta.platformWidgetsById)
.length,
});
}, [platformMeta]);

return (
<div>
<h2>KPI Tracker</h2>
{widgetDetailLink && <a href={widgetDetailLink}>View Details</a>}
{/* Widget content */}
</div>
);
};

export default KpiTrackerWithPlatformMeta;

Next Steps

Continue to: Layout and Testing