diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..6e7798f5 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +# Task 512388: Fix eslint warnings and errors in tests +/node_modules/* +/**/*.js +dist/* \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..4240ccee --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,236 @@ +// TODO: Remove "warn" settings for the rules after resolving them +module.exports = { + "env": { + "browser": true, + "node": true + }, + "extends": [ + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "webpack.test.tsconfig.json", + "sourceType": "module" + }, + "plugins": [ + "eslint-plugin-jsdoc", + "eslint-plugin-prefer-arrow", + "eslint-plugin-import", + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/adjacent-overload-signatures": "warn", + "@typescript-eslint/array-type": "off", + "@typescript-eslint/await-thenable": "warn", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/ban-types": [ + "warn", + { + "types": { + "Object": { + "message": "Avoid using the `Object` type. Did you mean `object`?" + }, + "Function": false, + "object": false, + "Boolean": { + "message": "Avoid using the `Boolean` type. Did you mean `boolean`?" + }, + "Number": { + "message": "Avoid using the `Number` type. Did you mean `number`?" + }, + "String": { + "message": "Avoid using the `String` type. Did you mean `string`?" + }, + "Symbol": { + "message": "Avoid using the `Symbol` type. Did you mean `symbol`?" + } + } + } + ], + "@typescript-eslint/consistent-type-definitions": "warn", + "@typescript-eslint/dot-notation": "off", + "@typescript-eslint/explicit-member-accessibility": [ + "off", + { + "accessibility": "explicit" + } + ], + "@typescript-eslint/explicit-module-boundary-types": [ + "warn", + { "allowArgumentsExplicitlyTypedAsAny": true } + ], + "@typescript-eslint/indent": [ + "warn", + 2, + { + "SwitchCase": 1, + "FunctionDeclaration": { + "parameters": "first" + }, + "FunctionExpression": { + "parameters": "first" + } + } + ], + "@typescript-eslint/member-delimiter-style": [ + "warn", + { + "multiline": { + "delimiter": "semi", + "requireLast": true + }, + "singleline": { + "delimiter": "semi", + "requireLast": false + } + } + ], + "@typescript-eslint/explicit-function-return-type": [ + "error", + { + "allowExpressions": true, + "allowDirectConstAssertionInArrowFunctions": true + } + ], + "@typescript-eslint/member-ordering": "off", + "@typescript-eslint/naming-convention": "off", + "@typescript-eslint/no-array-constructor": "warn", + "@typescript-eslint/no-empty-function": "warn", + "@typescript-eslint/no-empty-interface": "warn", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-extra-non-null-assertion": "warn", + "@typescript-eslint/no-extra-semi": "warn", + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-for-in-array": "warn", + "@typescript-eslint/no-implied-eval": "warn", + "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/no-misused-new": "warn", + "@typescript-eslint/no-misused-promises": "off", + "@typescript-eslint/no-namespace": "warn", + "@typescript-eslint/no-non-null-asserted-optional-chain": "warn", + "@typescript-eslint/no-non-null-assertion": "warn", + "@typescript-eslint/no-parameter-properties": "off", + "@typescript-eslint/no-this-alias": "warn", + "@typescript-eslint/no-unnecessary-type-assertion": "warn", + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-unused-expressions": "warn", + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "args": "after-used", "argsIgnorePattern": "^_" + } + ], + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/no-var-requires": "warn", + "@typescript-eslint/prefer-as-const": "warn", + "@typescript-eslint/prefer-for-of": "warn", + "@typescript-eslint/prefer-namespace-keyword": "warn", + "@typescript-eslint/prefer-regexp-exec": "off", + "@typescript-eslint/quotes": [ + "off", + { + "avoidEscape": true + } + ], + "@typescript-eslint/require-await": "warn", + "@typescript-eslint/restrict-plus-operands": "warn", + "@typescript-eslint/restrict-template-expressions": "off", + "@typescript-eslint/semi": [ + "error", + ], + "@typescript-eslint/triple-slash-reference": [ + "warn", + { + "path": "always", + "types": "prefer-import", + "lib": "always" + } + ], + "@typescript-eslint/type-annotation-spacing": "warn", + "@typescript-eslint/unbound-method": "off", + "@typescript-eslint/unified-signatures": "warn", + "arrow-parens": "off", + "brace-style": [ + "off", + "1tbs" + ], + "comma-dangle": "off", + "complexity": "off", + "constructor-super": "warn", + "eol-last": "warn", + "eqeqeq": [ + "warn", + "smart" + ], + "guard-for-in": "warn", + "id-blacklist": [ + "warn", + "any", + "Number", + "number", + "String", + "string", + "Boolean", + "boolean", + "Undefined", + ], + "id-match": "warn", + "import/order": "off", + "jsdoc/check-alignment": "warn", + "jsdoc/check-indentation": "warn", + "jsdoc/newline-after-description": "warn", + "max-classes-per-file": [ + "warn", + 1 + ], + "max-len": "off", + "new-parens": "warn", + "no-array-constructor": "off", + "no-caller": "warn", + "no-cond-assign": "warn", + "no-console": "off", + "no-debugger": "warn", + "no-empty": "warn", + "no-empty-function": "off", + "no-eval": "warn", + "no-extra-semi": "off", + "no-fallthrough": "off", + "no-implied-eval": "off", + "no-invalid-this": "off", + "no-multiple-empty-lines": ["error", { "max": 1 }], + "no-new-wrappers": "warn", + "no-shadow": "off", + "no-trailing-spaces": "warn", + "no-undef-init": "warn", + "no-underscore-dangle": "off", + "no-unsafe-finally": "warn", + "no-unused-labels": "warn", + "no-var": "warn", + "object-shorthand": "off", + "one-var": "off", + "prefer-const": "off", + "prefer-rest-params": "warn", + "quote-props": [ + "warn", + "consistent-as-needed" + ], + "radix": "warn", + "require-await": "off", + "space-before-function-paren": "off", + "spaced-comment": [ + "warn", + "always", + { + "markers": [ + "/" + ] + } + ], + "use-isnan": "warn", + "valid-typeof": "off" + } +}; diff --git a/.gitignore b/.gitignore index 713cbd07..d8bec088 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ node_modules/ -bower_components/ coverage/ docs typings/ @@ -9,4 +8,7 @@ npm-debug.log* dist/powerbi.js.map *.js.map package-lock.json -demo/package-lock.json +.vscode +owners.txt +test/util.spec.ts +.config/tsaoptions.json \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 4479811e..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "editor.tabSize": 2, - "editor.insertSpaces": true, - "editor.detectIndentation": false -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index a7b839de..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "0.1.0", - "command": "npm", - "isShellCommand": true, - "showOutput": "always", - "suppressTaskName": true, - "tasks": [ - { - "taskName": "build", - "args": [ - "run", - "build" - ], - "isBuildCommand": true - }, - { - "taskName": "test", - "args": [ - "run", - "test", - "--", - "--chrome" - ], - "isTestCommand": true - } - ] -} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 9e5bfa50..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,61 +0,0 @@ -# 2.0.0-beta.1 (GA candidate) - -## Breaking - -- DOMContentLoaded handler is now opt-in instead of the default behavior - - Reasons: - - The primary use case will be using the core library within another library which may not have the DOM ready even if DOMContentLoaded has fired. - - Most developers using SPA applications will fetch embed data asynchronously and not know report data by the time the DOMContentLoaded has fired. - - How to opt-in to DOMContentLoaded: - - Call `enableAutoEmbed()` on an instance of the PowerBi service to add the event listener. - - Example: - ``` - - - ``` - - Alternately if you are creating an instance of the service you can pass a configuration parameter `autoEmbedOnContentLoaded` - - Example: - ``` - var powerbiService = new Powerbi({ autoEmbedOnContentLoaded: true }); - ``` -- `powerbi.get(element: HTMLElement)` now only returns the instance of powerbi component associated with the element and does not implicitly emebed. Use `powerbi.embed(element: HTMLElement, config: IEmbedOptions = {})`. - - Reasons: - - powerbi.embed performed the same function and is more semantic. - - Now that overwrite: true is the default behavior for .embed having a separate method (get) for only retrieving compnents is good separation of intents. -- Embed urls must be provided by the server and will not be constructed by the components. This implies that the attributes `powerbi-report` will no longer be used. - - Reasons: - - The construction of these urls was unreliable since it dependeded on assumptions about server configuration (target environment, component type, etc). - Since url would be incorrect in some cases it could cause trouble for developers. Also, since the sever is already returning access tokens it's trival for the server to also provide embed urls and this reduces complexity. - - Previously you could supply the embed information in two ways: - - 1. Using report id: - - `
` - - This would implicitly construct the embed url to be something like: `https://embedded.powerbi.com/reports/5dac7a4a-4452-46b3-99f6-a25915e0fe55` - However - - 2. Using embed url: - - `
` - - Now only the latter options (#2) is supported. - -- Embed url attribute changed from `powerbi-embed` to `powerbi-embed-url` -- Component type is specified by attribute `powerbi-type`. Use `powerbi-type="report"` instead of applying the attribute `powerbi-report` -- Configuration settings attributes all start with prefix `powerbi-settings-`. - -## Changes - -- Fix bug to prevent memory leak of holding references to iframe elements which had been removed from the DOM. -- Detect overwriting container with new component and either throw error or properly cleanup and replace old component based on `config.overwrite` setting. -- Fix bug with prematurely attempting to parse post message data until it is known that it originated from embedded iframe. - -# 1.0.0 (Preview) \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f9a082e4..3e7f6be3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,33 +55,10 @@ node node_modules/karma/bin/karma start --browsers=Firefox --single-run=false -- The build and tests use webpack to compile all the source modules into one bundled module that can execute in the browser. -## Running the demo -Navigate to `/demo` directory - -Install bower dependencies: -``` -bower install -``` - -Serve the demo directory: -``` -npm start -``` - -Open the address to view in the browser: -``` -http://127.0.0.1:8080/ -``` - -## Updating the documenatation (For those with push permissions only) +## Updating the documentation (For those with push permissions only) First run the command to build the docs and open it to verify the changes are as expected. ``` npm run gulp -- build:docs ``` > There are errors during the TypeDoc compilation step due to some complication with modules however the documentation should still be generated. It's not clear if these are fixable by including more src files in the gulp task or if it's just the nature of TypeDoc lacking capabilities for this project structure. - -If the docs are correct then you may publish them to gh-pages using this command -``` -npm run gulp -- ghpages -``` \ No newline at end of file diff --git a/README.md b/README.md index c5d7c82e..9fecd37e 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,25 @@ # powerbi-client -JavaScript library for embedding Power BI into your apps. +A client side library for embedding Power BI using JavaScript or TypeScript into your apps. [![Build Status](https://img.shields.io/travis/Microsoft/PowerBI-JavaScript/master.svg)](https://travis-ci.org/Microsoft/PowerBI-JavaScript) [![NPM Version](https://img.shields.io/npm/v/powerbi-client.svg)](https://www.npmjs.com/package/powerbi-client) -[![Bower Version](https://img.shields.io/bower/v/powerbi-client.svg)](https://bower.io/search/?q=powerbi-client) [![Nuget Version](https://img.shields.io/nuget/v/Microsoft.PowerBI.JavaScript.svg)](https://www.nuget.org/packages/Microsoft.PowerBI.JavaScript/) [![NPM Total Downloads](https://img.shields.io/npm/dt/powerbi-client.svg)](https://www.npmjs.com/package/powerbi-client) [![NPM Monthly Downloads](https://img.shields.io/npm/dm/powerbi-client.svg)](https://www.npmjs.com/package/powerbi-client) [![GitHub tag](https://img.shields.io/github/tag/microsoft/powerbi-javascript.svg)](https://github.com/Microsoft/PowerBI-JavaScript/tags) [![Gitter](https://img.shields.io/gitter/room/Microsoft/PowerBI-JavaScript.svg)](https://gitter.im/Microsoft/PowerBI-JavaScript) -## Wiki -See the [wiki](https://github.com/Microsoft/PowerBI-JavaScript/wiki) for more details about embedding, service configuration, setting a default page, page navigation, dynamically applying filters, and more. +## Documentation +See the [Power BI embedded analytics Client APIs documentation](https://docs.microsoft.com/javascript/api/overview/powerbi/) to learn how to embed a Power BI report in your application and how to use the client APIs. ## Code Docs -See the [code docs](https://microsoft.github.io/PowerBI-JavaScript) for detailed information about classes, interfaces, types, etc. +See the [code docs](https://learn.microsoft.com/en-us/javascript/api/powerbi/powerbi-client) for detailed information about classes, interfaces, types, etc. -## Demo -New [live demo](https://microsoft.github.io/PowerBI-JavaScript/demo) for a sample application using the `powerbi-client` library in scenarios such as page navigation, applying filters, updating settings, and more. +## Sample Application +For examples of applications utilizing the `powerbi-client` library, please refer to the available samples in the [PowerBI-Developer-Samples repository](https://github.com/microsoft/PowerBI-Developer-Samples). + +## Playground +To explore and understand the capabilities of embedded analytics in your applications, please visit the [Power BI Embedded Analytics Playground](https://playground.powerbi.com). ## Installation @@ -29,10 +31,6 @@ Install from NPM: `npm install --save powerbi-client` -Install from Bower: - -`bower install powerbi-client --save` - Installing beta versions: `npm install --save powerbi-client@beta` @@ -48,10 +46,16 @@ import * as pbi from 'powerbi-client'; However, the library is exported as a Universal Module and the powerbi.js script can be included before your app's closing `` tag as: ```html - + ``` When included directly, the library is exposed as a global named `powerbi-client`. There is also another global named `powerbi` which is an instance of the service. +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit . + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..12fbd833 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + \ No newline at end of file diff --git a/bower.json b/bower.json deleted file mode 100644 index c6414984..00000000 --- a/bower.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "powerbi-client", - "description": "", - "main": "./dist/powerbi.js", - "authors": [ - "Microsoft" - ], - "license": "MIT", - "moduleType": [], - "homepage": "https://dev.powerbi.com/", - "private": false, - "ignore": [ - "**/.*", - "*/.js", - "*/.md", - "*/.nuspec", - "demo", - "node_modules", - "bower_components", - "src", - "test", - "tests", - "tsconfig.json", - "typings.json", - "webpack.test.tsconfig.json" - ], - "devDependencies": { - "jquery": "~2.2.0" - } -} diff --git a/demo/LICENSE.txt b/demo/LICENSE.txt deleted file mode 100644 index 736dfd1e..00000000 --- a/demo/LICENSE.txt +++ /dev/null @@ -1,13 +0,0 @@ -Microsoft.PowerBI.JavaScript - -Copyright (c) Microsoft Corporation - -All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/demo/NOTICE.txt b/demo/NOTICE.txt deleted file mode 100644 index 93917b59..00000000 --- a/demo/NOTICE.txt +++ /dev/null @@ -1,16 +0,0 @@ -Microsoft.PowerBI.JavaScript - -THIRD-PARTY SOFTWARE NOTICES AND INFORMATION -Do Not Translate or Localize - -This project incorporates components from the projects listed below. The original copyright notices and the licenses under which Microsoft received such components are set forth below. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise. - - 1. SyntaxHighlighter (https://github.com/syntaxhighlighter/syntaxhighlighter) - - Copyright (c) 2004-2013, Alex Gorbatchev - - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/demo/app/dataselection.js b/demo/app/dataselection.js deleted file mode 100644 index bd30f240..00000000 --- a/demo/app/dataselection.js +++ /dev/null @@ -1,39 +0,0 @@ -$(function () { - var models = window['powerbi-client'].models; - - console.log('Scenario 7: Data Selection'); - - var reportUrl = 'https://powerbi-embed-api.azurewebsites.net/api/reports/c52af8ab-0468-4165-92af-dc39858d66ad'; - var $reportContainer = $('#reportContainer'); - var report; - var $dataSelectedContainer = $("#dataSelectedContainer"); - - // Init - fetch(reportUrl) - .then(function (response) { - if (response.ok) { - return response.json() - .then(function (embedConfig) { - report = powerbi.embed($reportContainer.get(0), embedConfig); - initializeDataSelection(report, $dataSelectedContainer); - return report; - }); - } - else { - return response.json() - .then(function (error) { - throw new Error(error); - }); - } - }); -}); - -function initializeDataSelection(report, $dataSelectedContainer) { - report.on('dataSelected', function (event) { - console.log('dataSelected: ', event); - - var data = event.detail; - - $dataSelectedContainer.text(JSON.stringify(data, null, ' ')); - }); -} diff --git a/demo/app/defaults.js b/demo/app/defaults.js deleted file mode 100644 index c6ecf136..00000000 --- a/demo/app/defaults.js +++ /dev/null @@ -1,52 +0,0 @@ -$(function () { - var models = window['powerbi-client'].models; - - console.log('Scenario 5: Default Page and/or Filter'); - - var staticReportUrl = 'https://powerbi-embed-api.azurewebsites.net/api/reports/c52af8ab-0468-4165-92af-dc39858d66ad'; - var $defaultPageReportContainer = $('#reportdefaults'); - var defaultPageReport; - var defaultPageName = 'ReportSection2'; - var defaultFilter = new models.AdvancedFilter({ - table: "Store", - column: "Name" - }, "Or", [ - { - operator: "Contains", - value: "Wash" - }, - { - operator: "Contains", - value: "Park" - } - ]); - - var defaultFilters = [defaultFilter]; - - // Init - fetch(staticReportUrl) - .then(function (response) { - if (response.ok) { - return response.json() - .then(function (embedConfig) { - var defaultsEmbedConfig = $.extend({}, embedConfig, { - pageName: defaultPageName, - filter: defaultFilters, - settings: { - filterPaneEnabled: true, - navContentPaneEnabled: true - } - }); - - defaultPageReport = powerbi.embed($defaultPageReportContainer.get(0), defaultsEmbedConfig); - return defaultPageReport; - }); - } - else { - return response.json() - .then(function (error) { - throw new Error(error); - }); - } - }); -}); diff --git a/demo/app/dynamic.js b/demo/app/dynamic.js deleted file mode 100644 index 8812768d..00000000 --- a/demo/app/dynamic.js +++ /dev/null @@ -1,75 +0,0 @@ -$(function () { - var models = window['powerbi-client'].models; - - console.log('Scenario 2: Dynamic Embed'); - - // Declare Variables - var allReportsUrl = 'https://powerbi-embed-api.azurewebsites.net/api/reports'; - var $reportsList = $('#reportslist'); - var $resetButton = $('#resetButton'); - var $dynamicReportContainer = $('#reportdynamic'); - - // When report button is clicked embed the report - $reportsList.on('click', 'button', function (event) { - var button = event.target; - var report = $(button).data('report'); - var url = allReportsUrl + '/' + report.id; - - fetch(url) - .then(function (response) { - if (response.ok) { - return response.json() - .then(function (embedConfig) { - return powerbi.embed($dynamicReportContainer.get(0), embedConfig); - }); - } - else { - return response.json() - .then(function (error) { - throw new Error(error); - }); - } - }); - }); - - // When reset button is clicked reset container - $resetButton.on('click', function (event) { - powerbi.reset($dynamicReportContainer.get(0)); - }); - - // Helper function to generate HTML for each report - function generateReportListItem(report) { - var button = $(' - - - - - \ No newline at end of file diff --git a/demo/code-demo/code_area.html b/demo/code-demo/code_area.html deleted file mode 100644 index b4d52067..00000000 --- a/demo/code-demo/code_area.html +++ /dev/null @@ -1,13 +0,0 @@ - -
Code
-
- - -
- -
-
\ No newline at end of file diff --git a/demo/code-demo/docs.html b/demo/code-demo/docs.html deleted file mode 100644 index 96cc05b6..00000000 --- a/demo/code-demo/docs.html +++ /dev/null @@ -1,26 +0,0 @@ -
-
-

