Getting started
Requirement
Setup
CLI
npm i -D '@equinor/fusion-framework-cli'
Frameowork
npm i -D '@equinor/fusion-framework-react-app'
Typescript
{
"compilerOptions": {
"rootDir": "src",
"jsx": "react-jsx",
"module": "ES2022",
"target": "ES6",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"lib": [
"esnext",
"dom",
"dom.iterable"
],
}
}
EsLint
{
"extends": "@equinor/eslint-config-fusion-react",
}
npm i -D @equinor/eslint-config-fusion eslint prettier
Configuration
📚 Read more about configuration of modules
/** config.ts */
import type { AppModuleInitiator } from '@equinor/fusion-framework-react-app';
export const configure: AppModuleInitiator = async (configurator, { fusion, env }) => {
...
};
Application Config
When the application renders, the portal will load configuration from app service
import type { AppModuleInitiator } from '@equinor/fusion-framework-react-app';
import { enableContext } from '@equinor/fusion-framework-module-context';
export const configure: AppModuleInitiator = (configurator) => {
// enable context and set contextType
enableContext(configurator, async (builder) => {
builder.setContextType(['projectMaster']);
});
// configure framework loglevel
configurator.logger.level = 0;
};
export default configure;
import { defineAppConfig } from '@equinor/fusion-framework-cli';
export default defineAppConfig((_nev, { base }) =>
return {
environment: {
foo: 'foobar',
},
endpoints: {
api: {
url: 'https://foo.bars',
scopes: ['myscope/.default']
},
},
},
);
Environment variables
To access the environment variables in the application, use the hook useAppEnvironmentVariables
from @equinor/fusion-framework-react-app
.
import { useAppEnvironmentVariables } from '@equinor/fusion-framework-react-app';
type AppEnvironmentVariables = {
API_URL: string;
API_SCOPE: string;
}
const MyComponent = () => {
const env = useAppEnvironmentVariables<AppEnvironmentVariables>();
console.log(env); // { API_URL: 'https://foo.bar', API_SCOPE: 'c5161f15-9930-4cfc-b233-e9dfc5f8ad82/.default' }
}
Info
The useAppEnvironmentVariables
hook consumes asyncronous data from the app service.
In theory the value should always be available, since loaded during configuration.
There will be a future module which manages application state, where during the configuration the
desired environment variables can be picked.
Creating Application
Main
import { createElement } from 'react';
import { createRoot } from 'react-dom/client';
import { ComponentRenderArgs, makeComponent } from '@equinor/fusion-framework-react-app';
import configure from './config';
import App from './App';
/** create a render component */
const appComponent = createElement(App);
/** create React render root component */
const createApp = (args: ComponentRenderArgs) => makeComponent(appComponent, args, configure);
/** Render function */
export const renderApp = (el: HTMLElement, args: ComponentRenderArgs) => {
/** make render element */
const app = createApp(args);
/** create render root from provided element */
const root = createRoot(el);
/** render Application */
root.render(createElement(app));
/** Teardown */
return () => root.unmount();
};
export default renderApp;
Config
import type { AppModuleInitiator } from '@equinor/fusion-framework-react-app';
export const configure: AppModuleInitiator = (configurator, env) => {
/** print render environment arguments */
console.log('configuring application', env);
/** callback when configurations is created */
configurator.onConfigured((config) => {
console.log('application config created', config);
});
/** callback when the application modules has initialized */
configurator.onInitialized((instance) => {
console.log('application config initialized', instance);
});
};
export default configure;
Component
import { useAppSettings } from '@equinor/fusion-framework-react-app/settings';
import { useCallback } from 'react';
export const App = () => {
const { settings, updateSettings } = useAppSettings();
console.log('settings', settings);
const updateSettingsCallback = useCallback(() => {
updateSettings({ theme: 'dark', date: new Date().toISOString() });
}, []);
return (
<div
style={{
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
background: '#f0f0f0',
color: '#343434',
}}
>
<h1>🚀 Hello Fusion 😎</h1>
<button onClick={updateSettingsCallback}>SetSettings</button>
</div>
);
};
export default App;
Basic features
Use http client
upload this config to the application admin under configs
in the future the
config.endpoint
attribute in app admin will support scopes
read more about authentication
// config.ENV.json
{
"services": {
"myApi": {
"baseUri": "https://foo.bar",
"defaultScopes": "c5161f15-9930-4cfc-b233-e9dfc5f8ad82/.default"
}
}
}
configure application to create a http client based on dynamic config from app service
// config.ts
export const configure: AppModuleInitiator = (configurator, { env }) => {
const endpointApi = env.config?.getEndpoint('myApi');
configurator.configureHttpClient('myApi', {
baseUri: endpointApi?.url,
defaultScopes: endpointApi?.scopes,
});
// ... other config setting
create a util hook for accessing custom http client
// useMyApi.ts
import { useModule } from '@equinor/fusion-framework-react-app';
import { useHttpClient } from '@equinor/fusion-framework-react-app/http';
import type { IHttpClient } from '@equinor/fusion-framework-react-app/http';
export const useFooClient = (): IHttpClient => {
const httpProvider = useModule('http');
return useHttpClient('useMyApi');
}
Use service discovery
enable usage of service clients from service discovery
export const configure = (configurator) => {
/** enable usage of fusion portal api service */
await configurator.useFrameworkServiceClient('portal');
}
Enable routing
Enable routing in application
import { enableNavigation } from '@equinor/fusion-framework-module-navigation';
export const configure = (configurator, { env: { basename } }) => {
enableNavigation(configurator, basename);
}
Enable context
import { enableNavigation } from '@equinor/fusion-framework-module-context';
export const configure = (configurator) => enableContext(configurator);
import { enableNavigation } from '@equinor/fusion-framework-module-context';
export const configure = (configurator) => {
enableContext(configurator, (builder) => {
builder.setContextType(['project']);
builder.setContextFilter((items) => {
return items.filter(item => item.title.match(/a/));
});
});
}
Enable Ag Grid
Enable license key when deployed to portal
import { enableAgGrid } from '@equinor/fusion-framework-module-navigation';
export const configure = (configurator) => enableAgGrid(configurator);
Using Bookmarks
To enable bookmark for an application there are only one tinges needed. If the bookmark is enabled on in your portal. A function to capture the applications state is needed. The currentBookmark
will be updated when ever the bookmark changes, and all navigation will be handled by parent application / portal.
import { useCurrentBookmark } from '@equinor/fusion-framework-react-app/bookmark';
const currentBookmark = useCurrentBookmark(
useCallback(() => someApplicationState, [someApplicationState])
);