Skip to main content

API

Platform API

Various APIs provided by the platform for all widgets, such as:

  • Themes;
  • Reserved props (List of possibly shared props);
  • Widget props.

Themes

Themes are objects describing custom application styles, provided to all widgets. Implementation/usage is described in the theme-serving documentation section.

  • Multiple objects could be provided.
  • Theme is dynamic.
  • Changing themes lead to CSS styles change.
  • Themes are provided through the customization backend.
  • All widgets get the active theme through the styled-components context.
  • Theme-derived styles usage is recommended, but not mandatory in the widgets.

Branding

  • All the branding elements - custom icons, images, fonts, and other assets.
  • Branding resides on the customization backend.
  • Currently, only fonts are implemented through the theming API.

Platform Meta Props

  • Props indicating the current state of the platform that is important for widgets.
  • Includes info on the current active dashboard, other available widgets metadata.
  • Typings available through @invent/shared-types package.
interface IPlatformMeta {
storeWidgetsById: Record<string, IWidgetMetadata<Record<string, unknown>>>;
platformWidgetsById: Record<string, IPlatformWidget>;
currentDashboardId?: string;
currentDashboard: IDashboard | undefined;
}

State sharing

  • Widgets can read and write to the special section of app state.
  • useShareValue, useSelectSharedValue,useDeleteSharedValue hooks are provided for every widget through props, typing could be found in @invent/shared-types.
import React from "react";
import { UseSelectSharedValueT, ISharedState } from "@invent/shared-types";
import { path } from "ramda";

/* Lens function. It "focuses" key in `ISharedState` object. */
function profileSelector(state: ISharedState) {
return path<UserProfileT | undefined>(["userProfile"], state);
}

const MyComponent = ({ useSelectSharedValue }: PropsType) => {
const userProfile = useSelectSharedValue(profileSelector);
return <div>{userProfile.name}</div>;
};
import React, { useEffect } from "react";
import { v4 } from "uuid";

const ShareRandomValueComponent = ({ useShareValue }: PropsType) => {
const shareValue = useShareValue();

useEffect(() => {
const randomValue = v4();
/*
This value could be accessed with function like:

function randomValueSelector (state: ISharedState){
return path<UserProfileT>(['randomValue'], state);
}
const randomSharedValue = useSelectSharedValue(randomValueSelector);
*/
shareValue(["randomValue"], randomValue);
}, []);

return <div>{randomValue}</div>;
};
  • The dashboard-bound scope is auto-created in this section when some dashboard becomes active, it can be used to connect widget instances on the same board.

Http client

  • Platform provides a default HTTP client for widgets.
  • It takes care of credentials, tokens, etc.
  • Potentially, different clients/communication bindings could be provided.
  • Widgets can use custom ways of making requests if developers find it suitable.

Remote module rendering inside widgets

  • platformMeta, remoteModule and generateWidgetData props, if used together, can make it possible to easily render any other known widget (to the host app) inside your widget.
  • remoteModule prop provides a React component that the Platform uses to render remotes
  • generateWidgetData - accepts widget metadata (specific, or selected from platformMeta), and generates an object consumable by <RemoteModule/>.
  • also described at Module Federation.

Widget instance ID on the specific dashboard

  • dashboardWidgetInstanceId identifies widget instance inside the specific dashboard, and could be used for state sharing across this dashboard, or other means.

Use React Query Data

  • useQueryData prop is a hook, that internally subscribes to the react-query cache, and returns an updated query state object if it was changed. It should be provided with a query key argument, which works like path-based selectors in Redux. react-query caches data with long query key-based hashes which contain all the query parameters, but with useQueryData we can read updates while only providing a partial key, thus avoiding the need to gather all the query parameters to read it in some other micro frontends.
import { useQuery } from "react-query";
import { path } from "ramda";
import type { ISharedState } from "@invent/shared-types";

function userProfileSelector(state: ISharedState) {
return path<IUserProfile | undefined>(["userProfile"], state);
}

const GetUserProfile = ({
apiUrl,
httpClient,
useShareValue,
useSelectSharedValue,
}: PropsType) => {
const shareValue = useShareValue();
const userProfile = useSelectSharedValue(userProfileSelector);

const profileEndpoint = `${apiUrl}/profile`;

const { data: profileData } = useQuery<IUserProfile>(
[profileEndpoint, userProfile],
async () => {
if (apiUrl && !userProfile) {
return await httpClient(profileEndpoint, { traceId: projectId });
}
}
);

useEffect(() => {
shareValue(["userProfile"], data);
}, [data]);

return <div>{data.name}</div>;
};

Platform Widget Props

Platform widgets have some specific props for control application state.

type PlatformWidgetComponentProps = {
handleSignin: VoidFinction;
handleSignout: VoidFinction;
};