Getting Started

-
-
- Please visit our - documentation - to start using Power BI Embedded. -
-
- -

Videos

- -
-
- 1. Learn how to Embed and Interact with Power BI Reports. -
- -
- -
-
- 2. Learn how to Create, Edit and Save Power BI reports in Embedded view. -
- -
diff --git a/demo/code-demo/images/arrow.png b/demo/code-demo/images/arrow.png deleted file mode 100644 index e1acaefe..00000000 Binary files a/demo/code-demo/images/arrow.png and /dev/null differ diff --git a/demo/code-demo/images/arrow_flipped.png b/demo/code-demo/images/arrow_flipped.png deleted file mode 100644 index 76c76eeb..00000000 Binary files a/demo/code-demo/images/arrow_flipped.png and /dev/null differ diff --git a/demo/code-demo/images/clear.png b/demo/code-demo/images/clear.png deleted file mode 100644 index d2d65ca3..00000000 Binary files a/demo/code-demo/images/clear.png and /dev/null differ diff --git a/demo/code-demo/images/copy.png b/demo/code-demo/images/copy.png deleted file mode 100644 index 37d7203f..00000000 Binary files a/demo/code-demo/images/copy.png and /dev/null differ diff --git a/demo/code-demo/images/run.png b/demo/code-demo/images/run.png deleted file mode 100644 index ebd98604..00000000 Binary files a/demo/code-demo/images/run.png and /dev/null differ diff --git a/demo/code-demo/index.html b/demo/code-demo/index.html deleted file mode 100644 index 20f53c13..00000000 --- a/demo/code-demo/index.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - -
- -
- -
-
-
- -
-
- -
-
-
- - - - - - - - - - - - - - - - - - - - - diff --git a/demo/code-demo/log_window.html b/demo/code-demo/log_window.html deleted file mode 100644 index 37760719..00000000 --- a/demo/code-demo/log_window.html +++ /dev/null @@ -1,12 +0,0 @@ -
-
Log Viewer
-
- - -
- -
- -
-
- Cancel -
-
- Send -
-
- -
Sent
- - - - - - - \ No newline at end of file diff --git a/demo/v2-demo/live_showcases/insight_to_action/showcase_insight_to_action.js b/demo/v2-demo/live_showcases/insight_to_action/showcase_insight_to_action.js deleted file mode 100644 index 519df4e7..00000000 --- a/demo/v2-demo/live_showcases/insight_to_action/showcase_insight_to_action.js +++ /dev/null @@ -1,340 +0,0 @@ -let InsightToActionShowcaseState = { - report: null, - data: null, - allChecked: false, - tooltipNextPressed: false, -} - -const dialogTooltipTimeout = 1500; -const sentMessageTimeout = 3000; - -// Embed the report and retrieve the existing report bookmarks -function embedInsightsToActionReport() { - InsightToActionShowcaseState.tooltipNextPressed = false; - - // Load sample report properties into session - return LoadInsightToActionShowcaseReportIntoSession().then(function () { - - // Get models. models contains enums that can be used - const models = window['powerbi-client'].models; - - // Get embed application token from session - let accessToken = GetSession(SessionKeys.AccessToken); - - // Get embed URL from session - let embedUrl = GetSession(SessionKeys.EmbedUrl); - - // Get report Id from session - let embedReportId = GetSession(SessionKeys.EmbedId); - - // Use View permissions - let permissions = models.Permissions.View; - - // Icon for the custom extension - const base64Icon = "data:image/png;base64,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" - - // Table visual name - const tableVisualName = "1149606f2a101953b4ba"; - - // Embed configuration used to describe the what and how to embed - // This object is used when calling powerbi.embed - // This also includes settings and options such as filters - // You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details - let config= { - type: 'report', - tokenType: models.TokenType.Embed, - accessToken: accessToken, - embedUrl: embedUrl, - id: embedReportId, - permissions: permissions, - settings: { - filterPaneEnabled: false, - navContentPaneEnabled: false, - - // Adding the extension command to the options menu - extensions: [ - { - command: { - name: "campaign", - title: "Start campaign", - icon: base64Icon, - selector: { - $schema: "http://powerbi.com/product/schema#visualSelector", - visualName: tableVisualName - }, - extend: { - visualOptionsMenu: { - title: "Start campaign", - menuLocation: models.MenuLocation.Top, - } - } - } - }, - ], - - // Hiding built-in commands on the options menu - commands: [ - { - spotlight: { - selector: { - visualName: tableVisualName - }, - displayOption: models.CommandDisplayOption.Hidden, - }, - exportData: { - selector: { - visualName: tableVisualName - }, - displayOption: models.CommandDisplayOption.Hidden, - }, - seeData: { - selector: { - visualName: tableVisualName - }, - displayOption: models.CommandDisplayOption.Hidden, - }, - } - ] - }, - }; - - // Get a reference to the embedded report HTML element - let embedContainer = $('#embedContainer')[0]; - - // Embed the report and display it within the div container - InsightToActionShowcaseState.report = powerbi.embed(embedContainer, config); - InsightToActionShowcaseState.report.on("rendered", function() { - setTooltipPosition(); - $('#startTooltip').addClass("showTooltip"); - - // Remove event handler, thus, the tooltip will appear only once - InsightToActionShowcaseState.report.off("rendered"); - }); - - // Report.on will add an event handler to commandTriggered event which prints to console window. - InsightToActionShowcaseState.report.on("commandTriggered", function(event) { - if (event.detail.command === "campaign") { - InsightToActionShowcaseState.report.getPages() - .then(function (pages) { - - // Retrieve active page. - let activePage = pages.filter(function(page) { - return page.isActive - })[0]; - - // Get page's visuals - activePage.getVisuals() - .then(function (visuals) { - - // Retrieve the wanted visual. - let visual = visuals.filter(function(visual) { - return visual.name === tableVisualName; - })[0]; - - // Exports visual data - visual.exportData(models.ExportDataType.Underlying).then(handleExportData); - }); - }); - } - }); - }); -} - -// Handles the export data API result -function handleExportData(result) { - - // Parse the recieved data from csv to 2d array - let resultData = parseData(result.data); - - // Filter the unwanted columns - InsightToActionShowcaseState.data = filterTable(["Latest purchase - Category", "Total spend", "Days since last purchase"], resultData); - - // Create a table from the 2d array - let table = createTable(InsightToActionShowcaseState.data) - - // Clear the div - $("#dialogTable").empty(); - - // Add the table to the dialog - $("#dialogTable").append(table) - - // Hide the tooltip - $('#startTooltip').removeClass("showTooltip"); - - // Show the dialog - $('#dialogMask').show(); - $('#distributionDialog').show(); - - // Shows dialog tooltip after a short delay - setTimeout(function() { - $('#dialogTooltip').addClass("showTooltip"); - }, dialogTooltipTimeout); -} - -// Parse the data from the API -function parseData(data) { - let result = []; - data.split("\n").forEach(function(row) { - if (row !== "") { - let rowArray = []; - row.split(",").forEach(function(cell) { - rowArray.push(cell); - }); - - result.push(rowArray); - } - }); - - return result; -} - -// Filter the table's data - removing the 'filterValues' columns -function filterTable(filterValues, table) { - for (let i = 0; i < filterValues.length; i++) { - valueIndex = table[0].indexOf( - table[0].filter(function(value) { return value === filterValues[i] })[0] - ); - - for (let j = 0; j < table.length; j++) { - table[j].splice(valueIndex, 1); - } - } - - return table; -} - -// Handles tooltip click action -function onTootipClicked(tooltipId) { - if (!InsightToActionShowcaseState.tooltipNextPressed && tooltipId === "startTooltip") { - let newText = document.createTextNode("Then, click `Start campaign` menu command."); - let startTooltipSubText = $('#startTooltip .showcaseTooltipSubText'); - const textOldHeight = startTooltipSubText[0].offsetHeight; - startTooltipSubText.empty(); - startTooltipSubText.append(newText); - startTooltipSubText[0].setAttribute("style", "height: " + textOldHeight + "px;"); - - let newTooltipNumber = document.createTextNode("2 of 2"); - $('#startTooltip .tooltipNumber').empty(); - $('#startTooltip .tooltipNumber').append(newTooltipNumber); - - let newBtnText = document.createTextNode("Got it"); - $('#startTooltip .btnShowcaseTooltip').empty(); - $('#startTooltip .btnShowcaseTooltip').append(newBtnText); - - InsightToActionShowcaseState.tooltipNextPressed = true; - } else { - $('#' + tooltipId).hide(); - } -} - -// Closes the dialog -function onCloseDialog(id) { - $('#dialogTooltip').hide(); - $('#dialogMask').hide(); - $('#' + id).hide(); -} - -// Open the send coupon/discount dialog -function onSendClicked(name) { - let headerText = document.createTextNode("Send " + name + " to distribution list"); - $('#sendDialog .dialogHeaderText').empty(); - $('#sendDialog .dialogHeaderText').append(headerText); - - const promotionToSend = name === "coupon" ? "30$ coupon" : "10% discount"; - let bodyText = "Hi , get your " + promotionToSend + " today!"; - $('#sendDialog textarea').val(bodyText); - - $('#dialogTooltip').hide(); - $('#distributionDialog').hide(); - $('#sendDialog').show(); -} - -// Closes the send dialog and shows the 'Sent' message -function onSendDialogSendClicked() { - $('#sendDialog').hide(); - $('#dialogMask').hide(); - $('#messageSent').addClass("show"); - - setTimeout(function() { - $('#messageSent').removeClass("show"); - }, sentMessageTimeout); -} - -// Build the HTML table from the data -function createTable(tableData) { - let table = document.createElement('table'); - let tableBody = document.createElement('tbody'); - let rowIndex = 0; - - // Set all checked to true, for check all table button - InsightToActionShowcaseState.allChecked = true; - - tableData.forEach(function(rowData) { - let row = document.createElement('tr'); - - // Add ✓ or checkbox - if (rowIndex === 0) { - let cell = document.createElement('th'); - cell.setAttribute("onclick","onCheckAllClicked();"); - cell.setAttribute("class", "checkAllBtn"); - cell.appendChild(document.createTextNode('✓')); - row.appendChild(cell); - } else { - let cell = document.createElement('td'); - let checkboxElement = document.createElement("input"); - checkboxElement.setAttribute("type", "checkbox"); - checkboxElement.setAttribute("name", "tableRowCheckbox"); - checkboxElement.setAttribute("id", "row" + rowIndex); - checkboxElement.checked = true; - cell.appendChild(checkboxElement); - row.appendChild(cell); - } - - let isNameCell = true; - rowData.forEach(function(cellData) { - let cell; - if (rowIndex !== 0) { - cell = document.createElement('td'); - if (isNameCell) { - cell.setAttribute("class", "nameCell"); - isNameCell = false; - } - } else { - cell = document.createElement('th'); - } - - cell.appendChild(document.createTextNode(cellData)); - row.appendChild(cell); - }); - - tableBody.appendChild(row); - rowIndex++; - }); - - table.appendChild(tableBody); - - return table; -} - -// Check/Uncheck all the customers on the table -function onCheckAllClicked() { - let checkboxes = document.getElementsByName("tableRowCheckbox"); - for (let i = 0; i < checkboxes.length; i++) { - checkboxes[i].checked = !InsightToActionShowcaseState.allChecked; - } - - InsightToActionShowcaseState.allChecked = !InsightToActionShowcaseState.allChecked; -} - -// Calculate and set the tooltip position -function setTooltipPosition() { - let startTooltip = document.getElementById("startTooltip"); - let embedContainer = document.getElementById('embedContainer'); - let textHeight = document.getElementById('showcases-text').offsetHeight; - let containerHeight = embedContainer.offsetWidth * 0.56; - - // Calculate the tooltip position relatively - const top = textHeight + 64 + ((embedContainer.offsetHeight - containerHeight) / 2) - startTooltip.offsetHeight + (0.05 * embedContainer.offsetHeight); - const left = (embedContainer.offsetWidth - 10) * 0.971 - 125; - startTooltip.setAttribute("style", "top: " + top + "px; left: " + left + "px;"); -} \ No newline at end of file diff --git a/demo/v2-demo/live_showcases/quick_visual_creator/showcase_quick_visual_creator.html b/demo/v2-demo/live_showcases/quick_visual_creator/showcase_quick_visual_creator.html deleted file mode 100644 index b77b94f4..00000000 --- a/demo/v2-demo/live_showcases/quick_visual_creator/showcase_quick_visual_creator.html +++ /dev/null @@ -1,192 +0,0 @@ -
-

