├── .gitattributes
├── .npmignore
├── .gitignore
├── .prettierrc
├── src
├── docs
│ ├── index.jsx
│ ├── styles
│ │ └── formLayoutStyles.js
│ ├── common
│ │ ├── InfoTab.jsx
│ │ ├── FormButtonGroup.jsx
│ │ ├── Footer.jsx
│ │ ├── FormButtonGroupBootstrap.jsx
│ │ ├── Header.jsx
│ │ └── SideNav.jsx
│ ├── index.html
│ ├── hooks
│ │ └── useLocalStorage.jsx
│ ├── utils.js
│ ├── index.css
│ ├── App.jsx
│ ├── Tile
│ │ ├── Form.jsx
│ │ └── index.jsx
│ ├── Dashboard
│ │ ├── index.jsx
│ │ └── Form.jsx
│ ├── CreateReport
│ │ ├── Form.jsx
│ │ └── index.jsx
│ ├── ReportVisual
│ │ ├── index.jsx
│ │ └── Form.jsx
│ ├── Report
│ │ ├── index.jsx
│ │ └── Form.jsx
│ ├── UseReportDemo
│ │ ├── Form.jsx
│ │ └── index.jsx
│ ├── MultiplePageDemo
│ │ ├── Form.jsx
│ │ └── index.jsx
│ └── UseBootstrapDemo
│ │ ├── Form.jsx
│ │ └── index.jsx
└── lib
│ ├── index.tsx
│ ├── Embed.tsx
│ ├── Tile.tsx
│ ├── Report.tsx
│ ├── Dashboard.tsx
│ ├── ReportVisual.tsx
│ ├── utils
│ ├── index.ts
│ ├── onEmbedHandlers.ts
│ └── config.ts
│ ├── types.ts
│ └── hooks
│ └── useReport.ts
├── .babelrc
├── docs
├── index.html
└── bundle.js.LICENSE.txt
├── CONTRIBUTING.md
├── tsconfig.json
├── .github
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── workflows
│ └── release.yml
└── dependabot.yml
├── .releaserc
├── LICENSE
├── webpack.config.js
├── package.json
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | text=auto
2 | text eol=lf
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | docs
2 | src
3 | .babelrc
4 | webpack.config.js
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /lib
3 | **/.DS_Store
4 | .idea/*
5 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 2,
4 | "semi": true,
5 | "singleQuote": true,
6 | "printWidth": 72
7 | }
8 |
--------------------------------------------------------------------------------
/src/docs/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from 'react-dom';
3 | import App from './App';
4 | import 'antd/dist/antd.css';
5 |
6 | render(, document.getElementById('app'));
7 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/env",
4 | "@babel/react"
5 | ],
6 | "plugins": [
7 | "@babel/plugin-proposal-class-properties",
8 | "@babel/plugin-transform-runtime"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/src/lib/index.tsx:
--------------------------------------------------------------------------------
1 | import Dashboard from './Dashboard';
2 | import Report from './Report';
3 | import Tile from './Tile';
4 | import { useReport, useBootstrap } from './hooks/useReport';
5 | import ReportVisual from './ReportVisual';
6 |
7 | export { Dashboard, Report, Tile, useReport, ReportVisual, useBootstrap };
8 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
Power Bi Embed Demo
--------------------------------------------------------------------------------
/src/docs/styles/formLayoutStyles.js:
--------------------------------------------------------------------------------
1 | const layout = {
2 | labelCol: {
3 | span: 3,
4 | },
5 | wrapperCol: {
6 | span: 18,
7 | },
8 | };
9 |
10 | const tailLayout = {
11 | wrapperCol: {
12 | offset: 8,
13 | span: 20,
14 | },
15 | };
16 |
17 | const buttonStyle = {
18 | margin: '0 8px',
19 | };
20 |
21 | export { layout, tailLayout, buttonStyle };
22 |
--------------------------------------------------------------------------------
/src/docs/common/InfoTab.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Typography } from 'antd';
3 |
4 | const { Title } = Typography;
5 |
6 | const Info = ({ title, titleType, children }) => {
7 | return (
8 |
9 |
10 | {title}
11 |
12 | {children}
13 |
14 | );
15 | };
16 |
17 | export default Info;
18 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Steps to contribute
2 |
3 | 1. Fork the repo
4 | 2. Create a new PR with description of your changes and why it's needed
5 | 3. Wait ~1 day to get your changes reviewed
6 | 4. Once the comments are fixed and PR is merged new version of package will be deployed
7 |
8 |
9 | # Development
10 |
11 | `npm run dev`
12 |
13 | `lib` folder for package changes
14 |
15 | `docs` folder for demo site and testing your changes in local
16 |
--------------------------------------------------------------------------------
/src/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 | Power Bi Embed Demo
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": [
4 | "es2017",
5 | "es7",
6 | "es6",
7 | "dom"
8 | ],
9 | "esModuleInterop": true,
10 | "target": "es5",
11 | "module": "commonjs",
12 | "declaration": true,
13 | "outDir": "lib",
14 | "strict": true,
15 | "jsx": "react",
16 | "removeComments": true
17 | },
18 | "include": [
19 | "./src"
20 | ],
21 | "exclude": [
22 | "node_modules",
23 | "lib",
24 | "**/__tests__/*"
25 | ]
26 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[FEATURE]"
5 | labels: ''
6 | assignees: akshay5995
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
--------------------------------------------------------------------------------
/.releaserc:
--------------------------------------------------------------------------------
1 | {
2 | "branches": [
3 | "main",
4 | "next"
5 | ],
6 | "plugins": [
7 | "@semantic-release/commit-analyzer",
8 | "@semantic-release/release-notes-generator",
9 | [
10 | "@semantic-release/npm",
11 | {
12 | "npmPublish": true,
13 | "tarballDir": "lib"
14 | }
15 | ],
16 | [
17 | "@semantic-release/git",
18 | {
19 | "assets": [
20 | "lib/**/*.{js,css}",
21 | "docs",
22 | "package.json"
23 | ],
24 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
25 | }
26 | ]
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/src/docs/common/FormButtonGroup.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Button } from 'antd';
3 | import { tailLayout, buttonStyle } from '../styles/formLayoutStyles';
4 |
5 | const FormButtonGroup = ({ isSubmit, onReset }) => (
6 |
7 |
15 |
23 |
24 | );
25 |
26 | export default FormButtonGroup;
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG]"
5 | labels: bug
6 | assignees: akshay5995
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Additional context**
27 | Add any other context about the problem here.
28 |
--------------------------------------------------------------------------------
/src/lib/Embed.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { generateRandomHexWithId } from './utils/index';
3 | import { _useReport } from './hooks/useReport';
4 | import { Embed } from './types';
5 |
6 | const Embed = ({ config, performOnEmbed, style }: Embed) => {
7 | const { id } = config;
8 | const randId = generateRandomHexWithId(id);
9 | const reportEl = React.useRef(null);
10 | const [_, setEmbed] = _useReport(performOnEmbed);
11 |
12 | React.useEffect(() => {
13 | if (reportEl) {
14 | setEmbed(reportEl, config);
15 | }
16 | }, []);
17 |
18 | return (
19 |
20 | );
21 | };
22 |
23 | export default Embed;
24 |
--------------------------------------------------------------------------------
/src/docs/common/Footer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout, Typography } from 'antd';
3 | import { HeartTwoTone, GithubFilled } from '@ant-design/icons';
4 |
5 | const { Footer: StyledFooter } = Layout;
6 | const { Text } = Typography;
7 |
8 | const Footer = () => (
9 |
10 |
11 |
12 |
13 |
14 | {'Made with '}
15 |
16 | {' by '}
17 | @akshay5995
18 |
19 |
20 | );
21 |
22 | export default Footer;
23 |
--------------------------------------------------------------------------------
/src/docs/hooks/useLocalStorage.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 |
3 | function useLocalStorage(key, initialValue) {
4 | const [storedValue, setStoredValue] = useState(() => {
5 | try {
6 | const item = window.localStorage.getItem(key);
7 | return item ? JSON.parse(item) : initialValue;
8 | } catch (error) {
9 | console.log(error);
10 | return initialValue;
11 | }
12 | });
13 |
14 | const setValue = (value) => {
15 | try {
16 | const valueToStore =
17 | value instanceof Function ? value(storedValue) : value;
18 | setStoredValue(valueToStore);
19 | window.localStorage.setItem(key, JSON.stringify(valueToStore));
20 | } catch (error) {
21 | console.log(error);
22 | }
23 | };
24 |
25 | return [storedValue, setValue];
26 | }
27 |
28 | export { useLocalStorage };
29 |
--------------------------------------------------------------------------------
/src/lib/Tile.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Embed from './Embed';
3 | import { createTileConfig } from './utils/config';
4 | import { tileHandler } from './utils/onEmbedHandlers';
5 | import { Config, TileProps } from './types';
6 |
7 | const Tile = (props: TileProps) => {
8 | const [currentConfig, setCurrentConfig] = React.useState(null);
9 |
10 | const performOnEmbed = React.useCallback(
11 | (tile) => {
12 | tileHandler(tile, props);
13 | },
14 | [props]
15 | );
16 |
17 | React.useEffect(() => {
18 | setCurrentConfig(createTileConfig(props));
19 | }, [props]);
20 |
21 |
22 | if (!currentConfig) {
23 | return (Error!
)
24 | }
25 |
26 | return (
27 |
32 | );
33 | };
34 |
35 | export default Tile;
36 |
--------------------------------------------------------------------------------
/src/lib/Report.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Embed from './Embed';
3 | import { createReportConfig } from './utils/config';
4 | import { reportHandler } from './utils/onEmbedHandlers';
5 | import { Config, ReportProps } from './types';
6 |
7 | const Report = (props: ReportProps) => {
8 | const [currentConfig, setCurrentConfig] = React.useState(null);
9 |
10 | const performOnEmbed = React.useCallback(
11 | (report, reportRef) => {
12 | reportHandler(report, reportRef, props);
13 | },
14 | [props]
15 | );
16 |
17 | React.useEffect(() => {
18 | setCurrentConfig(createReportConfig(props));
19 | }, [props]);
20 |
21 | if (!currentConfig) {
22 | return (Error!
)
23 | }
24 |
25 | return (
26 |
31 | );
32 | };
33 |
34 | export default Report;
35 |
--------------------------------------------------------------------------------
/src/lib/Dashboard.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Embed from './Embed';
3 | import { createDashboardConfig } from './utils/config';
4 | import { dashboardHandler } from './utils/onEmbedHandlers';
5 | import { Config, DashboardProps } from './types';
6 |
7 | const Dashboard = (props: DashboardProps) => {
8 | const [currentConfig, setCurrentConfig] = React.useState(null);
9 |
10 | const performOnEmbed = React.useCallback(
11 | (dashboard, dashboardRef) => {
12 | dashboardHandler(dashboard, dashboardRef, props);
13 | },
14 | [props]
15 | );
16 |
17 | React.useEffect(() => {
18 | setCurrentConfig(createDashboardConfig(props));
19 | }, [props]);
20 |
21 | if (!currentConfig) {
22 | return (Error!
)
23 | }
24 |
25 | return (
26 |
31 | );
32 | };
33 |
34 | export default Dashboard;
35 |
--------------------------------------------------------------------------------
/src/docs/common/FormButtonGroupBootstrap.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Button } from 'antd';
3 | import { tailLayout, buttonStyle } from '../styles/formLayoutStyles';
4 |
5 | const FormButtonGroupBootstrap = ({ isBootstrapped, isSubmit, onBootstrap, onReset, isLoading }) => (
6 |
7 |
15 |
24 |
32 |
33 | );
34 |
35 | export default FormButtonGroupBootstrap;
36 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v3
13 | - uses: actions/setup-node@v3
14 | with:
15 | node-version: '16.x'
16 | - name: Intall dependencies
17 | run: npm install --frozen-lockfile
18 | - name: Build lib
19 | run: npm run lib
20 | - name: Build docs
21 | run: npm run docs:prod
22 | - name: Deploy docs
23 | run: |
24 | git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
25 | npx gh-pages -d docs -u "github-actions-bot "
26 | env:
27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28 | - name: Publish library
29 | run: npm run publish:lib
30 | env:
31 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33 |
--------------------------------------------------------------------------------
/src/lib/ReportVisual.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Embed from './Embed';
3 | import { createReportVisualConfig } from './utils/config';
4 | import { reportVisualHandler } from './utils/onEmbedHandlers';
5 | import { Config, ReportVisualProps } from './types';
6 |
7 | const ReportVisual = (props: ReportVisualProps) => {
8 | const [
9 | currentConfig,
10 | setCurrentConfig,
11 | ] = React.useState(null);
12 |
13 | const performOnEmbed = React.useCallback(
14 | (report, reportRef) => {
15 | reportVisualHandler(report, reportRef, props);
16 | },
17 | [props]
18 | );
19 |
20 | React.useEffect(() => {
21 | setCurrentConfig(createReportVisualConfig(props));
22 | }, [props]);
23 |
24 | if (!currentConfig) {
25 | return Error!
;
26 | }
27 |
28 | return (
29 |
34 | );
35 | };
36 |
37 | export default ReportVisual;
38 |
--------------------------------------------------------------------------------
/src/lib/utils/index.ts:
--------------------------------------------------------------------------------
1 | // Removes null, undefined and empty string from given object
2 |
3 | const clean = (obj: any) => {
4 | const propNames = Object.getOwnPropertyNames(obj);
5 | propNames.forEach((element) => {
6 | if (
7 | obj[element] === null ||
8 | obj[element] === undefined ||
9 | obj[element] === ''
10 | ) {
11 | delete obj[element];
12 | }
13 | });
14 | return obj;
15 | };
16 |
17 | const validateAndInvokeCallback = (
18 | callback: Function | undefined,
19 | data: any
20 | ) => {
21 | if (!!callback) {
22 | callback(data);
23 | }
24 | };
25 |
26 | const isEmptyObject = (obj: Object) =>
27 | Object.keys(obj).length === 0 && obj.constructor === Object;
28 |
29 | const generateRandomHexWithId = (embedId: string) => {
30 | const randHex: string = Math.floor((1 + Math.random()) * 0x10000)
31 | .toString(16)
32 | .substring(1);
33 |
34 | return `${embedId}+${randHex}`;
35 | };
36 |
37 | export {
38 | clean,
39 | validateAndInvokeCallback,
40 | isEmptyObject,
41 | generateRandomHexWithId,
42 | };
43 |
--------------------------------------------------------------------------------
/src/docs/utils.js:
--------------------------------------------------------------------------------
1 | const defaultOptions = {
2 | common: {
3 | tokenType: ['Embed', 'Aad'],
4 | },
5 | report: {
6 | mode: 'view',
7 | embedModes: ['view', 'edit', 'create'],
8 | },
9 | dashboard: {
10 | mode: 'view',
11 | embedModes: ['view'],
12 | pageView: 'fitToWidth',
13 | pageViews: ['fitToWidth', 'oneColumn', 'actualSize'],
14 | },
15 | tile: {
16 | mode: 'view',
17 | embedModes: ['view'],
18 | },
19 | };
20 |
21 | const embedTypes = Object.keys(defaultOptions);
22 |
23 | const initializeState = (type) => ({
24 | embedType: type,
25 | tokenType: 'Embed',
26 | accessToken: '',
27 | embedUrl: '',
28 | embedId: '',
29 | pageName: '',
30 | dashboardId: '',
31 | permissions: 'All',
32 | tileId: '',
33 | filterPaneEnabled: 'filter-false',
34 | navContentPaneEnabled: 'nav-false',
35 | visualHeaderFlag: true,
36 | flag: false,
37 | reportMode: defaultOptions[type].mode,
38 | datasetId: '',
39 | pageView: defaultOptions[type].pageView,
40 | });
41 |
42 | export { embedTypes, defaultOptions, initializeState };
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Akshay Ram Vignesh A
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 | const TerserPlugin = require('terser-webpack-plugin');
4 |
5 | module.exports = {
6 | entry: path.join(__dirname, 'src/docs'),
7 | output: {
8 | path: path.join(__dirname, 'docs'),
9 | filename: 'bundle.js',
10 | },
11 | optimization: {
12 | minimize: true,
13 | minimizer: [
14 | new TerserPlugin({
15 | test: /\.js(\?.*)?$/i,
16 | exclude: /\/node_modules/,
17 | }),
18 | ],
19 | },
20 | module: {
21 | rules: [
22 | {
23 | test: /\.(js|jsx)$/,
24 | use: 'babel-loader',
25 | exclude: /node_modules/,
26 | },
27 | {
28 | test: /\.css$/,
29 | use: ['style-loader', 'css-loader'],
30 | },
31 | ],
32 | },
33 | plugins: [
34 | new HtmlWebpackPlugin({
35 | template: path.join(__dirname, 'src/docs/index.html'),
36 | }),
37 | ],
38 | resolve: {
39 | extensions: ['.js', '.jsx'],
40 | },
41 | devServer: {
42 | static: {
43 | directory: path.join(__dirname, 'docs'),
44 | },
45 | port: 8000,
46 | liveReload: true,
47 | },
48 | };
49 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "23:30"
8 | open-pull-requests-limit: 10
9 | ignore:
10 | - dependency-name: antd
11 | versions:
12 | - 4.11.2
13 | - 4.12.0
14 | - 4.12.1
15 | - 4.12.2
16 | - 4.12.3
17 | - 4.13.0
18 | - 4.13.1
19 | - 4.14.0
20 | - 4.14.1
21 | - 4.15.0
22 | - 4.15.1
23 | - 4.15.2
24 | - dependency-name: css-loader
25 | versions:
26 | - 5.0.1
27 | - 5.0.2
28 | - 5.1.0
29 | - 5.1.1
30 | - 5.1.2
31 | - 5.1.3
32 | - 5.2.0
33 | - 5.2.1
34 | - dependency-name: "@babel/core"
35 | versions:
36 | - 7.12.10
37 | - 7.12.13
38 | - 7.12.16
39 | - 7.12.17
40 | - 7.13.0
41 | - 7.13.1
42 | - 7.13.10
43 | - 7.13.13
44 | - 7.13.14
45 | - 7.13.15
46 | - 7.13.8
47 | - dependency-name: concurrently
48 | versions:
49 | - 5.3.0
50 | - 6.0.0
51 | - 6.0.1
52 | - dependency-name: y18n
53 | versions:
54 | - 4.0.1
55 | - dependency-name: html-webpack-plugin
56 | versions:
57 | - 4.5.1
58 | - dependency-name: elliptic
59 | versions:
60 | - 6.5.3
61 |
--------------------------------------------------------------------------------
/src/docs/common/Header.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Breadcrumb, Switch, Typography, Space } from 'antd';
3 | import { HomeOutlined } from '@ant-design/icons';
4 |
5 | const { Text } = Typography;
6 |
7 | const titleImportMap = {
8 | 'Create Report': 'Report',
9 | 'Multiple Pages': 'Report',
10 | 'Report Visual': 'ReportVisual',
11 | Report: 'Report',
12 | Dashboard: 'Dashboard',
13 | Tile: 'Tile',
14 | useReport: 'useReport',
15 | useBootstrap: 'useBootstrap'
16 | };
17 |
18 | const embedTypes = new Set(['Report', 'Dashboard', 'Tile', 'ReportVisual']);
19 |
20 | const Header = ({ title, setDarkMode, isDarkMode }) => {
21 | const onChange = (checked) => setDarkMode(checked);
22 |
23 | const generateImportStatement = () => {
24 | const importComponent = titleImportMap[title];
25 | return `import { ${importComponent} } from 'powerbi-report-component';`;
26 | };
27 |
28 | return (
29 |
30 |
31 |
32 |
33 | {embedTypes.has(title) && Embed Type}
34 |
35 |
36 |
37 | {title}
38 |
39 |
40 |
41 |
42 | Dark Mode
43 |
44 |
45 |
46 | );
47 | };
48 | export default Header;
49 |
--------------------------------------------------------------------------------
/src/docs/index.css:
--------------------------------------------------------------------------------
1 | html,
2 | body,
3 | #app,
4 | .main {
5 | height: 100%;
6 | }
7 |
8 | .logo {
9 | height: 32px;
10 | background: rgba(255, 255, 255, 0.2);
11 | margin: 16px;
12 | }
13 |
14 | .site-layout-header {
15 | color: #fff !important;
16 | margin: 18px !important;
17 | display: flex;
18 | justify-content: space-between;
19 | }
20 |
21 | .title-dark {
22 | color: #fff !important;
23 | padding: 14px 12px !important;
24 | }
25 |
26 | .title-light {
27 | color: #000 !important;
28 | padding: 14px 12px !important;
29 | }
30 |
31 | .ant-layout-content {
32 | margin: 12px;
33 | background: snow;
34 | }
35 |
36 | .ant-tabs {
37 | height: 100%;
38 | overflow-y: scroll !important;
39 | }
40 |
41 | .ant-tabs-content-animated {
42 | height: 90%;
43 | }
44 |
45 | .ant-tabs-nav-scroll {
46 | margin: 8px 12px;
47 | }
48 |
49 | .tab-content {
50 | padding: 8px 12px;
51 | }
52 |
53 | .ant-tabs-content {
54 | height: 100%;
55 | }
56 |
57 | .ant-tabs-tab {
58 | padding: 12px 8px !important;
59 | }
60 |
61 | .ant-layout-footer {
62 | display: flex;
63 | justify-content: space-between;
64 | font-weight: bold;
65 | padding: 12px 50px !important;
66 | flex-flow: row;
67 | flex-wrap: wrap;
68 | }
69 |
70 | .ant-menu-item {
71 | font-size: 16px !important;
72 | }
73 |
74 | .ant-form {
75 | height: 100% !important;
76 | padding: 24px !important;
77 | overflow-y: auto !important;
78 | }
79 |
80 | .ant-tabs-tabpane {
81 | margin-top: -22px !important;
82 | }
83 |
84 | .report > iframe {
85 | border: 0 !important;
86 | }
87 |
--------------------------------------------------------------------------------
/src/docs/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout } from 'antd';
3 | import SideNav from './common/SideNav';
4 | import Header from './common/Header';
5 | import Footer from './common/Footer';
6 | import CreateReport from './CreateReport';
7 | import Report from './Report';
8 | import Tile from './Tile';
9 | import Dashboard from './Dashboard';
10 | import ReportVisual from './ReportVisual';
11 | import MultiplePageDemo from './MultiplePageDemo';
12 | import './index.css';
13 | import { useLocalStorage } from './hooks/useLocalStorage';
14 | import UseReportDemo from './UseReportDemo';
15 | import UseBootstrapDemo from './UseBootstrapDemo';
16 |
17 | const App = () => {
18 | const [embedType, setEmbedType] = React.useState('Report');
19 | const [darkMode, setDarkMode] = useLocalStorage('darkMode', true);
20 |
21 | const onSelect = (embedType) => setEmbedType(embedType);
22 |
23 | const renderDemo = () => {
24 | switch (embedType) {
25 | case 'Report':
26 | return ;
27 | case 'Dashboard':
28 | return ;
29 | case 'Tile':
30 | return ;
31 | case 'ReportVisual':
32 | return ;
33 | case 'Create Report':
34 | return ;
35 | case 'Multiple Pages':
36 | return ;
37 | case 'useReport':
38 | return ;
39 | case 'useBootstrap':
40 | return ;
41 | default:
42 | return null;
43 | }
44 | };
45 |
46 | return (
47 |
48 |
53 |
54 |
59 | {renderDemo()}
60 |
61 |
62 |
63 | );
64 | };
65 |
66 | export default App;
67 |
--------------------------------------------------------------------------------
/src/docs/Tile/Form.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Input, Select } from 'antd';
3 | import { layout } from '../styles/formLayoutStyles';
4 | import FormButtonGroup from '../common/FormButtonGroup';
5 |
6 | const TileForm = ({ onSubmit, initialTileProps, onReset }) => {
7 | const [isSubmit, setIsSubmit] = React.useState(false);
8 |
9 | const onSubmitForm = ({ tileProps }) => {
10 | setIsSubmit(true);
11 | onSubmit({ tileProps });
12 | };
13 |
14 | const onResetForm = () => {
15 | setIsSubmit(false);
16 | onReset(false);
17 | };
18 |
19 | return (
20 |
33 |
37 |
38 |
43 |
44 |
45 |
50 |
51 |
52 |
59 |
60 |
61 |
66 |
67 |
68 |
69 |
70 | );
71 | };
72 |
73 | export default TileForm;
74 |
--------------------------------------------------------------------------------
/src/docs/Tile/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout, Tabs, Badge } from 'antd';
3 | import { FormOutlined, CheckCircleTwoTone } from '@ant-design/icons';
4 | import { Tile } from '../../../lib';
5 | import Form from './Form';
6 |
7 | const { Content } = Layout;
8 | const { TabPane } = Tabs;
9 |
10 | const initialTileProps = {
11 | tokenType: 'Embed',
12 | };
13 |
14 | const TileDemo = () => {
15 | const [tileProps, setTileProps] = React.useState(initialTileProps);
16 | const [isValidConfig, setIsValidConfig] = React.useState(false);
17 | const [activeTab, setActiveTab] = React.useState('form');
18 |
19 | const onTabClick = (key, event) => setActiveTab(key);
20 |
21 | const renderWithTileProps = React.useCallback(
22 | ({ tileProps }) => {
23 | setTileProps(tileProps);
24 | setIsValidConfig(true);
25 | },
26 | [tileProps]
27 | );
28 |
29 | const onReset = React.useCallback(() => {
30 | setIsValidConfig(false);
31 | }, [isValidConfig]);
32 |
33 | return (
34 |
35 |
36 |
39 |
40 | Form
41 |
42 | }
43 | key="form"
44 | >
45 |
50 |
51 |
55 |
56 |
57 | Tile
58 |
59 |
60 | }
61 | key="tile"
62 | >
63 | {isValidConfig && (
64 | {
71 | console.log('Data from tile', data);
72 | }}
73 | onLoad={(data) => {
74 | console.log('Tile loaded', data);
75 | }}
76 | />
77 | )}
78 |
79 |
80 |
81 | );
82 | };
83 |
84 | export default TileDemo;
85 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "powerbi-report-component",
3 | "version": "2.6.1",
4 | "description": "It's a minimalistic react component to embed a Microsoft PowerBI report, dashboard or tile into your react application.",
5 | "main": "lib/index.js",
6 | "types": "lib/index.d.ts",
7 | "scripts": {
8 | "dev": "concurrently \"npm run lib:watch\" \"npm run docs\"",
9 | "lib": "tsc",
10 | "lib:watch": "tsc -w",
11 | "docs": "webpack serve --mode development",
12 | "docs:prod": "webpack --mode production",
13 | "publish:demo": "gh-pages -d docs",
14 | "publish:lib": "semantic-release"
15 | },
16 | "keywords": [
17 | "powerbi",
18 | "react-powerbi",
19 | "react",
20 | "bi",
21 | "embed",
22 | "report",
23 | "dashboard",
24 | "tile",
25 | "report visual",
26 | "powerbi-reports"
27 | ],
28 | "license": "MIT",
29 | "peerDependencies": {
30 | "react": "^17.0.2",
31 | "react-dom": "^17.0.2"
32 | },
33 | "devDependencies": {
34 | "@ant-design/icons": "^4.7.0",
35 | "@babel/cli": "^7.13.16",
36 | "@babel/core": "^7.14.0",
37 | "@babel/plugin-proposal-class-properties": "^7.13.0",
38 | "@babel/plugin-transform-runtime": "^7.13.15",
39 | "@babel/preset-env": "^7.14.1",
40 | "@babel/preset-react": "^7.13.13",
41 | "@semantic-release/changelog": "^6.0.1",
42 | "@semantic-release/git": "^10.0.1",
43 | "@semantic-release/npm": "^9.0.1",
44 | "@types/react": "^17.0.5",
45 | "@types/react-dom": "^17.0.3",
46 | "@types/zen-observable": "^0.8.2",
47 | "antd": "^4.15.4",
48 | "babel-loader": "^8.2.2",
49 | "concurrently": "^6.1.0",
50 | "css-loader": "^5.2.4",
51 | "gh-pages": "^4.0.0",
52 | "html-webpack-plugin": "^5.3.1",
53 | "node-sass": "^7.0.1",
54 | "react": "^17.0.2",
55 | "react-dom": "^17.0.2",
56 | "semantic-release": "^19.0.3",
57 | "style-loader": "^2.0.0",
58 | "typescript": "^4.2.4",
59 | "webpack": "^5.73.0",
60 | "webpack-cli": "^4.10.0",
61 | "webpack-dev-server": "^4.9.3"
62 | },
63 | "author": {
64 | "name": "Akshay Ram Vignesh A",
65 | "email": "akshay5995@gmail.com"
66 | },
67 | "homepage": "http://akshay5995.github.io/powerbi-report-component",
68 | "repository": {
69 | "type": "git",
70 | "url": "https://github.com/akshay5995/powerbi-report-component"
71 | },
72 | "dependencies": {
73 | "powerbi-client": "^2.21.0"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/lib/types.ts:
--------------------------------------------------------------------------------
1 | export type ReportModes = 'View' | 'Edit' | 'Create';
2 |
3 | export type EmbedType = 'report' | 'dashboard' | 'tile';
4 |
5 | export type TokenType = 'Aad' | 'Embed';
6 |
7 | export type Permissions =
8 | | 'Read'
9 | | 'ReadWrite'
10 | | 'Copy'
11 | | 'Create'
12 | | 'All';
13 |
14 | export type PageView = 'fitToWidth' | 'oneColumn' | 'actualSize';
15 |
16 | export interface IError {
17 | message: string;
18 | detailedMessage?: string;
19 | errorCode?: string;
20 | }
21 |
22 | export interface TileProps {
23 | tokenType: TokenType;
24 | accessToken: string;
25 | embedUrl: string;
26 | embedId: string;
27 | dashboardId: string;
28 | style?: any;
29 | onLoad?: Function;
30 | onClick?: Function;
31 | }
32 |
33 | export interface DashboardProps {
34 | tokenType: TokenType;
35 | accessToken: string;
36 | embedUrl: string;
37 | embedId: string;
38 | pageView: PageView;
39 | style?: any;
40 | onLoad?: Function;
41 | onTileClicked?: Function;
42 | }
43 |
44 | export interface ReportProps {
45 | tokenType: TokenType;
46 | accessToken: string;
47 | embedUrl: string;
48 | embedId: string;
49 | groupId?: string;
50 | permissions: Permissions;
51 | reportMode: ReportModes;
52 | pageName?: string;
53 | extraSettings?: any;
54 | style?: any;
55 | datasetId?: string;
56 | onLoad?: Function;
57 | onRender?: Function;
58 | onError?: Function;
59 | onButtonClicked?: Function;
60 | onSelectData?: Function;
61 | onPageChange?: Function;
62 | onCommandTriggered?: Function;
63 | onSave?: Function;
64 | }
65 |
66 | export interface ReportVisualProps {
67 | tokenType: TokenType;
68 | accessToken: string;
69 | embedUrl: string;
70 | embedId: string;
71 | pageName: string;
72 | visualName: string;
73 | style?: any;
74 | onLoad?: Function;
75 | onRender?: Function;
76 | onSelectData?: Function;
77 | }
78 |
79 | export interface Config {
80 | type: EmbedType;
81 | tokenType: TokenType;
82 | accessToken: string;
83 | embedUrl: string;
84 | pageName: string;
85 | groupId: string;
86 | visualName: string;
87 | extraSettings: any;
88 | permissions: Permissions;
89 | id: string;
90 | reportMode: ReportModes;
91 | datasetId: string;
92 | pageView: PageView;
93 | dashboardId: string;
94 | }
95 |
96 | export interface Embed {
97 | config: Config;
98 | performOnEmbed: (report: any, reportRef?: any) => void;
99 | style: any;
100 | }
101 |
--------------------------------------------------------------------------------
/src/docs/Dashboard/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout, Tabs, Badge } from 'antd';
3 | import { FormOutlined, CheckCircleTwoTone } from '@ant-design/icons';
4 | import { Dashboard } from '../../../lib';
5 | import Form from './Form';
6 |
7 | const { Content } = Layout;
8 | const { TabPane } = Tabs;
9 |
10 | const initialDashboardProps = {
11 | tokenType: 'Embed',
12 | };
13 |
14 | const DashboardDemo = () => {
15 | const [dashboardProps, setDashboardProps] = React.useState(
16 | initialDashboardProps
17 | );
18 | const [isValidConfig, setIsValidConfig] = React.useState(false);
19 | const [activeTab, setActiveTab] = React.useState('form');
20 |
21 | const onTabClick = (key, event) => setActiveTab(key);
22 |
23 | const renderWithDashboardProps = React.useCallback(
24 | ({ dashboardProps }) => {
25 | setDashboardProps(dashboardProps);
26 | setIsValidConfig(true);
27 | },
28 | [dashboardProps]
29 | );
30 |
31 | const onReset = React.useCallback(() => {
32 | setIsValidConfig(false);
33 | }, [isValidConfig]);
34 |
35 | return (
36 |
37 |
38 |
41 |
42 | Form
43 |
44 | }
45 | key="form"
46 | >
47 |
52 |
53 |
57 |
58 |
59 | Dashboard
60 |
61 |
62 | }
63 | key="dashboard"
64 | >
65 | {isValidConfig && (
66 | {
73 | console.log('Data from tile', data);
74 | }}
75 | onLoad={(data) => {
76 | console.log('Dashboard loaded', data);
77 | }}
78 | />
79 | )}
80 |
81 |
82 |
83 | );
84 | };
85 |
86 | export default DashboardDemo;
87 |
--------------------------------------------------------------------------------
/src/docs/Dashboard/Form.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Input, Select } from 'antd';
3 | import { layout } from '../styles/formLayoutStyles';
4 | import FormButtonGroup from '../common/FormButtonGroup';
5 |
6 | const DashboardForm = ({ onSubmit, initialDashboardProps, onReset }) => {
7 | const [isSubmit, setIsSubmit] = React.useState(false);
8 |
9 | const onSubmitForm = ({ dashboardProps }) => {
10 | setIsSubmit(true);
11 | onSubmit({ dashboardProps });
12 | };
13 |
14 | const onResetForm = () => {
15 | setIsSubmit(false);
16 | onReset(false);
17 | };
18 |
19 | return (
20 |
33 |
37 |
38 |
43 |
44 |
45 |
50 |
51 |
52 |
57 |
58 |
59 |
63 |
68 |
69 |
70 |
71 | );
72 | };
73 |
74 | export default DashboardForm;
75 |
--------------------------------------------------------------------------------
/src/docs/CreateReport/Form.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Input, Select } from 'antd';
3 | import { layout } from '../styles/formLayoutStyles';
4 | import FormButtonGroup from '../common/FormButtonGroup';
5 |
6 | const ReportForm = ({ onSubmit, initialReportProps, onReset }) => {
7 | const [isSubmit, setIsSubmit] = React.useState(false);
8 |
9 | const onSubmitForm = ({ reportProps }) => {
10 | setIsSubmit(true);
11 | onSubmit({ reportProps });
12 | };
13 |
14 | const onResetForm = () => {
15 | setIsSubmit(false);
16 | onReset(false);
17 | };
18 |
19 | return (
20 |
33 |
37 |
38 |
43 |
44 |
45 |
50 |
51 |
52 |
53 |
56 |
57 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | );
75 | };
76 |
77 | export default ReportForm;
78 |
--------------------------------------------------------------------------------
/src/docs/ReportVisual/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout, Tabs, Badge } from 'antd';
3 | import { FormOutlined, CheckCircleTwoTone } from '@ant-design/icons';
4 | import { ReportVisual } from '../../../lib';
5 | import Form from './Form';
6 |
7 | const { Content } = Layout;
8 | const { TabPane } = Tabs;
9 |
10 | const initialReportProps = {
11 | tokenType: 'Embed',
12 | };
13 |
14 | const ReportVisualDemo = () => {
15 | const [reportVisualProps, setReportVisualProps] = React.useState(
16 | initialReportProps
17 | );
18 | const [isValidConfig, setIsValidConfig] = React.useState(false);
19 | const [activeTab, setActiveTab] = React.useState('form');
20 |
21 | const onTabClick = (key, event) => setActiveTab(key);
22 |
23 | const renderWithReportProps = React.useCallback(
24 | ({ reportVisualProps }) => {
25 | setReportVisualProps(reportVisualProps);
26 | setIsValidConfig(true);
27 | },
28 | [reportVisualProps]
29 | );
30 |
31 | const onReset = React.useCallback(() => {
32 | setIsValidConfig(false);
33 | }, [isValidConfig]);
34 |
35 | return (
36 |
37 |
38 |
41 |
42 | Form
43 |
44 | }
45 | key="form"
46 | >
47 |
52 |
53 |
57 |
58 |
59 | ReportVisual
60 |
61 |
62 | }
63 | key="report"
64 | >
65 | {isValidConfig && (
66 | {
73 | console.log('Report Loaded!');
74 | }}
75 | onRender={(report) => {
76 | console.log('Report Rendered');
77 | }}
78 | onSelectData={(data) => {
79 | console.log('Data selected', data);
80 | }}
81 | />
82 | )}
83 |
84 |
85 |
86 | );
87 | };
88 |
89 | export default ReportVisualDemo;
90 |
--------------------------------------------------------------------------------
/src/docs/CreateReport/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout, Tabs, Badge } from 'antd';
3 | import { FormOutlined, CheckCircleTwoTone } from '@ant-design/icons';
4 | import { Report } from '../../../lib';
5 | import Form from './Form';
6 |
7 | const { Content } = Layout;
8 | const { TabPane } = Tabs;
9 |
10 | const initialReportProps = {
11 | tokenType: 'Embed',
12 | reportMode: 'Create',
13 | };
14 |
15 | const ReportDemo = () => {
16 | const [reportProps, setReportProps] = React.useState(
17 | initialReportProps
18 | );
19 | const [isValidConfig, setIsValidConfig] = React.useState(false);
20 | const [activeTab, setActiveTab] = React.useState('form');
21 |
22 | const onTabClick = (key, event) => setActiveTab(key);
23 |
24 | const renderWithReportProps = React.useCallback(
25 | ({ reportProps }) => {
26 | setReportProps(reportProps);
27 | setIsValidConfig(true);
28 | },
29 | [reportProps]
30 | );
31 |
32 | const onReset = React.useCallback(() => {
33 | setIsValidConfig(false);
34 | }, [isValidConfig]);
35 |
36 | return (
37 |
38 |
39 |
42 |
43 | Form
44 |
45 | }
46 | key="form"
47 | >
48 |
53 |
54 |
58 |
59 |
60 | Create Report
61 |
62 |
63 | }
64 | key="report"
65 | >
66 | {isValidConfig && (
67 | {
74 | console.log('Report Loaded!');
75 | }}
76 | onRender={(report) => {
77 | console.log('Report Rendered!');
78 | }}
79 | onSave={(data) => {
80 | console.log('Report saved. Event data ', data);
81 | }}
82 | onError={(data) => {
83 | console.log('Error', data);
84 | }}
85 | />
86 | )}
87 |
88 |
89 |
90 | );
91 | };
92 |
93 | export default ReportDemo;
94 |
--------------------------------------------------------------------------------
/src/docs/ReportVisual/Form.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Input, Select } from 'antd';
3 | import { layout } from '../styles/formLayoutStyles';
4 | import FormButtonGroup from '../common/FormButtonGroup';
5 |
6 | const ReportForm = ({ onSubmit, initialReportProps, onReset }) => {
7 | const [isSubmit, setIsSubmit] = React.useState(false);
8 |
9 | const onSubmitForm = ({ reportVisualProps }) => {
10 | setIsSubmit(true);
11 | onSubmit({ reportVisualProps });
12 | };
13 |
14 | const onResetForm = () => {
15 | setIsSubmit(false);
16 | onReset(false);
17 | };
18 |
19 | return (
20 |
33 |
37 |
38 |
43 |
44 |
45 |
50 |
51 |
52 |
62 |
63 |
64 |
74 |
75 |
76 |
86 |
87 |
88 |
89 |
90 | );
91 | };
92 |
93 | export default ReportForm;
94 |
--------------------------------------------------------------------------------
/src/lib/utils/onEmbedHandlers.ts:
--------------------------------------------------------------------------------
1 | import { validateAndInvokeCallback } from '../utils';
2 | import {
3 | ReportProps,
4 | DashboardProps,
5 | TileProps,
6 | ReportVisualProps,
7 | } from '../types';
8 |
9 | const reportHandler = (
10 | report: any,
11 | reportRef: any,
12 | props: ReportProps
13 | ): void => {
14 | const { reportMode } = props;
15 | const isCreateMode = reportMode === 'Create';
16 | const reportInstance = window.powerbi.get(reportRef);
17 |
18 | report.on('loaded', () => {
19 | validateAndInvokeCallback(props.onLoad, reportInstance);
20 | });
21 |
22 | report.on('error', (event: any) =>
23 | validateAndInvokeCallback(props.onError, event.detail)
24 | );
25 |
26 | report.on('saved', (event: any) =>
27 | validateAndInvokeCallback(props.onSave, event.detail)
28 | );
29 |
30 | if (!isCreateMode) {
31 | report.on('rendered', () =>
32 | validateAndInvokeCallback(props.onRender, reportInstance)
33 | );
34 |
35 | report.on('dataSelected', (event: any) =>
36 | validateAndInvokeCallback(props.onSelectData, event.detail)
37 | );
38 |
39 | report.on('pageChanged', (event: any) =>
40 | validateAndInvokeCallback(props.onPageChange, event.detail)
41 | );
42 |
43 | report.on('buttonClicked', (event: any) =>
44 | validateAndInvokeCallback(props.onButtonClicked, event.detail)
45 | );
46 |
47 | report.on('commandTriggered', (event: any) =>
48 | validateAndInvokeCallback(props.onCommandTriggered, event.detail)
49 | );
50 | }
51 | };
52 |
53 | const reportVisualHandler = (
54 | reportVisual: any,
55 | reportRef: any,
56 | props: ReportVisualProps
57 | ): void => {
58 | const reportInstance = window.powerbi.get(reportRef);
59 |
60 | reportVisual.on('loaded', () => {
61 | validateAndInvokeCallback(props.onLoad, reportInstance);
62 | });
63 |
64 | reportVisual.on('rendered', () =>
65 | validateAndInvokeCallback(props.onRender, reportInstance)
66 | );
67 |
68 | reportVisual.on('dataSelected', (event: any) =>
69 | validateAndInvokeCallback(props.onSelectData, event.detail)
70 | );
71 | };
72 |
73 | const dashboardHandler = (
74 | dashboard: any,
75 | dashboardRef: any,
76 | props: DashboardProps
77 | ): void => {
78 | if (props.onLoad)
79 | props.onLoad(dashboard, window.powerbi.get(dashboardRef));
80 |
81 | dashboard.on('tileClicked', (event: any) =>
82 | validateAndInvokeCallback(props.onTileClicked, event.detail)
83 | );
84 | };
85 |
86 | const tileHandler = (tile: any, props: TileProps): void => {
87 | tile.on('tileLoaded', (event: any) =>
88 | validateAndInvokeCallback(props.onLoad, event.detail)
89 | );
90 |
91 | tile.on('tileClicked', (event: any) =>
92 | validateAndInvokeCallback(props.onClick, event.detail)
93 | );
94 | };
95 |
96 | export {
97 | reportHandler,
98 | dashboardHandler,
99 | tileHandler,
100 | reportVisualHandler,
101 | };
102 |
--------------------------------------------------------------------------------
/src/docs/Report/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout, Tabs, Badge } from 'antd';
3 | import { FormOutlined, CheckCircleTwoTone } from '@ant-design/icons';
4 | import { Report } from '../../../lib';
5 | import Form from './Form';
6 |
7 | const { Content } = Layout;
8 | const { TabPane } = Tabs;
9 |
10 | const initialReportProps = {
11 | tokenType: 'Embed',
12 | };
13 |
14 | const ReportDemo = () => {
15 | const [reportProps, setReportProps] = React.useState(
16 | initialReportProps
17 | );
18 | const [isValidConfig, setIsValidConfig] = React.useState(false);
19 | const [activeTab, setActiveTab] = React.useState('form');
20 |
21 | const onTabClick = (key, event) => setActiveTab(key);
22 |
23 | const renderWithReportProps = React.useCallback(
24 | ({ reportProps }) => {
25 | setReportProps(reportProps);
26 | setIsValidConfig(true);
27 | },
28 | [reportProps]
29 | );
30 |
31 | const onReset = React.useCallback(() => {
32 | setIsValidConfig(false);
33 | }, [isValidConfig]);
34 |
35 | const extraSettings = {
36 | filterPaneEnabled: false,
37 | navContentPaneEnabled: false,
38 | };
39 |
40 | return (
41 |
42 |
43 |
46 |
47 | Form
48 |
49 | }
50 | key="form"
51 | >
52 |
57 |
58 |
62 |
63 |
64 | Report
65 |
66 |
67 | }
68 | key="report"
69 | >
70 | {isValidConfig && (
71 | {
79 | console.log('Report Loaded!');
80 | }}
81 | onRender={(report) => {
82 | console.log('Report Rendered');
83 | }}
84 | onSelectData={(data) => {
85 | console.log('Data selected', data);
86 | }}
87 | onError={(data) => {
88 | console.log('Error', data);
89 | }}
90 | onPageChange={(data) => {
91 | console.log('Page changed', data);
92 | }}
93 | />
94 | )}
95 |
96 |
97 |
98 | );
99 | };
100 |
101 | export default ReportDemo;
102 |
--------------------------------------------------------------------------------
/src/docs/common/SideNav.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Layout, Menu, Typography } from 'antd';
3 | import {
4 | BuildTwoTone,
5 | PieChartTwoTone,
6 | FundTwoTone,
7 | EditTwoTone,
8 | CopyTwoTone,
9 | LinkOutlined,
10 | ExperimentTwoTone,
11 | ContainerTwoTone,
12 | HourglassTwoTone
13 | } from '@ant-design/icons';
14 |
15 | const { Sider } = Layout;
16 | const { Title } = Typography;
17 |
18 | const SideNav = ({ darkMode, selected, onSelect }) => {
19 | const theme = darkMode ? 'dark' : 'light';
20 |
21 | const onClick = ({ key }) => {
22 | if (key !== '_msDemoLink') onSelect(key);
23 | };
24 |
25 | return (
26 |
27 |
32 | PowerBI Report Component
33 |
34 |
98 |
99 | );
100 | };
101 |
102 | export default SideNav;
103 |
--------------------------------------------------------------------------------
/src/docs/Report/Form.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Input, Select } from 'antd';
3 | import { layout } from '../styles/formLayoutStyles';
4 | import FormButtonGroup from '../common/FormButtonGroup';
5 |
6 | const ReportForm = ({ onSubmit, initialReportProps, onReset }) => {
7 | const [isSubmit, setIsSubmit] = React.useState(false);
8 |
9 | const onSubmitForm = ({ reportProps }) => {
10 | setIsSubmit(true);
11 | onSubmit({ reportProps });
12 | };
13 |
14 | const onResetForm = () => {
15 | setIsSubmit(false);
16 | onReset(false);
17 | };
18 |
19 | return (
20 |
33 |
37 |
38 |
43 |
44 |
45 |
50 |
51 |
52 |
62 |
63 |
64 |
65 |
69 |
70 |
74 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | );
88 | };
89 |
90 | export default ReportForm;
91 |
--------------------------------------------------------------------------------
/src/docs/UseReportDemo/Form.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Input, Select } from 'antd';
3 | import { layout } from '../styles/formLayoutStyles';
4 | import FormButtonGroup from '../common/FormButtonGroup';
5 |
6 | const ReportForm = ({ onSubmit, initialReportProps, onReset }) => {
7 | const [isSubmit, setIsSubmit] = React.useState(false);
8 |
9 | const onSubmitForm = ({ reportProps }) => {
10 | setIsSubmit(true);
11 | onSubmit({ reportProps });
12 | };
13 |
14 | const onResetForm = () => {
15 | setIsSubmit(false);
16 | onReset(false);
17 | };
18 |
19 | return (
20 |
33 |
36 |
37 |
42 |
46 |
47 |
52 |
53 |
54 |
59 |
60 |
61 |
71 |
72 |
73 |
77 |
81 |
82 |
83 |
87 |
88 |
89 |
90 | );
91 | };
92 |
93 | export default ReportForm;
94 |
--------------------------------------------------------------------------------
/src/docs/MultiplePageDemo/Form.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, Input, Select } from 'antd';
3 | import { layout } from '../styles/formLayoutStyles';
4 | import FormButtonGroup from '../common/FormButtonGroup';
5 |
6 | const ReportForm = ({ onSubmit, initialReportProps, onReset }) => {
7 | const [isSubmit, setIsSubmit] = React.useState(false);
8 |
9 | const onSubmitForm = ({ reportProps }) => {
10 | setIsSubmit(true);
11 | onSubmit({ reportProps });
12 | };
13 |
14 | const onResetForm = () => {
15 | setIsSubmit(false);
16 | onReset(false);
17 | };
18 |
19 | return (
20 |
34 |
38 |
39 |
44 |
45 |
46 |
51 |
52 |
53 |
63 |
64 |
65 |
66 |
70 |
71 |
81 |
82 |
83 |
93 |
94 |
95 |
96 |
97 | );
98 | };
99 |
100 | export default ReportForm;
101 |
--------------------------------------------------------------------------------
/src/lib/hooks/useReport.ts:
--------------------------------------------------------------------------------
1 | import { useState, useCallback } from 'react';
2 | import {
3 | parseConfigErrors,
4 | validateConfig,
5 | createEmbedConfigBasedOnEmbedType,
6 | validateBootrapConfig
7 | } from '../utils/config';
8 | import { Config } from '../types';
9 | import { Embed } from 'embed';
10 |
11 | declare type UseReport = [any, (ref: any, config: Config) => void];
12 |
13 | declare type UseBootstrap = [any, (ref: any, config: Config) => void, (ref: any, config: Config) => void];
14 |
15 | // powerbi object is global
16 | // used inside Embed.jsx has more logic tied to props of Embed.
17 | function _useReport(
18 | performOnEmbed: (report: any, reportRef?: any) => void
19 | ): UseReport {
20 | const [report, _setEmbedInstance] = useState