diff --git a/README.md b/README.md index 80b7abf..3daa52c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This project was created using React with Python. This application aims to demon ## Dashboard view - ![Dashboard view](images/dashboard-view.png) + ![Dashboard view](images/dashboard.png) ## Prerequisites @@ -20,79 +20,55 @@ The samples require the following to run. #### Supported browsers -* Google Chrome, Microsoft Edge, Mozilla Firefox, and Safari. +* Google Chrome, Microsoft Edge, and Mozilla Firefox. + +## Configuration + +* Please [get](https://github.com/boldbi/react-with-aspnet-core-sample/tree/master/React-with-ASP.NETCore) the React with ASP.NET Core sample from GitHub. + +* Please ensure 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](/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](/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-python/tree/master/python/django-sample-master) within the application. Please ensure you have placed it in the application, as shown in the following image. + + ![EmbedConfig image](/images/embedconfig-location.png) ## Developer IDE -* Visual studio code() - -### Run a Sample Using Visual Studio Code - - 1. The React application acts as a client, and the Python application acts as a server. In the `models.py` file of the Python application, you need to set the User Email and Embed Secret properties. - - - - - - - - - - - - - -
UserEmailUserEmail of the Admin in your Bold BI, which would be used to get the dashboard list.
User PasswordPassword of the Admin in Bold BI, which will be used to get the dashboards list.
- - 2. Once you have provided the details, run the application using the command "python manage.py runserver." The application will be running on port number 8000. - - 3. Then, once you run your Python application, you will see results similar to those of the React application. - - ![Python Backend API](images/backend-api.png) - - 4. To run the React application, we need to set the following properties in the DashboardListing.js file: - - ![DashboardListing](images/dashboard-listing.png) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SiteIdentifierFor the Bold BI Enterprise edition, it should be like `site/site1`. For Bold BI Cloud, it should be an empty string.
RootUrlDashboard Server URL (Eg: http://localhost:5000/bi, http://demo.boldbi.com/bi).
Authorization URLProvide the API end point(get_embed_details) of python application.
EnvironmentYour Bold BI application environment. (If Cloud, you should use `cloud,` if Enterprise, you should use `onpremise`).
API HostURL of python application(example: http://localhost:8000/).
UserEmailUserEmail of the Admin in your Bold BI, which would be used to get the dashboard list.
User PasswordPassword of the Admin in Bold BI, which will be used to get the dashboards list.
- - 5. Once you provide these details, run the command “npm install.” After all the packages are installed, run the command “npm start.” - - ![Dashboard view](images/dashboard-view.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. +* [Visual Studio Code]() + +## Run a Sample Using Visual Studio Code + +### Python sample via VS Code + + 1. Open the [Python Django](https://github.com/boldbi/react-with-python/tree/master/python/django-sample-master) folder in Visual Studio Code. + + 2. Open the terminal in Visual Studio Code and execute the command `python manage.py runserver` to run the application. It will display a URL in the command line interface, typically something like http://localhost:8000. Copy this URL and paste it into your default web browser, as shown in the image below. + + ![backend image](/images/backend-api.png) + +### React sample via VS Code + + 1. Open the [React](https://github.com/boldbi/react-with-python/tree/master/React) folder in Visual Studio Code. + + 2. To install all dependent packages, use the following command `npm install`. + + > **NOTE:** If you are using Node.js version higher than v16.17, you can update the `package.json` file by adding the following line as a `script` within the `start` command. Make ensure that you replace the existing line with this updated script. + + ``` bash + "start": "react-scripts --openssl-legacy-provider start" + ``` + + 3. To run the application, use the command `npm start` in the terminal. After executing the command, the application will automatically launch in the default browser. You can access it at the specified port number (). Please refer to the following image. + + ![dashboard view](/images/dashboard.png) + +> **NOTE:** We represent the dashboard embedding by default without the dashboard listing sidebar. To view the dashboard listing, provide userEmail and embedSecret values in the `DashboardListing.js` file and then navigate to the URL (such as http://localhost:3000/dashboardlisting). ## Important notes diff --git a/React/package.json b/React/package.json index 22552cf..a322dbc 100644 --- a/React/package.json +++ b/React/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { - "@boldbi/boldbi-embedded-sdk": "^6.12.12", + "@boldbi/boldbi-embedded-sdk": "^15.1.65", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.4.0", "@testing-library/user-event": "^7.2.1", @@ -11,8 +11,8 @@ "jquery": "^3.5.1", "react": "^16.12.0", "react-dom": "^16.12.0", - "react-scripts": "^3.4.0", - "type-casting-tool": "file:../../../npm 5.3.53/embedded-bi-samples" + "react-router-dom": "^6.30.3", + "react-scripts": "^3.4.0" }, "scripts": { "start": "react-scripts start", @@ -35,4 +35,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file diff --git a/React/src/App.js b/React/src/App.js index 56ab79b..5c39613 100644 --- a/React/src/App.js +++ b/React/src/App.js @@ -1,14 +1,18 @@ import React from 'react'; -// import logo from './logo.svg'; import './App.css'; import DashboardListing from './DashboardListing/DashboardListing'; +import Dashboard from './Dashboard/Dashboard'; +import { BrowserRouter, Routes, Route } from 'react-router-dom'; class App extends React.Component { render() { return ( -
- -
+ + + } /> + } /> + + ); } } diff --git a/React/src/Dashboard/Dashboard.js b/React/src/Dashboard/Dashboard.js new file mode 100644 index 0000000..bb88515 --- /dev/null +++ b/React/src/Dashboard/Dashboard.js @@ -0,0 +1,83 @@ +import React from 'react'; +import '../index'; +import { BoldBI } from '@boldbi/boldbi-embedded-sdk'; + +//ASP.NET Core application would be run on https://localhost:5001; http://localhost:5000, which needs to be set as `apiHost` +const apiHost = "http://localhost:8000"; + +//Url of the TokenGeneration action in views.py of the backend application +const tokenGenerationUrl = "/tokenGeneration"; + +//var BoldBiObj; +class Dashboard extends React.Component { + constructor(props) { + super(props); + this.state = { + toke: undefined, + items: [], + embedConfig: {}, + }; + this.BoldBiObj = new BoldBI(); + }; + + 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 + }); + + dashboard.loadDashboard(); + }) + .catch(err => { + console.error("Error rendering dashboard:", err); + }); + }; + + render() { + return ( +
+
+
+
+
+ ); + } + + async componentDidMount() { + try { + const response = await fetch(apiHost + '/getdetails'); + const data = await response.json(); + // Transform camelCase keys to PascalCase + const transformedEmbedConfigData = { + DashboardId: data.DashboardId, + EmbedType: data.EmbedType, + Environment: data.Environment, + ServerUrl: data.ServerUrl, + SiteIdentifier: data.SiteIdentifier + }; + this.setState({ embedConfig: transformedEmbedConfigData }, () => { + this.renderDashboard(this.state.embedConfig); + }); + } catch (error) { + console.log(error); + this.setState({ toke: "error", items: "error" }); + } + } +} +export default Dashboard; diff --git a/React/src/DashboardListing/DashboardListing.css b/React/src/DashboardListing/DashboardListing.css deleted file mode 100644 index 8b13789..0000000 --- a/React/src/DashboardListing/DashboardListing.css +++ /dev/null @@ -1 +0,0 @@ - diff --git a/React/src/DashboardListing/DashboardListing.js b/React/src/DashboardListing/DashboardListing.js index 414ff3e..8f07f51 100644 --- a/React/src/DashboardListing/DashboardListing.js +++ b/React/src/DashboardListing/DashboardListing.js @@ -1,122 +1,139 @@ import React from 'react'; -import './DashboardListing.css'; import '../index.css'; import '../index'; -import {BoldBI} from '@boldbi/boldbi-embedded-sdk'; +import { BoldBI } from '@boldbi/boldbi-embedded-sdk'; import Axios from 'axios'; -//For Bold BI Enterprise edition, it should be like `site/site1`. For Bold BI Cloud, it should be empty string. -const siteIdentifier = "site/site1"; - -//Your Bold BI application environment. (If Cloud, you should use `cloud`, if Enterprise, you should use `onpremise`) -const environment = "enterprise"; - //ASP.NET Core application would be run on http://localhost:61377/, which needs to be set as `apiHost` -const apiHost="http://localhost:8000" +const apiHost = "http://localhost:8000" -//Bold BI Server URL (ex: http://localhost:5000/bi, http://demo.boldbi.com/bi) -const rootUrl = "http://localhost:60951/bi/"; - -//Url of the GetDetails action in ValuesController of the ASP.NET Core application -const authorizationUrl="/get_embed_details"; +//Url of the TokenGeneration action in views.py of the backend application +const tokenGenerationUrl = "/tokenGeneration"; //Enter your BoldBI credentials here const userEmail= ""; const embedSecret= ""; class DashboardListing extends React.Component { - constructor(props){ - super(props); - this.state = {toke: undefined, items: []}; - this.BoldBiObj = new BoldBI(); - }; + constructor(props) { + super(props); + this.state = { toke: undefined, items: [] }; + this.BoldBiObj = new BoldBI(); + }; - renderDashboard(data) { - this.dashboard= BoldBI.create({ - serverUrl: rootUrl + siteIdentifier, - dashboardId: data.Id, - embedContainerId: "dashboard", - embedType: BoldBI.EmbedType.Component, - environment: environment==="enterprise"? BoldBI.Environment.Enterprise:BoldBI.Environment.Cloud, - mode:BoldBI.Mode.View, - width:"100%", - height: window.innerHeight + 'px', - expirationTime:100000, - authorizationServer: { - url:apiHost + authorizationUrl - } - }); - - console.log(this.dashboard); - this.dashboard.loadDashboard(); - + 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: this.state.embedConfig.ServerUrl + "/" + this.state.embedConfig.SiteIdentifier, + dashboardId: data.DashboardId ? data.DashboardId : data.Id, + embedContainerId: "dashboard", + embedToken: accessToken + }); + + dashboard.loadDashboard(); + }) + .catch(err => { + console.error("Error rendering dashboard:", err); + }); + }; + render() { return (
-
-
-
All Dashboard
-
-
- {this.state.items.map((el) => - - )} -
+
+
+
All Dashboards
-
-
+
+ {this.state.items.map((el) => + + )}
+
+
+
+
); } - componentDidMount() { - // var dashboard = undefined; + async componentDidMount() { + const response = await fetch(apiHost + '/getdetails'); + const data = await response.json(); + try { + const response = await fetch(apiHost + '/getdetails'); + const data = await response.json(); + // Transform camelCase keys to PascalCase + const transformedEmbedConfigData = { + DashboardId: data.DashboardId, + EmbedType: data.EmbedType, + Environment: data.Environment, + ServerUrl: data.ServerUrl, + SiteIdentifier: data.SiteIdentifier + }; + this.setState({ embedConfig: transformedEmbedConfigData }, () => { + }); + } catch (error) { + console.log(error); + this.setState({ toke: "error", items: "error" }); + } + var querystring = require('querystring'); var token = ""; - Axios.post(rootUrl+'api/'+ siteIdentifier +'/token', - querystring.stringify({ - username: userEmail, - embed_secret: embedSecret, - grant_type: "embed_secret" - }), { - headers: { + Axios.post(data.ServerUrl + '/api/' + data.SiteIdentifier + '/token', + querystring.stringify({ + username: userEmail, + embed_secret: embedSecret, + grant_type: "embed_secret" + }), { + headers: { "Content-Type": "application/x-www-form-urlencoded" } }).then(response => { - var result = response; - token = result.data.access_token; - this.setState({ toke: token}); - //Get Dashboards - Axios.get(rootUrl+'api/'+ siteIdentifier +'/v2.0/items?ItemType=2', - { - headers: { - "Access-Control-Allow-Origin": "*", - "Authorization":'bearer ' + this.state.toke - } - }).then(res => { + var result = response; + token = result.data.access_token; + this.setState({ toke: token }); + //Get Dashboards + Axios.get(data.ServerUrl + '/api/' + data.SiteIdentifier + '/v2.0/items?ItemType=2', + { + headers: { + "Access-Control-Allow-Origin": "*", + "Authorization": 'bearer ' + this.state.toke + } + }).then(res => { var arrayOfObjects = res.data; - this.setState({ items: arrayOfObjects}); + this.setState({ items: arrayOfObjects }); this.renderDashboard(arrayOfObjects[0]); - }, + }, + error => { + this.setState({ items: "error" }); + }); + }, error => { - this.setState({items: "error"}); + this.setState({ toke: "error" }); }); - }, - error => { - this.setState({toke: "error"}); - }); - } + } } -export default DashboardListing; +export default DashboardListing; \ No newline at end of file diff --git a/images/backend-api.png b/images/backend-api.png index c0977c0..75233e8 100644 Binary files a/images/backend-api.png and b/images/backend-api.png differ diff --git a/images/dashboard.png b/images/dashboard.png new file mode 100644 index 0000000..d0e811e Binary files /dev/null and b/images/dashboard.png differ diff --git a/images/download-embedsecretkey.png b/images/download-embedsecretkey.png new file mode 100644 index 0000000..abe0c1b Binary files /dev/null and b/images/download-embedsecretkey.png differ diff --git a/images/embedconfig-file.png b/images/embedconfig-file.png new file mode 100644 index 0000000..4ba11a5 Binary files /dev/null and b/images/embedconfig-file.png differ diff --git a/images/embedconfig-location.png b/images/embedconfig-location.png new file mode 100644 index 0000000..b59c465 Binary files /dev/null and b/images/embedconfig-location.png differ diff --git a/images/enable-embedsecretkey.png b/images/enable-embedsecretkey.png new file mode 100644 index 0000000..cbd4a7c Binary files /dev/null and b/images/enable-embedsecretkey.png differ diff --git a/python/django-sample-master/Embedsample/__pycache__/__init__.cpython-310.pyc b/python/django-sample-master/Embedsample/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 745853d..0000000 Binary files a/python/django-sample-master/Embedsample/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/Embedsample/__pycache__/__init__.cpython-311.pyc b/python/django-sample-master/Embedsample/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 494ec86..0000000 Binary files a/python/django-sample-master/Embedsample/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/Embedsample/__pycache__/settings.cpython-310.pyc b/python/django-sample-master/Embedsample/__pycache__/settings.cpython-310.pyc deleted file mode 100644 index ed0ff10..0000000 Binary files a/python/django-sample-master/Embedsample/__pycache__/settings.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/Embedsample/__pycache__/settings.cpython-311.pyc b/python/django-sample-master/Embedsample/__pycache__/settings.cpython-311.pyc deleted file mode 100644 index 4ef8b4c..0000000 Binary files a/python/django-sample-master/Embedsample/__pycache__/settings.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/Embedsample/__pycache__/urls.cpython-310.pyc b/python/django-sample-master/Embedsample/__pycache__/urls.cpython-310.pyc deleted file mode 100644 index d41207a..0000000 Binary files a/python/django-sample-master/Embedsample/__pycache__/urls.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/Embedsample/__pycache__/urls.cpython-311.pyc b/python/django-sample-master/Embedsample/__pycache__/urls.cpython-311.pyc deleted file mode 100644 index c295167..0000000 Binary files a/python/django-sample-master/Embedsample/__pycache__/urls.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/Embedsample/__pycache__/wsgi.cpython-310.pyc b/python/django-sample-master/Embedsample/__pycache__/wsgi.cpython-310.pyc deleted file mode 100644 index 55494f1..0000000 Binary files a/python/django-sample-master/Embedsample/__pycache__/wsgi.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/Embedsample/__pycache__/wsgi.cpython-311.pyc b/python/django-sample-master/Embedsample/__pycache__/wsgi.cpython-311.pyc deleted file mode 100644 index 47b58c1..0000000 Binary files a/python/django-sample-master/Embedsample/__pycache__/wsgi.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/README.md b/python/django-sample-master/README.md deleted file mode 100644 index 172de8c..0000000 --- a/python/django-sample-master/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# BoldBI Embedding Django Sample - -This Bold BI Django sample repository contains the Dashboard embedding sample. This sample demonstrates how to embed the dashboard which is available in your Bold BI server. - -This section guides you in using the Bold BI dashboard in your Django sample application. - - * [Requirements to run the demo](#requirements-to-run-the-demo) - * [Using the Django sample](#using-the-django-sample) - * [Online Demos](#online-demos) - * [Documentation](#documentation) - - ## Requirements to run the demo - -The samples require the following to run: - * [Python installer] (https://www.python.org/downloads/) - * [Visual Studio Code](https://code.visualstudio.com/download) - * [Python extension in VS code] (https://marketplace.visualstudio.com/items?itemName=ms-python.python) - - ## Using the Django sample - - * Open the Django embed sample in Visual studio code or any respective IDE. - - * Open the models.py file in the following location, /dashboardapp/models.py. - - * Please change the following properties in the `models.py` file as per your Bold BI Server. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RootUrlDashboard Server URL (Eg: http://localhost:5000/bi, http://demo.boldbi.com/bi).
SiteIdentifierFor the Bold BI Enterprise edition, it should be like `site/site1`. For Bold BI Cloud, it should be an empty string.
EnvironmentYour Bold BI application environment. (If Cloud, you should use `cloud,` if Enterprise, you should use `onpremise`).
dashboardIdId of the dashboard you want to embed.
UserEmailUserEmail of the Admin in your Bold BI, which would be used to get the dashboard list.
EmbedSecretGet your EmbedSecret key from the Embed tab by enabling the `Enable embed authentication` on the Administration page https://help.boldbi.com/embedded-bi/site-administration/embed-settings/.
- -* Now run the Django sample. - -Please refer to the [help documentation](https://help.boldbi.com/embedded-bi/javascript-based/samples/v3.3.40-or-later/other-platform-samples/#django-sample-to-embed-the-dashboard) to know how to run the sample. - -## Online Demos - -Look at the Bold BI Embedding sample to live demo [here](https://samples.boldbi.com/embed). - - -## Documentation - -A complete Bold BI Embedding documentation can be found on the [Bold BI Embedding Help](https://help.boldbi.com/embedded-bi/javascript-based/). \ No newline at end of file diff --git a/python/django-sample-master/dashboardapp/__pycache__/__init__.cpython-310.pyc b/python/django-sample-master/dashboardapp/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 67120e2..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/__init__.cpython-311.pyc b/python/django-sample-master/dashboardapp/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 33f3503..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/admin.cpython-310.pyc b/python/django-sample-master/dashboardapp/__pycache__/admin.cpython-310.pyc deleted file mode 100644 index c006822..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/admin.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/admin.cpython-311.pyc b/python/django-sample-master/dashboardapp/__pycache__/admin.cpython-311.pyc deleted file mode 100644 index ba2dc7e..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/admin.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/apps.cpython-310.pyc b/python/django-sample-master/dashboardapp/__pycache__/apps.cpython-310.pyc deleted file mode 100644 index 673b5b3..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/apps.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/apps.cpython-311.pyc b/python/django-sample-master/dashboardapp/__pycache__/apps.cpython-311.pyc deleted file mode 100644 index 399cfc6..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/apps.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/models.cpython-310.pyc b/python/django-sample-master/dashboardapp/__pycache__/models.cpython-310.pyc deleted file mode 100644 index c3c41af..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/models.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/models.cpython-311.pyc b/python/django-sample-master/dashboardapp/__pycache__/models.cpython-311.pyc deleted file mode 100644 index fd4aa9d..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/models.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/urls.cpython-310.pyc b/python/django-sample-master/dashboardapp/__pycache__/urls.cpython-310.pyc deleted file mode 100644 index 94e41bd..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/urls.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/urls.cpython-311.pyc b/python/django-sample-master/dashboardapp/__pycache__/urls.cpython-311.pyc deleted file mode 100644 index 98a9b27..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/urls.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/views.cpython-310.pyc b/python/django-sample-master/dashboardapp/__pycache__/views.cpython-310.pyc deleted file mode 100644 index 84726ff..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/views.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/__pycache__/views.cpython-311.pyc b/python/django-sample-master/dashboardapp/__pycache__/views.cpython-311.pyc deleted file mode 100644 index 282699a..0000000 Binary files a/python/django-sample-master/dashboardapp/__pycache__/views.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/global_app_settings.py b/python/django-sample-master/dashboardapp/global_app_settings.py new file mode 100644 index 0000000..974b9e9 --- /dev/null +++ b/python/django-sample-master/dashboardapp/global_app_settings.py @@ -0,0 +1,43 @@ +from dataclasses import dataclass +from pathlib import Path +import json + + +@dataclass +class EmbedDetails: + Environment: str = None + SiteIdentifier: str = None + ServerUrl: str = None + EmbedSecret: str = None + UserEmail: str = None + EmbedType: str = None + DashboardId: str = None + + +class GlobalAppSettings: + EmbedDetails: EmbedDetails = EmbedDetails() + + +def load_embed_details(): + """Load embedConfig.json and populate GlobalAppSettings.EmbedDetails.""" + config_path = Path(__file__).resolve().parents[1] / 'embedConfig.json' + with open(config_path, 'r', encoding='utf-8-sig') as f: + cfg = json.load(f) + embed = cfg.get('EmbedDetails', cfg) + + GlobalAppSettings.EmbedDetails = EmbedDetails( + Environment=embed.get('Environment') or embed.get('environment'), + SiteIdentifier=embed.get('SiteIdentifier') or embed.get('siteIdentifier') or embed.get('siteidentifier'), + ServerUrl=embed.get('ServerUrl') or embed.get('serverUrl') or embed.get('serverurl'), + EmbedSecret=embed.get('EmbedSecret') or embed.get('embedSecret') or embed.get('embedsecret'), + UserEmail=embed.get('UserEmail') or embed.get('userEmail') or embed.get('email'), + EmbedType=embed.get('EmbedType') or embed.get('embedType') or embed.get('embedtype'), + DashboardId=embed.get('DashboardId') or embed.get('dashboardId') or (embed.get('Dashboard') or {}).get('id') + ) + + +# Load on import if possible; fail silently so Django can still start +try: + load_embed_details() +except Exception: + pass diff --git a/python/django-sample-master/dashboardapp/migrations/0001_initial.py b/python/django-sample-master/dashboardapp/migrations/0001_initial.py deleted file mode 100644 index 56931bc..0000000 --- a/python/django-sample-master/dashboardapp/migrations/0001_initial.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.2.8 on 2021-10-11 03:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='ApiResponse', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ], - ), - ] diff --git a/python/django-sample-master/dashboardapp/migrations/__init__.py b/python/django-sample-master/dashboardapp/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/python/django-sample-master/dashboardapp/migrations/__pycache__/0001_initial.cpython-310.pyc b/python/django-sample-master/dashboardapp/migrations/__pycache__/0001_initial.cpython-310.pyc deleted file mode 100644 index e313841..0000000 Binary files a/python/django-sample-master/dashboardapp/migrations/__pycache__/0001_initial.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/migrations/__pycache__/0001_initial.cpython-311.pyc b/python/django-sample-master/dashboardapp/migrations/__pycache__/0001_initial.cpython-311.pyc deleted file mode 100644 index 1a68c03..0000000 Binary files a/python/django-sample-master/dashboardapp/migrations/__pycache__/0001_initial.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/migrations/__pycache__/__init__.cpython-310.pyc b/python/django-sample-master/dashboardapp/migrations/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index e1aa2f4..0000000 Binary files a/python/django-sample-master/dashboardapp/migrations/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/migrations/__pycache__/__init__.cpython-311.pyc b/python/django-sample-master/dashboardapp/migrations/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index c181fa0..0000000 Binary files a/python/django-sample-master/dashboardapp/migrations/__pycache__/__init__.cpython-311.pyc and /dev/null differ diff --git a/python/django-sample-master/dashboardapp/models.py b/python/django-sample-master/dashboardapp/models.py deleted file mode 100644 index 08b843f..0000000 --- a/python/django-sample-master/dashboardapp/models.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.db import models - -class EmbedProperties: - - - #Enter your BoldBI credentials here. - UserEmail = "" - - #Get the embedSecret key from Bold BI. - EmbedSecret = "" \ No newline at end of file diff --git a/python/django-sample-master/dashboardapp/urls.py b/python/django-sample-master/dashboardapp/urls.py index 8439d24..078a536 100644 --- a/python/django-sample-master/dashboardapp/urls.py +++ b/python/django-sample-master/dashboardapp/urls.py @@ -4,5 +4,6 @@ urlpatterns = [ path('', views.index, name='index'), - path('get_embed_details', views.get_embed_details, name = "get_embed_details"), + path('getdetails', views.getdetails, name='getdetails'), + path('tokenGeneration', views.tokenGeneration, name='tokenGeneration') ] \ No newline at end of file diff --git a/python/django-sample-master/dashboardapp/views.py b/python/django-sample-master/dashboardapp/views.py index 3bae717..ea46d42 100644 --- a/python/django-sample-master/dashboardapp/views.py +++ b/python/django-sample-master/dashboardapp/views.py @@ -1,42 +1,54 @@ import datetime from django.shortcuts import render -from django.http import HttpResponse +from django.http import HttpResponse, JsonResponse from rest_framework.decorators import api_view -from . import models import requests import json import hashlib import hmac import base64 +from pathlib import Path +from . import global_app_settings + def index(request): - return render(request,'index.html') +@api_view(['GET']) +def getdetails(request): + try: + d = global_app_settings.GlobalAppSettings.EmbedDetails + except Exception as e: + return JsonResponse({'error': 'Could not load embed details', 'details': str(e)}, status=500) + + return JsonResponse({ + 'DashboardId': d.DashboardId, + 'ServerUrl': d.ServerUrl, + 'EmbedType': d.EmbedType, + 'Environment': d.Environment, + 'SiteIdentifier': d.SiteIdentifier, + }) + @api_view(['POST']) -def get_embed_details(request): - body = json.loads(request.body.decode('utf-8')) - embedQuerString = body.get("embedQuerString") - dashboardServerApiUrl = body.get("dashboardServerApiUrl") - embedQuerString = embedQuerString +"&embed_user_email=" + models.EmbedProperties.UserEmail - timeStamp = (datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds() - embedQuerString += "&embed_server_timestamp=" + str(timeStamp) - embedDetailsUrl = "/embed/authorize?" + embedQuerString + "&embed_signature=" + get_signature_url(embedQuerString) - result_content=requests.get(dashboardServerApiUrl+embedDetailsUrl) - return HttpResponse(result_content) - - -def get_signature_url(message): - #EmbedSecret = "G6zjbRHBGDzzsSoLwmRs9o7rqZJ2njIe" - EmbedSecret = models.EmbedProperties.EmbedSecret - keyBytes = bytes(EmbedSecret.encode('utf-8')) - messageBytes = bytes(message.encode('utf-8')) - hashMessage = base64.b64encode(hmac.new(keyBytes,messageBytes,digestmod=hashlib.sha256).digest()) - #var hashMessage = hmacsha1.ComputeHash(messageBytes); - - return str(hashMessage, "utf-8") - - - - - \ No newline at end of file +def tokenGeneration(request): + embed_details = { + "email": global_app_settings.GlobalAppSettings.EmbedDetails.UserEmail, + "serverurl": global_app_settings.GlobalAppSettings.EmbedDetails.ServerUrl, + "siteidentifier": global_app_settings.GlobalAppSettings.EmbedDetails.SiteIdentifier, + "embedsecret": global_app_settings.GlobalAppSettings.EmbedDetails.EmbedSecret, + "dashboard": { + "id": global_app_settings.GlobalAppSettings.EmbedDetails.DashboardId + } + } + + request_url = f"{embed_details['serverurl']}/api/{embed_details['siteidentifier']}/embed/authorize" + headers = {"Content-Type": "application/json"} + + result = requests.post(request_url, headers=headers, data=json.dumps(embed_details), timeout=30) + result.raise_for_status() + + data = result.json() + try: + return HttpResponse(data["Data"]["access_token"]) + except (KeyError, TypeError): + return HttpResponse(f"Unexpected response format: {data}", status=502) \ No newline at end of file diff --git a/python/django-sample-master/template/index.html b/python/django-sample-master/template/index.html index 09067a1..f4f3b9b 100644 --- a/python/django-sample-master/template/index.html +++ b/python/django-sample-master/template/index.html @@ -2,29 +2,10 @@ -
- API is running