Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This project was created using NodeJS 14.16. This application aims to demonstrat

## Dashboard view

![Dashboard view](https://github.com/boldbi/react-with-nodejs-sample/assets/129486688/9608f9e1-99f8-4375-9724-d15820cb690f)
![Dashboard view](/images/dashboard.png)

## Prerequisites

Expand All @@ -15,32 +15,28 @@ The samples require the following to run.

> **NOTE:** Node.js v14.16 to v18.18 are supported.

### Help link

* <https://help.boldbi.com/embedded-bi/faq/where-can-i-find-the-product-version/?utm_source=github&utm_medium=backlinks>

#### Supported browsers

* Google Chrome, Microsoft Edge, Mozilla Firefox, and Safari.
* Google Chrome, Microsoft Edge, and Mozilla Firefox.

## Configuration

* Please ensure that you have enabled embed authentication on the `embed settings` page. If it is not currently enabled, please refer to the following image or detailed [instructions](https://help.boldbi.com/site-administration/embed-settings/#get-embed-secret-code?utm_source=github&utm_medium=backlinks) to enable it.

![Embed Settings](https://github.com/boldbi/aspnet-core-sample/assets/91586758/b3a81978-9eb4-42b2-92bb-d1e2735ab007)
![Embed Settings](/images/enable-embedsecretkey.png)

* To download the `embedConfig.json` file, please follow this [link](https://help.boldbi.com/site-administration/embed-settings/#get-embed-configuration-file?utm_source=github&utm_medium=backlinks) for reference. Additionally, you can refer to the following image for visual guidance.

![Embed Settings Download](https://github.com/boldbi/aspnet-core-sample/assets/91586758/d27d4cfc-6a3e-4c34-975e-f5f22dea6172)
![EmbedConfig Properties](https://github.com/boldbi/aspnet-core-sample/assets/91586758/d6ce925a-0d4c-45d2-817e-24d6d59e0d63)
![Embed Settings Download](/images/download-embedsecretkey.png)
![EmbedConfig Properties](/images/embedconfig-file.png)

* Copy the downloaded `embedConfig.json` file and paste it into the designated [location](https://github.com/boldbi/react-with-nodejs-sample/tree/master) within the application. Please ensure that you have placed it in the application as shown in the following image.

![EmbedConfig image](https://github.com/boldbi/react-with-nodejs-sample/assets/129486688/6dc248bc-306c-497f-9aed-421abb2ca710)
![EmbedConfig image](/images/embedconfig-location.png)

## Developer IDE

* Visual studio code(<https://code.visualstudio.com/download>)
* [Visual Studio Code](<https://code.visualstudio.com/download>)

### Run a Sample Using Visual Studio Code

Expand All @@ -60,7 +56,7 @@ The samples require the following to run.

* After executing the command, the application will automatically launch in the default browser. You can access it at the specified port number (e.g., <https://localhost:3000>).

![Dashboard view](https://github.com/boldbi/react-with-nodejs-sample/assets/129486688/9608f9e1-99f8-4375-9724-d15820cb690f)
![dashboard view](/images/dashboard.png)

> **NOTE:** If the API host is already in use, modify the port number per your preference in embed.js and update that Dashboard.js file.

Expand Down
49 changes: 29 additions & 20 deletions client/src/Dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import React from 'react';
import '../index';
import {BoldBI} from '@boldbi/boldbi-embedded-sdk';


//NodeJs application will run on http://localhost:8080, which needs to be set as apiHost.
const apiHost="http://localhost:8080";

//Url of the authorizationserver action in the ValuesController of the NodeJs application.
const authorizationUrl="/authorizationserver/get";
//Url of the TokenGeneration action in embed.js
const tokenGenerationUrl = "/tokengeneration";

class Dashboard extends React.Component {
constructor(props) {
Expand All @@ -20,24 +19,34 @@ class Dashboard extends React.Component {
this.BoldBiObj = new BoldBI();
};

renderDashboard(data) {
this.dashboard= BoldBI.create({
serverUrl: data.ServerUrl+"/" + data.SiteIdentifier,
dashboardId: data.DashboardId,
embedContainerId: "dashboard",
embedType: data.EmbedType,
environment: data.Environment,
mode:BoldBI.Mode.View,
width:"100%",
height: window.innerHeight + 'px',
expirationTime:100000,
authorizationServer: {
url: apiHost + authorizationUrl
}
});
getEmbedToken() {
return fetch(apiHost + tokenGenerationUrl, { // Backend application URL
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({})
})
.then(response => {
if (!response.ok) throw new Error("Token fetch failed");
return response.text();
});
}

renderDashboard(data) {
this.getEmbedToken()
.then(accessToken => {
const dashboard = BoldBI.create({
serverUrl: data.ServerUrl + "/" + data.SiteIdentifier,
dashboardId: data.DashboardId,
embedContainerId: "dashboard",
embedToken: accessToken
});

this.dashboard.loadDashboard();
}
dashboard.loadDashboard();
})
.catch(err => {
console.error("Error rendering dashboard:", err);
});
};

render() {
return (
Expand Down
4 changes: 1 addition & 3 deletions client/src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from 'react';
import {createRoot } from 'react-dom/client';
import App from './App';

createRoot(document.getElementById('root')).render(<App />);

createRoot(document.getElementById('root')).render(<App />);
99 changes: 60 additions & 39 deletions embed.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
var fs = require("fs");
var http = require("http");
var https = require("https");
var url = require("url");
var express = require('express');
var cors = require('cors');
var app = express();
var crypto = require('crypto');
const path = require('path');
app.use(cors());
//Parse JSON bodies (as sent by API clients).
Expand All @@ -15,54 +13,77 @@ app.use(express.json());
const port = 8080;

let appconfig;
const configPath = path.join(__dirname, 'embedConfig.json');
let rawConfig;
try {
appconfig = JSON.parse(fs.readFileSync('embedConfig.json'));
} catch (error) {
console.error('Error: embedConfig.json file not found.');
process.exit(1); //Exit the program with a non-zero exit code to indicate an error.
rawConfig = fs.readFileSync(configPath, 'utf8');
} catch (err) {
console.error(`Error: cannot read embedConfig.json at ${configPath}:`, err.message);
process.exit(1);
}
try {
if (rawConfig && rawConfig.charCodeAt(0) === 0xFEFF) {
rawConfig = rawConfig.slice(1);
}
rawConfig = rawConfig.trim();
appconfig = JSON.parse(rawConfig);
} catch (err) {
console.error(`Error: invalid JSON in embedConfig.json at ${configPath}:`, err.message);
process.exit(1);
}

var embedSecret = appconfig.EmbedSecret;
app.post('/TokenGeneration', function (req, response) {
const embedDetails = {
email: appconfig.UserEmail,
serverurl: appconfig.ServerUrl,
siteidentifier: appconfig.SiteIdentifier,
embedsecret: appconfig.EmbedSecret,
dashboard: { // Dashboard ID property is mandatory only when using BoldBI version 14.1.11.
id: appconfig.DashboardId
}
}

var userEmail = appconfig.UserEmail;
const parsedUrl = new URL(embedDetails.serverurl);
const postData = JSON.stringify(embedDetails);
const client = parsedUrl.protocol === 'https:' ? https : http;
const options = {
hostname: parsedUrl.hostname,
port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80),
path: `${parsedUrl.pathname}/api/${embedDetails.siteidentifier}/embed/authorize`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData)
}
};

app.post('/authorizationserver/get', async function (req, response){
var embedQuerString = req.body.embedQuerString;
var dashboardServerApiUrl = req.body.dashboardServerApiUrl;

embedQuerString += "&embed_user_email=" + userEmail;
embedQuerString += "&embed_server_timestamp=" + Math.round((new Date()).getTime() / 1000);
var embedSignature = "&embed_signature=" + GetSignatureUrl(embedQuerString);
var embedDetailsUrl = "/embed/authorize?" + embedQuerString+embedSignature;

var serverProtocol = url.parse(dashboardServerApiUrl).protocol == 'https:' ? https : http;
serverProtocol.get(dashboardServerApiUrl+embedDetailsUrl, function(res){
var str = '';
res.on('data', function (chunk) {
str += chunk;
});
res.on('end', function () {
response.send(str);
});
const requ = client.request(options, res => {
let result = '';
res.setEncoding('utf8');
res.on('data', chunk => result += chunk);
res.on('end', () => {
const resultparse = JSON.parse(result); // Parse the response
response.send(resultparse?.Data?.access_token);
});
})
});

function GetSignatureUrl(queryString)
{
var keyBytes = Buffer.from(embedSecret);
var hmac = crypto.createHmac('sha256', keyBytes);
data = hmac.update(queryString);
gen_hmac= data.digest().toString('base64');
requ.on('error', (e) => {
console.error("Error fetching embed token:", e.message);
});

requ.write(postData);
requ.end();
})

return gen_hmac;
}
app.get('/GetData', (req, res) => {
const serverEmbedConfigData = path.join(__dirname, 'embedConfig.json');
const jsonData = fs.readFileSync(serverEmbedConfigData, 'utf8');
const parsedData = JSON.parse(jsonData);
const parsedData = appconfig;

const clientEmbedConfigData = {
DashboardId: parsedData.DashboardId, ServerUrl: parsedData.ServerUrl, SiteIdentifier: parsedData.SiteIdentifier, EmbedType: parsedData.EmbedType, Environment: parsedData.Environment
DashboardId: parsedData.DashboardId,
ServerUrl: parsedData.ServerUrl,
SiteIdentifier: parsedData.SiteIdentifier,
EmbedType: parsedData.EmbedType,
Environment: parsedData.Environment
};

res.send(clientEmbedConfigData);
Expand Down
Binary file added images/dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/download-embedsecretkey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/embedconfig-file.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/embedconfig-location.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/enable-embedsecretkey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "",
"main": "embed.js",
"dependencies": {
"@boldbi/boldbi-embedded-sdk": "^6.18.11",
"@boldbi/boldbi-embedded-sdk": "^15.1.65",
"cors": "^2.8.5",
"express": "^4.18.2"
},
Expand Down