Quick visual creator

-
-
- This showcase demonstrates one example of how you can leverage our visual APIs to quickly generate and personalize a visual.
- This is useful for quickly importing a visual into a presentation or email without having any prior Power BI experience,
- and for quick ad-hock analytics which can then be saved. Additionally, you can implement your own method for sharing or exporting the visual.

-
- 1. Choose the visual type from the dropdown list
-
Note: On this showcase we only provide a subset of the available visual types.

- 2. Select the fields to define the data for displaying in your visual

- 3. Use the 'Properties' to personalize your visual

- 4. You can use the 'Print' button to export the visual to PDF
-
-
- -
- -
-
-
Generator
-
-
-
- Visual Type -
-
- -
-
-
-
- Fields -
-
- Axis: -
- -
-
-
- Legend: -
- -
-
-
- Value: -
- -
-
- -
-
- -
- Properties -
-
- Legend: - -
-
- X Axis: - -
-
- Y Axis: - -
-
- Title: - -
- -
- Personalized Title: -
- - -
- -
-
- -
-
-
-
- -
- Title alignment: -
-
-
- -
-
- -
-
- -
-
-
-
- -
-
- -
-
- -
-
-
-
-
-
-
-
-
-
-
Visual view
-
- - -
-
-
- -
- Loading showcase... -
-
-
-
-
-
- - \ No newline at end of file diff --git a/demo/v2-demo/live_showcases/quick_visual_creator/showcase_quick_visual_creator.js b/demo/v2-demo/live_showcases/quick_visual_creator/showcase_quick_visual_creator.js deleted file mode 100644 index e63f6f73..00000000 --- a/demo/v2-demo/live_showcases/quick_visual_creator/showcase_quick_visual_creator.js +++ /dev/null @@ -1,638 +0,0 @@ -let VisualCreatorShowcaseState = { - report: null, - page: null, - visual: null, - visualType: null, - dataRoles: { - Legend: null, - Values: null, - Value: null, - Axis: null, - Tooltips: null, - 'Y Axis': null, - Category: null, - Breakdown: null, - }, - dataFieldsCount: 0, - properties: { - legend: true, - xAxis: true, - yAxis: true, - title: true, - titleText: null, - titleAlign: null - }, -} - -// Define the available data roles for the visual types -const visualTypeToDataRoles = [ - { name: 'pieChart', displayName: 'Pie chart', dataRoles: ['Legend', 'Values', 'Tooltips'] }, - { name: 'columnChart', displayName: 'Column chart', dataRoles: ['Axis', 'Value', 'Tooltips'] }, - { name: 'areaChart', displayName: 'Area chart', dataRoles: ['Axis', 'Legend', 'Values'] }, - { name: 'waterfallChart', displayName: 'Waterfall Chart', dataRoles: ['Category', 'Breakdown', 'Y Axis'] }, -]; - -// Define the available fields for each data role -const dataRolesToFields = [ - { dataRole: 'Legend', Fields: ['State', 'Region', 'Manufacturer'] }, - { dataRole: 'Values', Fields: ['Total Units', 'Total Category Volume', 'Total Compete Volume'] }, - { dataRole: 'Axis', Fields: ['State', 'Region', 'Manufacturer'] }, - { dataRole: 'Value', Fields: ['Total Units', 'Total Category Volume', 'Total Compete Volume'] }, - { dataRole: 'Y Axis', Fields: ['Total Units', 'Total Category Volume', 'Total Compete Volume'] }, - { dataRole: 'Tooltips', Fields: ['Total Units', 'Total Category Volume', 'Total Compete Volume'] }, - { dataRole: 'Category', Fields: ['State', 'Region', 'Date'] }, - { dataRole: 'Breakdown', Fields: ['State', 'Region', 'Manufacturer'] }, -]; - -// Define schemas for visuals API -const schemas = { - column: 'http://powerbi.com/product/schema#column', - measure: 'http://powerbi.com/product/schema#measure', - property: 'http://powerbi.com/product/schema#property', -}; - -// Define mapping from fields to target table and column/measure -const dataFieldsTargets = { - State: { column: 'State', table: 'Geo', schema: schemas.column }, - Region: { column: 'Region', table: 'Geo', schema: schemas.column }, - District: { column: 'District', table: 'Geo', schema: schemas.column }, - Manufacturer: { column: 'Manufacturer', table: 'Manufacturer', schema: schemas.column }, - TotalUnits: { measure: 'Total Units', table: 'SalesFact', schema: schemas.measure }, - TotalCategoryVolume: { measure: 'Total Category Volume', table: 'SalesFact', schema: schemas.measure }, - TotalCompeteVolume: { measure: 'Total Compete Volume', table: 'SalesFact', schema: schemas.measure }, - Date: { measure: 'Date', table: 'Date', schema: schemas.measure }, -}; - -// Define the available -const showcaseProperties = ['legend', 'xAxis', 'yAxis']; -const visualTypeProperties = { - pieChart: ['legend'], - columnChart: ['xAxis', 'yAxis'], - areaChart: ['legend', 'xAxis', 'yAxis'], - waterfallChart: ['legend', 'xAxis', 'yAxis'], -}; - -const disabledClass = "generator-disabled"; - -// Embed the report -function embedQuickVisualCreatorReport() { - - // Load sample report properties into session - return LoadQuickVisualCreatorShowcaseReportIntoSession().then(function () { - - // Starting spinner animation - $("#spinner").show(); - - // Get models. models contains enums that can be used - let models = window['powerbi-client'].models; - - // Get embed application token from session - let accessToken = GetSession(SessionKeys.AccessToken); - - // Get embed URL from session - let embedUrl = GetSession(SessionKeys.EmbedUrl); - - // Get report Id from session - let embedReportId = GetSession(SessionKeys.EmbedId); - - // Use View permissions - let permissions = models.Permissions.View; - - // Embed configuration used to describe the what and how to embed - // This object is used when calling powerbi.embed - // This also includes settings and options such as filters - // You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details - let config = { - type: 'report', - tokenType: models.TokenType.Embed, - accessToken: accessToken, - embedUrl: embedUrl, - id: embedReportId, - permissions: permissions, - settings: { - filterPaneEnabled: false, - navContentPaneEnabled: false, - layoutType: models.LayoutType.Custom, - customLayout: { - pageSize: { - type: models.PageSizeType.Custom, - width: $('#embedContainer').width(), - height: $('#embedContainer').height() - }, - displayOption: models.DisplayOption.ActualSize, - } - } - }; - - // Get a reference to the embedded report HTML element - let embedContainer = $('#embedContainer')[0]; - - // Embed the report and display it within the div container - VisualCreatorShowcaseState.report = powerbi.embed(embedContainer, config); - - // Report.on will add an event handler for report rendered event - VisualCreatorShowcaseState.report.on("rendered", function () { - - // Setting the first page as active - VisualCreatorShowcaseState.report.getPages().then(function (pages) { - pages[0].setActive(); - VisualCreatorShowcaseState.page = pages[0]; - }); - - // Update html available visual types - updateAvailableVisualTypes(); - - // Enable choosing visual type - $("#generator-type").removeClass(disabledClass); - - // Hiding the spinner animation - $("#spinner").hide(); - - // Covering the embeded view with instruction text - $("#overlay-embed-container").addClass("overlay-text") - $('#overlay-embed-container').text('Start by choosing the visual type'); - $("#overlay-embed-container").show(); - - // Remove the event listener, thus, it will only be called once - VisualCreatorShowcaseState.report.off("rendered"); - }); - }); -} - -// Initialize the custom dropdowns -function initializeDropdowns() { - let x, i, j, selElmnt, a, b, c; - - // Look for any elements with the class "styled-select" - x = document.getElementsByClassName("styled-select"); - for (i = 0; i < x.length; i++) { - selElmnt = x[i].getElementsByTagName("select")[0]; - - // For each element, create a new DIV that will act as the selected item - a = document.createElement("DIV"); - a.setAttribute("class", "select-selected"); - a.setAttribute("id", "selected-value-" + i); - a.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML; - x[i].appendChild(a); - - // For each element, create a new DIV that will contain the option list - b = document.createElement("DIV"); - b.setAttribute("class", "select-items select-hide"); - for (j = 1; j < selElmnt.length; j++) { - - // For each option in the original select element, - // create a new DIV that will act as an option item - c = document.createElement("DIV"); - c.innerHTML = selElmnt.options[j].innerHTML; - - // Adding new click event listener - c.addEventListener("click", function (e) { - - // When an item is clicked, update the original select box, and the selected item - let y, i, k, s, h; - s = this.parentNode.parentNode.getElementsByTagName("select")[0]; - h = this.parentNode.previousSibling; - for (i = 0; i < s.length; i++) { - if (s.options[i].innerHTML == this.innerHTML) { - s.selectedIndex = i; - h.innerHTML = this.innerHTML; - y = this.parentNode.getElementsByClassName("same-as-selected"); - for (k = 0; k < y.length; k++) { - y[k].removeAttribute("class"); - } - - this.setAttribute("class", "same-as-selected"); - break; - } - } - - h.click(); - - // Changing the visual type or updating the data role field, according to the dropdown id - if (s.id == 'visual-type') { - changeVisualType(h.innerHTML); - } else { - updateDataRoleField(s.parentNode.parentNode.children[0].id, h.innerHTML); - } - }); - - b.appendChild(c); - } - - x[i].appendChild(b); - - // Adding new click event listener for the select box - a.addEventListener("click", function (e) { - // When the select box is clicked, close any other select boxes, - // and open/close the current select box - e.stopPropagation(); - closeAllSelect(this); - this.nextSibling.classList.toggle("select-hide"); - this.classList.toggle("select-arrow-active"); - }); - } -} - -// Close all select boxes in the document, except the current select box -function closeAllSelect(elmnt) { - - let x, y, i, arrNo = []; - x = document.getElementsByClassName("select-items"); - y = document.getElementsByClassName("select-selected"); - for (i = 0; i < y.length; i++) { - if (elmnt == y[i]) { - arrNo.push(i) - } else { - y[i].classList.remove("select-arrow-active"); - } - } - - for (i = 0; i < x.length; i++) { - if (arrNo.indexOf(i)) { - x[i].classList.add("select-hide"); - } - } -} - -// Changing the visual type -function changeVisualType(visualTypeDisplayName) { - // Get the visual type from the display name - let visualTypeData = visualTypeToDataRoles.filter((function (e) { return e.displayName === visualTypeDisplayName }))[0]; - let visualTypeName = visualTypeData.name; - - // Retrieve the visual's capabilities - VisualCreatorShowcaseState.report.getVisualCapabilities(visualTypeName).then(function (capabilities) { - - // Validating data roles existence on the given visual type - if (!validateDataRoles(capabilities, visualTypeData.dataRoles)) { - resetVisualGenerator(); - handleInvalidDataRoles(); - return; - } - - // Enable the fields section - $('#generator-fields').removeClass(disabledClass); - - // Disable the properties section, and reset all properties - $('#generator-properties').addClass(disabledClass); - resetGeneratorProperties(); - - // Update the overlay text - $('#overlay-embed-container').text('Use the dropdown menus to choose data fields'); - $('#overlay-embed-container').show(); - - // Reset the data fields count - VisualCreatorShowcaseState.dataFieldsCount = 0; - - // If the visual doesn't exist, create new visual, otherwise, delete the old visual and create new visual - if (!VisualCreatorShowcaseState.visual) { - VisualCreatorShowcaseState.page.createVisual(visualTypeName, getVisualLayout()).then(function () { - updateShowCaseVisType(visualTypeName, visualTypeData.dataRoles); - }); - } - else if (visualTypeName != VisualCreatorShowcaseState.visualType) { - VisualCreatorShowcaseState.page.deleteVisual(VisualCreatorShowcaseState.visual.name).then(function () { - VisualCreatorShowcaseState.page.createVisual(visualTypeName, getVisualLayout()).then(function () { - updateShowCaseVisType(visualTypeName, visualTypeData.dataRoles); - }); - }); - } - }); -} - -// Update showcase after visual type change -function updateShowCaseVisType(visualTypeName, dataRoles) { - updateCurrentVisualState(visualTypeName); - resetGeneratorDataRoles(); - updateAvailableDataRoles(dataRoles); - updateDropdownsVisibility(); -} - -// Update the visual state -function updateCurrentVisualState(visualTypeName) { - VisualCreatorShowcaseState.page.getVisuals().then(function (visuals) { - // Update visual and visual type - VisualCreatorShowcaseState.visual = visuals[0] - VisualCreatorShowcaseState.visualType = visualTypeName; - - // Enabling the pie chart legend (disabled by default) - if (visualTypeName === "pieChart") { - VisualCreatorShowcaseState.visual.setProperty(propertyToSelector('legend'), { schema: schemas.property, value: true }); - } - - // Formatting the title to be more accessible - VisualCreatorShowcaseState.visual.setProperty(propertyToSelector('titleSize'), { schema: schemas.property, value: 14 }); - VisualCreatorShowcaseState.visual.setProperty(propertyToSelector('titleColor'), { schema: schemas.property, value: '#000000' }); - - // Disabling unavailable properties for specific visual types - $('.toggle-wrapper').removeClass("disabled"); - for (let i = 0; i < showcaseProperties.length; i++) { - if (visualTypeProperties[visualTypeName].indexOf(showcaseProperties[i]) < 0) { - $('#' + showcaseProperties[i] + '.toggle-wrapper').addClass("disabled"); - } - } - }); -} - -// Update the data roles and the data roles fields, on the dropdown menus -function updateAvailableDataRoles(dataRoles) { - let dataRolesNamesElements = document.querySelectorAll('.inline-select-text'); - for (let i = 0; i < dataRoles.length; i++) { - dataRolesNamesElements[i].innerHTML = dataRoles[i] + ':'; - dataRolesNamesElements[i].id = dataRoles[i]; - - let dataFields = dataRolesToFields.filter(function (e) { return e.dataRole === dataRoles[i] })[0].Fields; - updateAvailableDataFields(dataRolesNamesElements[i].parentElement, dataFields); - } -} - -// Update the data fields on the dropdown menus -function updateAvailableDataFields(dataRoleElement, dataFields) { - let fieldDivElements = dataRoleElement.querySelector('.select-items').children; - let fieldOptionElements = dataRoleElement.querySelectorAll('option'); - for (let i = 0; i < dataFields.length; i++) { - fieldDivElements[i].innerHTML = dataFields[i]; - fieldOptionElements[i + 1].innerHTML = dataFields[i]; - } -} - -// Update html visual types -function updateAvailableVisualTypes() { - let typesDivElements = $('.select-items')[0].children; - let typesOptionElements = $('#visual-type')[0].children; - for (let i = 0; i < visualTypeToDataRoles.length; i++) { - typesDivElements[i].innerHTML = visualTypeToDataRoles[i].displayName; - typesOptionElements[i + 1].innerHTML = visualTypeToDataRoles[i].displayName; - } -} - -// Print the report -function printVisual() { - if (!VisualCreatorShowcaseState.visual) - return; - VisualCreatorShowcaseState.report.print(); -} - -// Update data roles field on the visual -function updateDataRoleField(dataRole, field) { - - // Check if the requested field is not the same as the selected field - if (field != VisualCreatorShowcaseState.dataRoles[dataRole]) { - - // Getting the visual capabilites - VisualCreatorShowcaseState.visual.getCapabilities().then(function (capabilities) { - - // Getting the data role name - let dataRoleName = capabilities.dataRoles.filter(function (dr) { return dr.displayName === dataRole })[0].name; - - // Remove whitespaces from field - let dataFieldKey = field.replace(/\s+/g, ''); - - // Check if the data role already has a field - if (VisualCreatorShowcaseState.dataRoles[dataRole]) { - - // If the data role has a field, remove it - VisualCreatorShowcaseState.visual.removeDataField(dataRoleName, 0).then(function (res) { - VisualCreatorShowcaseState.dataFieldsCount--; - - // If there are no more data fields, recreating the visual before adding the data field - if (VisualCreatorShowcaseState.dataFieldsCount === 0) { - VisualCreatorShowcaseState.page.createVisual(VisualCreatorShowcaseState.visualType, getVisualLayout()).then(function () { - VisualCreatorShowcaseState.page.getVisuals().then(function (visuals) { - VisualCreatorShowcaseState.visual = visuals[0]; - VisualCreatorShowcaseState.dataFieldsCount++; - VisualCreatorShowcaseState.visual.addDataField(dataRoleName, dataFieldsTargets[dataFieldKey]).then(function () { disableSelectedDataFields(dataRole, field); }); - }); - }); - } else { - VisualCreatorShowcaseState.dataFieldsCount++; - VisualCreatorShowcaseState.visual.addDataField(dataRoleName, dataFieldsTargets[dataFieldKey]).then(function () { disableSelectedDataFields(dataRole, field); }); - } - }); - } else { - - // Adding a new field - VisualCreatorShowcaseState.visual.addDataField(dataRoleName, dataFieldsTargets[dataFieldKey]).then(function () { - disableSelectedDataFields(dataRole, field); - VisualCreatorShowcaseState.dataFieldsCount++; - - // Showing the visual if there are 2 or more data fields - if (VisualCreatorShowcaseState.dataFieldsCount > 1) { - $("#overlay-embed-container").hide(); - $('#generator-properties').removeClass(disabledClass); - } - }); - } - }); - } -} - -// Hiding the selected data field from the dropdown -function disableSelectedDataFields(dataRole, field) { - VisualCreatorShowcaseState.dataRoles[dataRole] = field; - updateDropdownsVisibility(); -} - -// Update the visibility of the dropdowns -function updateDropdownsVisibility() { - $('.select-items div').show(); - - let selected = $('.select-selected'); - selected.each(function () { - let selectedValue = $(this).text(); - $('.select-items div:contains(' + selectedValue + ')').hide(); - }); -} - -// Return the visual layout -function getVisualLayout() { - // Get models. models contains enums that can be used - let models = window['powerbi-client'].models; - - return { - width: 0.9 * $('#embedContainer').width(), - height: 0.85 * $('#embedContainer').height(), - x: (0.1 * $('#embedContainer').width()) / 2, - y: (0.1 * $('#embedContainer').height()) / 2, - displayState: { - // Change the selected visuals display mode to visible - mode: models.VisualContainerDisplayMode.Visible - } - }; -} - -// Toggle a property value -function toggleProperty(propertyName) { - if (!VisualCreatorShowcaseState.visual) - return; - - let newValue = $('#' + propertyName + '-toggle')[0].checked; - VisualCreatorShowcaseState.properties[propertyName] = newValue; - - // Setting the property on the visual - VisualCreatorShowcaseState.visual.setProperty(propertyToSelector(propertyName), { schema: schemas.property, value: newValue }); -} - -// Update the title alignment -function onAlignClicked(direction) { - if (!VisualCreatorShowcaseState.visual) - return; - - $(".alignment-block").removeClass("selected"); - $("#align-" + direction).addClass("selected"); - VisualCreatorShowcaseState.properties['titleAlign'] = direction; - - // Setting the property on the visual - VisualCreatorShowcaseState.visual.setProperty(propertyToSelector('titleAlign'), { schema: schemas.property, value: direction }); -} - -// Convert property name to selector -function propertyToSelector(propertyName) { - switch (propertyName) { - case 'title': - return { objectName: "title", propertyName: "visible" }; - case 'xAxis': - return { objectName: "categoryAxis", propertyName: "visible" }; - case 'yAxis': - return { objectName: "valueAxis", propertyName: "visible" }; - case 'legend': - return { objectName: "legend", propertyName: "visible" }; - case 'titleText': - return { objectName: "title", propertyName: "titleText" }; - case 'titleAlign': - return { objectName: "title", propertyName: "alignment" }; - case 'titleSize': - return { objectName: "title", propertyName: "textSize" }; - case 'titleColor': - return { objectName: "title", propertyName: "fontColor" }; - } -} - -// Handles erase tool click -function onEraseToolClicked() { - if (!VisualCreatorShowcaseState.visual) - return; - - document.getElementById("ptitle").value = ""; - - // Reseting the title text to auto generated - VisualCreatorShowcaseState.visual.resetProperty(propertyToSelector('titleText')); -} - -// Update the title's text -function updateTitleText() { - if (!VisualCreatorShowcaseState.visual) - return; - - let text = document.getElementById("ptitle").value; - - // If the title is blank, reseting the title to auto generated - if (text === "") { - onEraseToolClicked(); - return; - } - - VisualCreatorShowcaseState.visual.setProperty(propertyToSelector('titleText'), { schema: schemas.property, value: text }); -} - -// Reset the data roles section -function resetGeneratorDataRoles() { - if (!VisualCreatorShowcaseState.visual) - return; - - VisualCreatorShowcaseState.dataRoles = { - Legend: null, - Values: null, - Value: null, - Axis: null, - Tooltips: null, - 'Y Axis': null, - Category: null, - Breakdown: null, - }; - - VisualCreatorShowcaseState.dataFieldsCount = 0; - - let nodesToReset = $('.select-selected').slice(1); //all dropdowns except of visual type selection - for (let i = 0; i < nodesToReset.length; i++) { - nodesToReset[i].innerHTML = 'Select an option'; - } - - $('.field ~ .select-items').children().show(); - $('.field ~ .select-items').children().removeClass('same-as-selected'); -} - -// Reset the current visual -function resetGeneratorVisual() { - if (!VisualCreatorShowcaseState.visual) - return; - - VisualCreatorShowcaseState.page.deleteVisual(VisualCreatorShowcaseState.visual.name); - VisualCreatorShowcaseState.visual = null; - VisualCreatorShowcaseState.visualType = null; - $('.select-selected')[0].innerHTML = 'Select an option'; - $('#visual-type ~ .select-items > .same-as-selected').show(); - $('#visual-type ~ .select-items > .same-as-selected')[0].removeAttribute('class'); -} - -// Reset the properties section -function resetGeneratorProperties() { - if (!VisualCreatorShowcaseState.visual) - return; - - VisualCreatorShowcaseState.properties = { - legend: true, - xAxis: true, - yAxis: true, - title: true, - titleText: null, - titleAlign: null - }; - - for (let i = 0; i < 4; i++) { - $('input[type="checkbox"]')[i].checked = true; - } - - $(".alignment-block").removeClass("selected"); - $("#align-left").addClass("selected"); - - document.getElementById("ptitle").value = ""; -} - -// Reset the visual generator (data roles, properties and visual) -function resetVisualGenerator() { - if (!VisualCreatorShowcaseState.visual) - return; - - $('#generator-fields').addClass(disabledClass); - $('#generator-properties').addClass(disabledClass); - - $('#overlay-embed-container').text('Start by choosing the visual type'); - $("#overlay-embed-container").show(); - - resetGeneratorDataRoles(); - resetGeneratorProperties(); - resetGeneratorVisual(); -} - -// Validate the existance of each dataRole on the visual's capabilities -function validateDataRoles(capabilities, dataRolesDisplayNames) { - for (let i = 0; i < dataRolesDisplayNames.length; i++) { - - // Filter the corrsponding dataRole in the visual's capabilities dataRoles - if (capabilities.dataRoles.filter(function (dr) { return dr.displayName === dataRolesDisplayNames[i] }).length === 0) { - return false; - } - } - - return true; -} - -// Show an error message on dataRoles validation failure -function handleInvalidDataRoles() { - - // Update the overlay text - $('#overlay-embed-container').text("Failed to validate the visual's dataRoles. Please select a different visual type to continue."); - $('#overlay-embed-container').show(); -} - diff --git a/demo/v2-demo/live_showcases/themes/showcase_themes.html b/demo/v2-demo/live_showcases/themes/showcase_themes.html deleted file mode 100644 index 941bef94..00000000 --- a/demo/v2-demo/live_showcases/themes/showcase_themes.html +++ /dev/null @@ -1,43 +0,0 @@ -
-

