The Bundle
The bundle itself is available at https://bundle.greenscreens.ai/rates.bundle.js
NOTE: This script is distributed via Amazon CloudFront and may be inaccessible from certain regions due to geographic restrictions and access policies. If you experience loading issues, contact support.
To start using the bundle, include it in the body of your page using this script
:
<body>
<script src="[<https://bundle.greenscreens.ai/rates.bundle.js>](<https://gs-portable.s3.amazonaws.com/rates.bundle.js>)"></script>
//Your code that will use the bundle goes here.
</body>
When the page loads, the bundle will add a special TriumphIntelligence
object to the global window object. (Previously, the object was called Greenscreens
. It still works, but itβs now preferable to use TriumphIntelligence
.)
window: {
TriumphIntelligence: {
Rates: {
build()
}
}
}
The TriumphIntelligence
object contains all the intelligence.triumph.io bundles that you add to your page, in this case only Rates (it's the only bundle that exists for now.)
The build()
Function
Every bundle that is intended for rendering intelligence.triumph.io widgets has a build()
function inside of it. The build()
function is the main entry point of he bundle and its type is BundleBuildFunction that has the following signature:
type BundleBuildFunction = (params?: Params = {}) => BundleRenderer;
interface Params {
container?: HTMLElement | null;
baseApiPath?: string;
accessTokenProvider?: AccessTokenProvider;
user?: UserDescriptor;
widgets?: WidgetsConfiguration;
}
build()
function signature is BundleBuildFunction.
All parameters of the build function are optional, and the parameter object itself is optional as well.
The Parameters of the build()
Function
Lets look at each parameter of the build()
function in detail.
interface Params {
container?: HTMLElement | null;
baseApiPath?: string;
accessTokenProvider?: AccessTokenProvider;
user?: UserDescriptor;
widgets?: WidgetsConfiguration;
}
container
container?: HTMLElement | null;
container
is the HTMLElement that the intelligence.triumph.io widgets will be rendered to.
Example:
// a simple query DOM query
container: document.getElementById("gsContainerId");
// or in case of react
const gsContainerRef = useRef<HTMLDivelement>(null);
container: gsContainerRef.current
<div ref={gsContainerRef} />
baseApiPath
baseApiPath?: string;
baseApiPath
is the path to intelligence.triumph.io APIs that you want to use.
Example:
// in production
baseApiPath: "<https://intelligence.triumph.io>"
// deployed on to the testing environment
baseApiPath: "<https://intelligencetest.triumph.io>"
// during development - if you have a dev server with a proxy configured
baseApiPath: ""
// what is used in the demo app
baseApiPath: process.env.NODE_ENV === "development"
? ""
: "<https://intelligencetest.triumph.io>",
accessTokenProvider
accessTokenProvider?: AccessTokenProvider;
type AccessTokenProvider = () => string;
accessTokenProvider
is a function that, when called, should return a string to be sent to the TriumphIntelligence APIs in the Authorization header. Note that the value returned should be a valid Authorization:
header value, not just the token (e.g., Bearer ${token}
)
Example:
accessTokenProvider: () => `Bearer ${getCurrentUserAccessToken()}`
More information about how to acquire the token can be found here:
user
user?: UserDescriptor;
interface UserDescriptor {
email?: string;
}
user
is the object containing the data about the currently logged-in user
Example:
user: {
email: getCurrentUser().email
}
widgets
widgets?: WidgetsConfiguration;
interface WidgetsConfiguration{
targetBuyRate?: WidgetConfiguration;
targetSellRate?: WidgetConfiguration;
rateFeedback?: WidgetConfiguration;
marketIndices?: WidgetConfiguration;
routeMap?: WidgetConfiguration;
shortTermHistory?: WidgetConfiguration;
longTermHistory?: WidgetConfiguration;
topCarriers?: WidgetConfiguration;
negotiationCoach?: WidgetConfiguration;
laneAnalytics?: WidgetConfiguration;
networkRates?: WidgetConfiguration;
bids?: WidgetConfiguration;
quotes?: WidgetConfiguration;
}
interface WidgetConfiguration {
// Empty for now
}
widgets
is the object containing the configuration of what widgets you want the bundle to display
Example:
widgets: {
targetBuyRate: {},
routeMap: {},
negotiationCoach: {},
}
This configuration will only display 3 widgets: target buy rate, route map and negotiation coach.
The Return Type of the build()
Function
build()
function returns a BundleRenderer object that can be used to render the bundle and set all of the same parameters that the build()
function accepts. This is done so that you do not need to rebuild the bundle every time some parameter changes, e.g. other user logs in or token times out and is refreshed.
interface BundleRenderer {
setContainer: (container: HTMLElement) => Bundle;
setBaseApiPath: (baseApiPath: string) => Bundle;
setAccessTokenProvider: (accessTokenProvider: AccessTokenProvider) => Bundle;
setUser: (user: UserDescriptor) => Bundle;
setWidgets: (widgets: WidgetsConfiguration) => Bundle;
render: (inputValues: InputValues) => void;
}
Let's look at the methods of BundleRenderer in detail.
the setters
setContainer: (container: HTMLElement) => Bundle;
setBaseApiPath: (baseApiPath: string) => Bundle;
setAccessTokenProvider: (accessTokenProvider: AccessTokenProvider) => Bundle;
setUser: (user: UserDescriptor) => Bundle;
setWidgets: (widgets: WidgetsConfiguration) => Bundle;
These methods are used to set the properties needed during the rendering process. Same as the parameters that can be provided to the build() function.
render
render
is the function that does all of the main work of the bundle. It calls the APIs and displays the widgets using the results of those calls. It accepts an object containing the parameters that will be passed to APIs and used for calculations (e.g. lane details)
Example:
render: (inputValues: InputValues) => void;
interface InputValues {
truck: TransportType;
origin: Address;
destination: Address;
extraStops?: Address[];
pickupDate?: Date; // defaults to 8 AM of the next day if not provided
deliveryDate?: Date;
weight?: number;
commodity?: string;
customer?: string;
currency?: Currency; // defaults to USD if not provided
};
type TransportType = "VAN" | "REEFER" | "FLATBED";
type Address = ZipAddress | CityStateAddress | FullAddress;
interface ZipAddress {
zip: string;
}
interface CityStateAddress {
city: string;
state: string;
}
interface FullAddress {
zip: string;
city: string;
state: string;
}
type Currency = "USD" | "CAD";
Usage Examples
This list of examples is not exhaustive and the approaches used in them can be combined in any way that is most convenient for your use case.
One general advice is to not call build() more than once during the app lifetime. This should not ever be needed.
Code Examples
The Default
//somewhere in a singleton - does not need to happen more than once per page life
export const gsRates = window.Greenscreens.Rates.build({
baseApiPath: "gs api path"
});
//somewhere after user login
gsRates.setUser({
email: getEmail()
});
//somewhere after token refresh / acquisition
gsRates.setAccessTokenProvider(() => `Bearer ${getToken()}`);
//somewhere after the container element is in the DOM tree
gsRates.setContainer(react ref, dom selector, etc.);
//when input values are ready and all other required data is set
gsRates.render(inputValues);
All in the Constructor
export const gsRates = window.Greenscreens.Rates.build({
container: react ref, dom selector, etc.,
baseApiPath: "gs api path",
accessTokenProvider: () => `Bearer ${getToken()}`,
user: {
email: getEmail()
}
});
gsRates.render(inputValues);
Chained Setters
//it can also be simplified to just this:
export const gsRates = window.Greenscreens.Rates.build()
.setContainer(react ref, dom selector, etc.)
.setBaseApiPath("gs api path")
.setAccessTokenProvider(() => `Bearer ${getToken()}`)
.setUser({
email: getEmail()
})
gsRates.render(inputValues);
Combined
//somewhere in a singleton
export const gsRates = window.Greenscreens.Rates.build({
baseApiPath: "gs api path"
});
gsRates
.setUser({
email: getEmail()
})
.setAccessTokenProvider(() => `Bearer ${getToken()}`)
.setContainer(react ref, dom selector, etc.)
.render(inputValues);
The Demo Page
For a complete real-world example you can go to our demo page at https://bundle.greenscreens.ai/index.html
Inspect the page in the browser developer tools and check out the Sources tab:
render.bundle.js - is the main bundle of the demo app
auth.bundle.js - is the bundle responsible for acquiring authentication token
rates.bundle.js - is the portable bundle itself
Important notes
CORS
For the bundle to be able to call intelligence.triumph.io APIs from your origin, we will need to add your testing and production origins to our CORS policy. Contact us to provide the origins for the bundle.
Enabling CORS for the development machines is a bit trickier. You can read more about it here.
Authentication
In order for the intelligence.triumph.io API to accept the requests made by the bundle, you will need to acquire a valid access token and provide it to the bundle using the accessTokenProvider callback. There are multiple ways to do this, and they, as well as some other useful info, are described here.
Contacting us
The portable bundle integration is not an easy task; that's why we are always there to help you. In order for you to have the best experience of using the bundle, we highly recommend establishing a channel for quick communication with us. The most convenient way is to use Slack, but any other messenger or even emailing a developer directly can be a solution. Your Customer Success Manager can provide an email for the right developer, or you can contact Triumph Intelligence Support.