Custom Marketplace UI
Why build a custom marketplace UI?
The embedded marketplace allows you to easily embed a Prismatic's marketplace as an iframe in your app. Theming gives you some flexibility with the look and feel of the marketplace, and lets you match your app's branding colors and font.
But, you may want to customize the marketplace further. With a custom marketplace UI, you can query Prismatic's API for a list of available integrations and map that list to native UI elements within your app. You can present integrations as material cards, in a table, as a listview - any way you like.
A full example implementation of a custom UI is available on GitHub.
Querying for marketplace integrations
The marketplaceIntegrations query yields an array of integrations that are available in marketplace. Since Prismatic's API is GraphQL-based, you can query for more or fewer fields, but this query (and its corresponding TypeScript types) generally has the information you'll need to display a marketplace:
- GraphQL Query
- TypeScript Types
query getMarketplaceIntegrations {
marketplaceIntegrations(includeActiveIntegrations: true) {
nodes {
id
name
allowMultipleMarketplaceInstances
avatarUrl
category
description
isCustomerDeployable
marketplaceConfiguration
overview
versionNumber
firstDeployedInstance {
id
}
deployedInstances
deploymentStatus
}
}
}
interface MarketplaceIntegration {
id: string;
name: string;
allowMultipleMarketplaceInstances: boolean;
avatarUrl?: string;
category: string;
description: string;
isCustomerDeployable: boolean;
marketplaceConfiguration: string;
overview: string;
versionNumber: number;
firstDeployedInstance?: { id: string };
deployedInstances: "ZERO" | "ONE" | "MULTIPLE";
deploymentStatus?: "ACTIVATED" | "PAUSED" | "UNCONFIGURED";
}
type MarketplaceIntegrationsResponse = {
data: {
marketplaceIntegrations: {
nodes: MarketplaceIntegration[];
};
};
};
A few notes about this query:
- The
includeActiveIntegrations
parameter is optional. Include it if you have customer-specific integrations are deployed to only a hand-full of customers, and have not been added to your marketplace it. This will make those integrations appear to the customers who have instances of those integrations. - The
firstDeployedInstance
,deployedInstances
, anddeploymentStatus
properties are used for performance reasons - they're more performant than including aninstances { nodes { } }
connection in the query.firstDeployedInstance
represents the first instance of this integration that is deployed to the customer making the query (if any).deployedInstances
will have one of three values -"ZERO"
,"ONE"
or"MULTIPLE"
and represents the number of instances this customer has deployed.deploymentStatus
will have one of four values -"ACTIVATED"
,"PAUSED"
,"UNCONFIGURED"
ornull
, depending on the state of the instance the customer has deployed (if any).
To issue the query to Prismatic, you can either use the embedded package's prismatic.graphqlRequest
function, or you can leverage a GraphQL client like graphql-request.
See Embedded API Requests for more.
Displaying integration avatars
Each integration returned from the query above has an optional avatarUrl
property, which you can use to fetch the icon associated with your integration.
Your avatarUrl
will look something like /media/UUID/Integration/UUID/EnumMeta.AVATAR/UUID.png
.
With an avatarUrl
in hand, make make an authenticated API call to Prismatic with your URL as a relative path (so, something like https://app.prismatic.io/media/UUID/Integration/UUID/EnumMeta.AVATAR/UUID.png
).
Ensure that your request is authenticated with your embedded JWT as a header, Authorization: Bearer ${TOKEN}
.
This request will return JSON data that looks like
{ "data": { "url": "https://s3.us-west-2.amazonaws.com/PRESIGNED-URL" } }
You can now set that presigned URL as your image's src
property.
Here's an example ReactJS implementation that displays an integration's avatar icon (if it has one), or defaults to a generic icon if it does not.
function PrismaticAvatar({ avatarUrl, token }) {
const [src, setSrc] = React.useState("");
useEffect(() => {
let mounted = true;
if (avatarUrl) {
// Fetch the presigned URL from
// https://app.prismatic.io/media/UUID/Integration/UUID/EnumMeta.AVATAR/UUID.png
fetch(`https://app.prismatic.io${avatarUrl}`, {
headers: { Authorization: `Bearer ${token}` },
}).then((response) => {
response.json().then((data) => {
if (mounted) {
setSrc(data.url);
}
});
});
}
return () => {
mounted = false;
};
}, []);
// If the integration has no avatar URL, display a generic avatar icon
// Otherwise, display an avatar with the presigned URL we fetched
return src ? (
<Avatar variant="rounded" src={src} />
) : (
<Avatar>
<CableTwoTone />
</Avatar>
);
}
Opening integration configuration windows
After mapping marketplace integrations to UI elements in your app, you'll want to make them clickable, so users can open the config wizard modal and deploy instances for themselves. Though you can build the config wizard from scratch and set config variables programmatically, we generally recommend that you lean on Prismatic's implementation of the config wizard. Config wizards are complicated!
To open a config wizard, issue a prismatic.configureInstance()
call with your integration's name (or an existing instance's ID).
See Embedding Marketplace for more details.