Fluent Commerce Logo
Sign In

Display REST API Data in Standard Library Components

How-to Guide
Extend

Author:

Lesley Dean

Changed on:

2 May 2024

Key Points

  • For Frontend (React) Developers who are familiar with using the Fluent OMX Component SDK
  • Build a REST API Data Provider Component to enable the standard Component Library to render data from the Fluent Platform REST APIs
  • Learn how to override the data provided to components
  • Learn how to support template value props for dynamic input
  • Learn how to decorate the query results for enabling
    `byName`
    attributes access in the manifest

Steps

Introduction

Step arrow right iconOverview

The Fluent UX Framework provides a Component Library for quickly configuring Fluent web apps.

Currently these Components receive data from the Page Query, which is GraphQL. The Fluent Platform includes a number of REST APIs, not available via GraphQL. This means that the standard Components can't display REST based data.

Imagine if you could easily use the UX Framework Component Library to build and extend screens with data from these APIs?

This article will guide you through implementing a custom data provider component that makes it possible to display REST based data in the standard UX Framework Component Library.

Problem Statement & Scenario

Step arrow right iconProblem Statement

Since the standard Components accept datasources from the page query defined in the manifest, the only way to display data from REST APIs is to write custom components using the Component SDK.

This would need to be done for each component where a custom data source is required, and potentially adds significant effort to implementation.

While the Component SDK provides the tools to achieve this, it would be ideal if we could reuse the existing component library, and configure an alternate data source in the manifest.

Step arrow right iconScenario

Imagine you needed to provide an enhanced Activity Viewer, Webhooks Dashboard, or display information from the Event API on your Orders Dashboard.

Additionally, you need to achieve this while maintaining a consistent look, feel, and configuration experience, while minimising the total cost of custom code components?

What if this could be achieved with one simple custom component, and work for all components in the library?

No alt provided

An example Dashboard using Event API as a datasource for the standard Dashboard Tile Component

Solution

Step arrow right iconApproach

Following the pattern of the default page component, let's decouple the data fetching and display logic so that we can use the standard cards, lists, and other library components.

Let's write a simple custom component as a manifest configurable data provider for nested components to use.

In this approach, the data provider component could accept an

`endpoint`
, and some additional
`props`
to configure the request or body parameters. Internally, it would execute the REST Call, and return a data source for the nested components defined within the manifest.

Example manifest usage:

1{
2  "component": "devrel.provider.rest",
3  "props": {
4    "endpoint": "api/v4.1/event",
5    "props": {
6      "context.entityType": "ORDER",
7      "eventType": "ORCHESTRATION",
8      "eventStatus": "FAILED",
9      "from": "{{dateStringFormatter (dateAdd hours=-24) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}"
10    }
11  },
12  "descendants": [
13    /* display components here... */
14  ]
15}

Language: plain_text

Name: Example REST Data Provider Configuration

Description:

Example target manifest configuration experience for components using REST data

Implementation Steps

Step arrow right iconStep 1: Create a custom Data Provider Component

Using the Component SDK, create a new file in the components folder called

`RestProvider.tsx`
.

Create a new Interface to accept the RestProviderProps:

1export interface RestProviderProps {
2  data: any;
3  endpoint: string;
4  props: Record<string, string>;
5}

Language: tsx

Name: RestProviderProps

Description:

Define the manifest configurable props for the RestDataProvider

The

`data`
field will automatically be provided by the UX Framework and contain the Page Query Data.

The

`endpoint`
and
`props`
fields will be configured in the manifest.

Now you can create the Component:

1export const RestProvider: FC<RestProviderProps> = ({
2      data,
3      endpoint,
4      props,
5    }) => {
6      // TODO: Implementation Code here...
7};

Language: tsx

Name: RestProviderComponent Definition

Description:

Define the RestProvider Component

A you can see, we make use of a React Function Component (

`FC`
), which you should import from
`react`
.

Step arrow right iconStep 2: Render Props and Build the REST endpoint with props

The UX Framework provides the ability to pass page query and URL parameters into the props values. The best way to handle this is to support template strings as props, which then need to be “rendered”. The TemplateRegistry provides a render function to do this for you. So all we need to do is loop through the provided props, and call the render function.

Let’s create a separate function in the same file for this:

1const getRenderedProps = (props: Record<string, string>, data: any) => {
2  return Object.fromEntries(
3    Object.entries(props).map(([key, value]) => [
4      key,
5      TemplateRegistry.render(value, data)
6    ])
7  );
8};

Language: tsx

Name: RestDataProvider getRenderedProps function

Description:

Render configured template strings as values for the props

You will need to import the TemplateRegistry from

`mystique/registry/TemplateRegistry`
.

Now we can use this function in our Component implementation and build the endpoint:

1  const [endPointWithProps] = useState(
2    () => `${endpoint}?${new URLSearchParams(getRenderedProps(props, data))}`
3  );

Language: tsx

Name: RestDataProvider - build endpoint

Description:

Build the REST API Endpoint with URL parameters

The

`useState`
hook should be imported from
`react`
.

As you can see from the code above, we will keep state of the provided parameters, so as not to re-render  the component unnecessarily if the props values are changing all the time. This is relevant to our example use case, where we will be providing a “Last 24 Hours” date range to the request, and this would be changing every millisecond, triggering a re-render unnecessarily.

Step arrow right iconStep 3: Call the REST API and return the result to the child components

The Component SDK provides a

`useRest`
hook to call the Fluent Platform REST APIs:

1const response = useRest(endPointWithProps);

Language: tsx

Name: RestDataProvider - useRest

Description:

Call the REST API

Import the

`useRest`
hook from
`mystique/hooks/useRest`
.

The