Personalize report design

-
-
- You can personalize the colors and styling of your embedded analytics using the themes API.
- Themes help define styling and colors so you can match them to your application or brand color palette, for example.
- With the themes API, you can apply a custom theme during the report load or during a session.
- In this showcase, we’ve provided a few example color palettes and styles so you can see how themes can be applied to user report views.
-
- -
- -
-
-
Data colors
-
-
-
-
-
Background
-
-
-
-
-
-
-
Embedded view
-
-
-
-
-
- - \ No newline at end of file diff --git a/demo/v2-demo/live_showcases/themes/showcase_themes.js b/demo/v2-demo/live_showcases/themes/showcase_themes.js deleted file mode 100644 index f1c204ce..00000000 --- a/demo/v2-demo/live_showcases/themes/showcase_themes.js +++ /dev/null @@ -1,252 +0,0 @@ - - -let ThemesShowcaseState = { - themesArray: null, - themesReport: null, - dataColorSize: 16, - backgroundSize: 16, -}; - -// For report themes documentation please check https://docs.microsoft.com/en-us/power-bi/desktop-report-themes -const jsonThemes = [ - { - "name": "Apothecary", - "dataColors": ["#93A299", "#CF543F", "#B5AE53", "#848058", "#E8B54D", "#786C71", "#93A2A0", "#CF9A3F", "#8CB553", "#728458", "#D0E84D", "#786D6C"], - "background":"#FFFFFF", - "foreground": "#CF543F", - "tableAccent": "#93A299" - }, - { - "name": "Colorblind Safe", - "dataColors": ["#074650", "#009292", "#fe6db6", "#feb5da", "#480091", "#b66dff", "#b5dafe", "#6db6ff", "#914800", "#23fd23"], - "background":"#FFFFFF", - "foreground": "#074650", - "tableAccent": "#fe6db6" - }, - { - "name": "Valentine's Day", - "dataColors": ["#990011", "#cc1144", "#ee7799", "#eebbcc", "#cc4477", "#cc5555", "#882222", "#A30E33"], - "background":"#FFFFFF", - "foreground": "#ee7799", - "tableAccent": "#990011" - }, - { - "name": "Waveform", - "dataColors": ["#31B6FD", "#4584D3", "#5BD078", "#A5D028", "#F5C040", "#05E0DB", "#3153FD", "#4C45D3", "#5BD0B0", "#54D028", "#D0F540", "#057BE0"], - "background":"#FFFFFF", - "foreground": "#4584D3", - "tableAccent": "#31B6FD" - }, -]; - -const backgrounds = [ - { - "background": "#FFFFFF", - }, - { - "background": "#323130", - "foreground": "#FFFFFF", - "tableAccent": "#FFFFFF", - "visualStyles": { - "*":{ - "*":{ - "*":[{ - "fontFamily":"Segoe UI", - "color":{"solid":{"color":"#323130"}}, - "labelColor":{"solid":{"color":"#FFFFFF"}}, - "titleColor":{"solid":{"color":"#FFFFFF"}}, - }], - "labels":[{ - "color":{"solid":{"color":"#FFFFFF"}} - }], - "categoryLabels":[{ - "color":{"solid":{"color":"#FFFFFF"}} - }] - } - } - } - } -] - -// Embed the report -function embedThemesReport() { - - // Load sample report properties into session - return LoadThemesShowcaseReportIntoSession().then(function () { - - // Get models. models contains enums that can be used - const models = window['powerbi-client'].models; - - // Get embed application token from session - let accessToken = GetSession(SessionKeys.AccessToken); - - // Get embed URL from session - let embedUrl = GetSession(SessionKeys.EmbedUrl); - - // Get report Id from session - let embedReportId = GetSession(SessionKeys.EmbedId); - - // Use View permissions - let permissions = models.Permissions.View; - - // Embed configuration used to describe the what and how to embed - // This object is used when calling powerbi.embed - // This also includes settings and options such as filters - // You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details - let config= { - type: 'report', - tokenType: models.TokenType.Embed, - accessToken: accessToken, - embedUrl: embedUrl, - id: embedReportId, - permissions: permissions, - settings: { - filterPaneEnabled: false, - navContentPaneEnabled: false, - }, - - // Adding theme attribute to the config, will apply the theme on load - theme: {themeJson: jsonThemes[0]}, - }; - - // Get a reference to the embedded report HTML element - let embedContainer = $('#embedContainer')[0]; - - // Embed the report and display it within the div container - ThemesShowcaseState.themesReport = powerbi.embed(embedContainer, config); - - // Report.on will add an event handler for report loaded event - ThemesShowcaseState.themesReport.on("loaded", function() { - let themesList = $('#themesList'); - - // Set the first theme on the list as active - themesList.find("#theme0").attr('checked', true); - - // Displaying the themes list and the backgrounds list - themesList.show(); - $('#backgroundsList').show(); - $('#background0', '#backgroundsList').addClass("selected"); - }); - }); -} - -// Apply clicked theme and set it as the active theme on the list -function onThemeClicked(element) { - - // Set the clicked theme as active - $(element).attr('checked', true); - - applyTheme(); -} - -// Apply clicked background and set it as the active background on the list -function setThemeBackgroundActive(id) { - - // Set the clicked background as active - $('.themeBackgroundColor').removeClass("selected"); - $('#background' + id, '#backgroundsList').addClass("selected"); - - applyTheme(); -} - -function applyTheme() { - // Get active theme id - activeThemeId = Number($('input[name=theme]:checked', '#themesList')[0].getAttribute("id").slice(-1)); - activeBackgroundId = Number($('.selected', '#backgroundsList')[0].getAttribute("id").slice(-1)); - theme = {} - $.extend(theme, jsonThemes[activeThemeId], backgrounds[activeBackgroundId]); - - // Apply the theme - let report = ThemesShowcaseState.themesReport; - report.applyTheme({themeJson: theme}); -} - -// Create a themes list -function createThemesList() { - - // Build the themes list HTML code - let themesList = $('#themesList'); - - // Hide the div until the report loads - themesList.hide(); - - // Building the themes list - for (let i = 0; i < jsonThemes.length; i++) { - themesList.append(buildThemeElement(i)); - } -} - -// Create a backgrounds list -function createBackgroundsList() { - - // Build the backgrounds list HTML code - let backgroundsList = $('#backgroundsList'); - - // Hide the div until the report loads - backgroundsList.hide(); - - // Building the themes list - for (let i = 0; i < backgrounds.length; i++) { - backgroundsList.append(buildBackgroundElement(i)); - } -} - -// Build theme radio button HTML element -function buildThemeElement(id) { - let labelElement = document.createElement("label"); - labelElement.setAttribute("class", "showcaseRadioContainer themesRadioContainer"); - - let inputElement = document.createElement("input"); - inputElement.setAttribute("type", "radio"); - inputElement.setAttribute("name", "theme"); - inputElement.setAttribute("id", 'theme' + id); - inputElement.setAttribute("onclick", "onThemeClicked(this);"); - labelElement.appendChild(inputElement); - - let spanElement = document.createElement("span"); - spanElement.setAttribute("class", "showcaseRadioCheckmark"); - labelElement.appendChild(spanElement); - - let secondSpanElement = document.createElement("span"); - secondSpanElement.setAttribute("class", "radioTitle"); - let radioTitleElement = document.createTextNode(jsonThemes[id].name); - secondSpanElement.appendChild(radioTitleElement); - labelElement.appendChild(secondSpanElement); - - let colorsDivElement = document.createElement("div"); - colorsDivElement.setAttribute("class","themeColors"); - - // Calculate the max width for displaying data colors - const maxWidth = document.getElementById('themesDataColorsWrapper').offsetWidth - 48 /*padding*/; - const dataColors = jsonThemes[id].dataColors; - const singleDataColorWidth = ThemesShowcaseState.dataColorSize + 3 /*margin*/; - let currentWidth = 0; - for (let i = 0; i < dataColors.length; i++) { - - // Verify that the data colors will not overflow - if (currentWidth + singleDataColorWidth > maxWidth) - break; - - let dataColorElement = document.createElement("img"); - let url = "https://placehold.it/" + ThemesShowcaseState.dataColorSize + "/" + dataColors[i].substr(1) + "/000000?text=+"; - dataColorElement.setAttribute("src", url); - dataColorElement.setAttribute("class", "themeDataColor"); - colorsDivElement.appendChild(dataColorElement); - currentWidth += singleDataColorWidth; - } - - labelElement.appendChild(colorsDivElement); - - return labelElement; -} - -// Build background HTML element -function buildBackgroundElement(id) { - let backgroundElement = document.createElement("img"); - let url = "https://placehold.it/" + ThemesShowcaseState.backgroundSize + "/" + backgrounds[id].background.substr(1) + "/000000?text=+"; - backgroundElement.setAttribute("src", url); - backgroundElement.setAttribute("class", "themeBackgroundColor"); - backgroundElement.setAttribute("id", 'background' + id); - backgroundElement.setAttribute("onclick", "setThemeBackgroundActive(" + id + ");"); - return backgroundElement; -} diff --git a/demo/v2-demo/log_window.html b/demo/v2-demo/log_window.html deleted file mode 100644 index 1f1f56c7..00000000 --- a/demo/v2-demo/log_window.html +++ /dev/null @@ -1,14 +0,0 @@ -
-
Log
-
- - -
-
-