The "wrapper" around your application!
Insights Chrome provides:
- Standard header and navigation
- Base CSS/style
- A JavaScript library for interacting with Insights Chrome
You can include/use chrome in your development project by running the insights-proxy (https://github.com/RedHatInsights/insights-proxy) in front of your application and using the following HTML template.
<!doctype html>
<html>
<head>
<!-- your own HEAD tags -->
<esi:include src="/@@env/chrome/snippets/head.html" />
</head>
<body>
<esi:include src="/@@env/chrome/snippets/body.html"/>
</body>
</html>
Then, render your application to the "root" element. With React, for instance:
ReactDOM.render(
<Provider store={ init().getStore() }>
<Router basename={ `/${RELEASE}/platform/(project_name)` }>
<App />
</Router>
</Provider>,
document.getElementById('root')
);
Insights Chrome comes with a Javacript API that allows applications to control navigation, global filters, etc.
// initialize chrome
insights.chrome.init();
// identify yourself (the application). This tells Chrome which global navigation element should be active
insights.chrome.identifyApp('advisor');
The following events can be observed:
APP_NAVIGATION
- fired when the application navigation option is selected.event.navId
can be used to access the id of the navigation optionNAVIGATION_TOGGLE
- fired when user clicks on burger to hide navigation. No data are given.GLOBAL_FILTER_UPDATE
- fired when user selects anything in global filter. Object with all selected tags is returned. Tags are groupped together under namespace in which there is another object with keys as tag key and additional meta information.
-
To activate certain app within your app (your app is using some kind of router and you want to activate certain part of navigation programatically) you can call function
insights.chrome.appNavClick({id: 'some-id'})
for first level nav and for second level navs you have to callinsights.chrome.appNavClick({id: 'ocp-on-aws', parentId: 'some-parent', secondaryNav: true})
-
You can also use Chrome to update a page action and object ID for OUIA. You can use
insights.chrome.appAction('action')
to activate a certain action, andinsights.chrome.appObjectId('object-id')
to activate a certain ID. For instance, if you want to open the "edit name" dialog for an entity with id=5, you should callinsights.chrome.appAction('edit-name')
and theninsights.chrome.appObjectId(5)
. Once the user is done editing, you have to callinsights.chrome.appAction()
andinsights.chrome.appObjectId()
in order to indicate that the action is done. -
If you want to scope global filter to specific source you can do that by firing
insights.chrome.globalFilterScope('insights')
(this will populate global filter with tags for systems only from insights source).
List of available permissions methods:
isOrgAdmin
- test if logged in user is organization adminisActive
- test if logged in user is activeisInternal
- test if logged in user is internalisEntitled
- test if logged in user is entitled, entitlements to check for is passed as an argumentisProd
- test if current environment is production (prod-beta and prod-stable)isBeta
- test if current environment is beta (ci-beta, qa-beta and prod-beta)hasPermissions
- test if current user has rbac role permissions ['app:scope:permission']
On all insights application users expect to see global filter with predefined options and every app should integrate with it.
By default subscribing to GLOBAL_FILTER_UPDATE
will return you an object with namespace and key as object keys. This is for more complex behaviors, when you want to filter our certain items or to do something else with this complex object.
insights.chrome.on('GLOBAL_FILTER_UPDATE', ({ data }) => {
// do something with data object
});
If you simply want to filter systems based on these values we provide a helper function insights.chromemapGlobalFilter
which transforms object into one level array with tags in ${namespace}/${key}=${value}
shape. This function accepts one parameter, that is the filter object returned from GLOBAL_FILTER_UPDATE
event.
If you want to encode tag partials (namespace, key or value) you can pass true
as second parameter to this function to enable uriEncoding
.
insights.chrome.on('GLOBAL_FILTER_UPDATE', ({ data }) => {
const selectedTags = insights.chrome?.mapGlobalFilter?.(data);
// selectedTags is now array with selected tags and workspaces
});
If you wish to hide the global filter on any route simply call insights.chrome.hideGlobalFilter()
once you do that global filter will be hidden on all pages in your application.
If you want to hide it on certain screens call insights.chrome.hideGlobalFilter()
on them (preferably in componentDidMount
function) and on screens you want to show it call insights.chrome.hideGlobalFilter(false)
.
There is numerous of task for building this application. You can run individual tasks or run them in batch to build the entire app or to watch files.
To run each task you have to first install dependencies npm install
and then you are free to use any task as you wish.
If you want to watch file changes for each build just pass -- -w
to specific task (this is not applicable to
npm run build:js:watch
because it's somewhat specific).
- Building of styles
> npm run build:sass
- Building of javascripts
> npm run build:js
- Building of javascripts and watching files when they change
> npm run watch:js
- Building of HTML partials
> npm run build:pug
- Running tests
> npm run test
- Run build of whole application just once
> npm run build
- Watching file changes and trigger build every time something changes
> npm run start
First install all dependencies
> npm install
Run build command in watch mode
> npm run watch
Open new terminal, navigate to build directory and run proxy
SPANDX_CONFIG=../../insights-frontend-starter-app/profiles/local-frontend.js \
LOCAL_CHROME=true \
bash ../../insights-proxy/scripts/run.sh
Where SPANDX_CONFIG
can be any config for your application (here is an example for insights-frontend-starter-app), just make sure your application is running npm start
in said application.
After permorming these tasks you can access ci.foo.redhat.com:1337/insights/starter
and observe changes as you save them.
You can have custom spandx config with all frontend apps specified if you want to, the .js
file just have to export routes
object with at least 2 paths:
module.exports = {
routes: {
// you will access the UI on this URL /$BUNDLE/$APP
'/$BUNDLE/$APP': { host: `https://localhost:8002` },
// here are your files stored, if you used frontend starter app it will automatically build them
// in apps/$APP folder
'/apps/$APP': { host: `https://localhost:8002` },
}
}
There are some localStorage values for you to enable debuging information or enable some values that are in experimental state. If you want to enable them call const iqe = insights.chrome.enable.iqe()
for instance to enable such service. This function will return callback to disable such feature so calling iqe()
will remove such item from localStorage.
Available function:
iqe
- to enable some iqe functions for QE purposesinvTags
- to enable experimental tags in inventoryjwtDebug
- to enable debugging of JWTremediationsDebug
- to enable debug buttons in remediations appshortSession
- to enable short session in order to test automatic logoutsforcePendo
- to force Pendo initializtion
This project captures events with Sentry.io.
Out of the box, we capture all fatal errors. We also provide Sentry to developers so they can throw their own errors.
Sentry object spec:
Sentry.init({
dsn: API_KEY, // API key
environment: `Prod${appDetails.beta}`, // We only want to init on Prod and prod-beta
maxBreadcrumbs: 50, // Max lines from error to trace
attachStacktrace: true, // Attach the console.logs
debug: true // Print Debugging information
sampleRate: 1.0 // Percentage of events to send (this is a default and not needed)
});
Sentry.configureScope((scope) => {
// User information
scope.setUser({
id: account_number, // 540155
account_id: account_id // Personal number
});
// Other tags not natively collected by Sentry
scope.setTags({
// App info: cloud.redhat.com/[app.group]/[app.name]
app_group: app.group,
app_name: app.name,
// Location: frontend. Backends can also send events, so we want to be able to query on this
location: 'frontend',
// Browser width
browser_width: window.innerWidth + ' px'
});
});
You can access the ability to create support cases by calling window.insights.chrome.createCase()
.
By default, the fields that are sent are:
createdBy: 'foo-username',
environment: 'Production',
product: 'Red Hat Insights',
You have the ability to add a few custom fields with the following API:
window.insights.chrome.createCase({
caseFields: {
key: 'any case specific values'
},
// anything not inside of "caseFields" will be sent to sentry
foo: {
key: 'additional value'
}
})