`response`
will contain 2 simple fields,
`status`
and
`result`
. We can use the
`status`
to determine what to return using a switch statement.

In the event that the API call is still executing, it is helpful to show the

`Loading`
component as helpful feedback for the user.

In the event that the API returns an error, we can log the rendered request to the console to help developers debug the problem, and depending on the use case present something else to the UI.

When the API returns successfully, the status will be

`ok`
, and the
`result`
object will be populated with the REST response payload. In this case, we can then return the
`Children`
component, and override the data source. The result of the REST query now becomes the
`data`
value injected into each descendant component, so any component designed to display information can be used to show it.

Let’s implement a simple switch statement to render feedback to the user:

1switch (response.status) {
2  case "ok":
3    return <Children dataOverride={decorateQueryResult(response.result)} />;
4
5  case "loading":
6    return <Loading />;
7
8  default:
9    // includes "error"
10    console.error(
11      `Could not retrieve data from REST API: ${JSON.stringify(endPointWithProps)}\n Response: ${JSON.stringify(response, null, 2)}`
12    );
13    return <div>Error occurred loading data from REST API</div>;
14}

Language: tsx

Name: RestDataProvider - switch return

Description:

Handle each API Response

Import

`Children`
from
`mystique/components/Children`
,
`Loading`
from
`mystique/components/Loading`
, and
`decorateQueryResult`
from
`'../../../lib/mystique-export'`
.

Step arrow right iconStep 4: Register the Component and try it out

In the

`index.tsx`
, register the component:

1ComponentRegistry.register(["devrel.provider.rest"], RestProvider, {category: "content"});

Language: tsx

Name: RestDataProvider - register component

Description:

Register the RestDataProvider Component in the ComponentRegistry

You'll need to import

`RestProvider`
from
`'./components/providers/RestProvider'`
.

Start your local server by running

`yarn start`
, and add your local server to the plugins configuration of your Fluent OMS webapp manifest:

1{
2    "type": "url",
3    "src": "http://localhost:3001"
4}

Language: json

Name: RestDataProvider - add local plugin to manifest

Description:

Add your localhost plugin to the app manifest

Since we’ll try this using the Event API, let’s use the Insights section of the Fluent OMS webapp. If you haven’t already, you will need to override the default Insights fragment for Fluent OMS.

Let’s add a new Page to the Insights fragment, and try out the component:

1{
2  "type": "page",
3  "path": "/devrel-events-dashboard",
4  "nav": {
5    "label": "DevRel Events Dashboard",
6    "icon": "MdEvent"
7  },
8  "component": "fc.page",
9  "props": {
10    "title": "DevRel Events Dashboard - Updated on: {{dateStringFormatter (dateAdd)}}"
11  },
12  "descendants": []
13}

Language: json

Name: RestDataProvider - add new Insights page manifest

Description:

Add a new "Events Dashboard" page in the Insights manifest fragment

To test the REST Provider Component, we’ll use the standard

`fc.dashboard.threshold`
component from the standard Component Library. This will need to be nested as a child descendant of the RestProvider component:

1{
2  "component": "devrel.provider.rest",
3  "props": {
4    "endpoint": "api/v4.1/event",
5    "props": {
6      "context.entityType": "ORDER",
7      "eventType": "ORCHESTRATION",
8      "eventStatus": "FAILED",
9      "from": "{{dateStringFormatter (dateAdd hours=-24) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}"
10    }
11  },
12  "descendants": [
13    {
14      "component": "fc.dashboard.threshold",
15      "props": {
16        "label": "Failed",
17        "value": "{{ results.length }}",
18        "thresholdLow": 1,
19        "thresholdHigh": 10,
20        "link": "#/events?context.entityType=ORDER&eventType=ORCHESTRATION&eventStatus=FAILED&from={{dateStringFormatter (dateAdd hours=-24) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true}}"
21      }
22    }
23  ]
24}

Language: json

Name: RestDataProvider - configure component in manifest

Description:

Use the RestDataProvider to display Event data in a standard Dashboard Threshold Tile Component

As you can see above, we’re configuring the

`devrel.provider.rest`
component to call the Event API with filter parameters to return only FAILED Order Orchestration Events for the last 24 hours, but remember you could pass in dynamic values from a page query result based on the use case.

No alt provided

A standard Dashboard Tile Component displaying failed Order Orchestration Events

What else can you do?

Step arrow right iconThe Art of the Possible...

The applications for this include composing various UI capabilities for the data exposed by the Fluent Platform APIs. You can build out Event Dashboards, Webhook Dashboards (coming soon), enhanced Activity views for entities, display execution paths and status transition information, or even display a List of Workflows and a detailed Rule Library.

Combining this with standard GraphQL page queries, you can build richer domain or entity based dashboards, activity views, etc.

You can make further enhancements to this component, such as rendering the Loading and Error responses in a card.

Additionally, you can swap out the

`useRest`
hook with the
`getRest`
promise to query data from any other external API.

Finally, while this component won't allow support for all child component features, such as list paging and filtering, you can combine this with a custom List wrapper component, to enable these capabilities.

The REST API Data Provider demonstrates how quick and easy it is to extend the UX Framework, and maximise reuse of standard library components for REST based data.

Conclusion

Step arrow right iconWrapping up

As you can see, this little custom component makes it super simple to enable presentation of REST API based data with the standard Component Library.

Copyright © 2024 Fluent Retail Pty Ltd (trading as Fluent Commerce). All rights reserved. No materials on this docs.fluentcommerce.com site may be used in any way and/or for any purpose without prior written authorisation from Fluent Commerce. Current customers and partners shall use these materials strictly in accordance with the terms and conditions of their written agreements with Fluent Commerce or its affiliates.

Fluent Logo