├── .gitignore ├── BRK3062 - Developing with Power BI Embedding.pdf ├── BRK3062 - Developing with Power BI Embedding.pptx ├── Demos ├── AppOwnsDataApp │ ├── AppOwnsDataApp.sln │ └── AppOwnsDataApp │ │ ├── AppOwnsDataApp.csproj │ │ ├── App_Start │ │ └── RouteConfig.cs │ │ ├── Content │ │ ├── Site.css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ ├── bootstrap.min.css.map │ │ └── img │ │ │ └── background.jpg │ │ ├── Controllers │ │ └── HomeController.cs │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── Models │ │ ├── MvcViewModels.cs │ │ └── PbiEmbeddingManager.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── Scripts │ │ ├── README.md │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ ├── bootstrap.min.js.map │ │ ├── esm │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── index.d.ts │ │ ├── jquery-3.4.1.intellisense.js │ │ ├── jquery-3.4.1.js │ │ ├── jquery-3.4.1.min.js │ │ ├── jquery-3.4.1.min.map │ │ ├── jquery-3.4.1.slim.js │ │ ├── jquery-3.4.1.slim.min.js │ │ ├── jquery-3.4.1.slim.min.map │ │ ├── modernizr-2.6.2.js │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ ├── popper.min.js.map │ │ ├── powerbi.js │ │ ├── powerbi.js.map │ │ ├── powerbi.min.js │ │ └── umd │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── Views │ │ ├── Home │ │ │ ├── Dashboard.cshtml │ │ │ ├── Index.cshtml │ │ │ ├── NewReport.cshtml │ │ │ ├── Qna.cshtml │ │ │ ├── Report.cshtml │ │ │ └── Reports.cshtml │ │ ├── Shared │ │ │ └── _Layout.cshtml │ │ ├── _ViewStart.cshtml │ │ └── web.config │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ ├── favicon.ico │ │ └── packages.config ├── PowerBiDaySPA │ ├── .vscode │ │ └── launch.json │ ├── npm-shrinkwrap.json │ ├── package.json │ ├── src │ │ ├── AppSettings.ts │ │ ├── components │ │ │ ├── App.css │ │ │ ├── App.tsx │ │ │ ├── Banner.css │ │ │ ├── Banner.tsx │ │ │ ├── Login.css │ │ │ ├── Login.tsx │ │ │ ├── TopNav.css │ │ │ ├── TopNav.tsx │ │ │ ├── ViewDashboards │ │ │ │ ├── EmbeddedDashboard.tsx │ │ │ │ └── ViewDashboards.tsx │ │ │ ├── ViewDatasets │ │ │ │ ├── EmbeddedNewReport.tsx │ │ │ │ └── ViewDatasets.tsx │ │ │ ├── ViewHome │ │ │ │ ├── ViewHome.css │ │ │ │ └── ViewHome.tsx │ │ │ └── ViewReports │ │ │ │ ├── EmbeddedReport.tsx │ │ │ │ ├── EmbeddedReportToolbar.css │ │ │ │ ├── EmbeddedReportToolbar.tsx │ │ │ │ └── ViewReports.tsx │ │ ├── favicon.ico │ │ ├── images │ │ │ └── AppIcon.png │ │ ├── index.html │ │ ├── index.tsx │ │ ├── models │ │ │ ├── IUser.ts │ │ │ └── PowerBiModels.ts │ │ └── services │ │ │ ├── PowerBiEmbeddingService.ts │ │ │ ├── PowerBiService.ts │ │ │ └── SpaAuthService.ts │ ├── tsconfig.json │ └── webpack.config.js ├── PowerBiEmbeddedScratchpad │ ├── PowerBiEmbeddedScratchpad.sln │ └── PowerBiEmbeddedScratchpad │ │ ├── App.config │ │ ├── Models │ │ ├── EmbeddingDataModels.cs │ │ ├── PageGenerator.cs │ │ └── PbiEmbeddedManager.cs │ │ ├── PageTemplates │ │ ├── EmbedDashboard.html │ │ ├── EmbedDashboardTile.html │ │ ├── EmbedNewReport.html │ │ ├── EmbedNewReportWithSaveAsRedirect.html │ │ ├── EmbedQna.html │ │ ├── EmbedReport.html │ │ ├── EmbedReportVisual.html │ │ ├── EmbedReportWithBookmarkCarousel.html │ │ ├── EmbedReportWithBookmarks.html │ │ ├── EmbedReportWithConfigurationOptions.html │ │ ├── EmbedReportWithContextMenus.html │ │ ├── EmbedReportWithCustomFiltering.html │ │ ├── EmbedReportWithFirstPartyToken.html │ │ ├── EmbedReportWithPageNavigation.html │ │ ├── EmbedReportWithPhasedLoading.html │ │ ├── EmbedReportWithRLS.html │ │ ├── EmbedReportWithToolbar.html │ │ ├── ReportInspector.html │ │ ├── app.css │ │ └── img │ │ │ ├── AppIcon_png │ │ │ ├── favicon_ico │ │ │ ├── loading2_gif │ │ │ ├── loading3_gif │ │ │ └── loading_gif │ │ ├── PowerBiEmbeddedScratchpad.csproj │ │ ├── Program.cs │ │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ │ ├── Scripts │ │ ├── jquery-3.3.1.js │ │ └── powerbi.js │ │ └── packages.config ├── RowLevelSecurityDemo │ ├── RowLevelSecurityDemo.sln │ └── RowLevelSecurityDemo │ │ ├── App_Start │ │ ├── IdentityConfig.cs │ │ ├── RouteConfig.cs │ │ └── Startup.Auth.cs │ │ ├── Content │ │ ├── Site.css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── Controllers │ │ ├── AccountController.cs │ │ ├── HomeController.cs │ │ └── ReportsController.cs │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── Models │ │ ├── IdentityModels.cs │ │ ├── MvcViewModels.cs │ │ ├── PbiEmbeddedManager.cs │ │ └── PbiEmbeddingModels.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── RowLevelSecurityDemo.csproj │ │ ├── Scripts │ │ ├── README.md │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ ├── bootstrap.min.js.map │ │ ├── esm │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── index.d.ts │ │ ├── jquery-3.3.1.intellisense.js │ │ ├── jquery-3.3.1.js │ │ ├── jquery-3.3.1.min.js │ │ ├── jquery-3.3.1.min.map │ │ ├── jquery-3.3.1.slim.js │ │ ├── jquery-3.3.1.slim.min.js │ │ ├── jquery-3.3.1.slim.min.map │ │ ├── modernizr-2.6.2.js │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ ├── popper.min.js.map │ │ ├── powerbi.js │ │ ├── powerbi.js.map │ │ ├── powerbi.min.js │ │ └── umd │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── Startup.cs │ │ ├── Views │ │ ├── Account │ │ │ └── Login.cshtml │ │ ├── Home │ │ │ ├── Index.cshtml │ │ │ └── UserInfo.cshtml │ │ ├── Reports │ │ │ ├── Index.cshtml │ │ │ ├── ReportByRole.cshtml │ │ │ └── ReportByState.cshtml │ │ ├── Shared │ │ │ ├── _Layout.cshtml │ │ │ └── _LoginPartial.cshtml │ │ ├── _ViewStart.cshtml │ │ └── web.config │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ └── packages.config ├── ThirdPartyEmbeddingDemo │ ├── ThirdPartyEmbeddingDemo.sln │ └── ThirdPartyEmbeddingDemo │ │ ├── App_Start │ │ ├── IdentityConfig.cs │ │ ├── RouteConfig.cs │ │ └── Startup.Auth.cs │ │ ├── Certificates │ │ ├── AppCert1.cer │ │ └── AppCert1.json.txt │ │ ├── Content │ │ ├── Site.css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── Controllers │ │ ├── AccountController.cs │ │ ├── HomeController.cs │ │ └── ReportsController.cs │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── Models │ │ ├── IdentityModels.cs │ │ ├── MvcViewModels.cs │ │ ├── PbiEmbeddedManager.cs │ │ └── PbiEmbeddingModels.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── Startup.cs │ │ ├── ThirdPartyEmbeddingDemo.csproj │ │ ├── Views │ │ ├── Account │ │ │ └── Login.cshtml │ │ ├── Home │ │ │ ├── Index.cshtml │ │ │ └── UserInfo.cshtml │ │ ├── Reports │ │ │ └── Index.cshtml │ │ ├── Shared │ │ │ ├── _Layout.cshtml │ │ │ └── _LoginPartial.cshtml │ │ ├── _ViewStart.cshtml │ │ └── web.config │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ ├── packages.config │ │ └── scripts │ │ ├── README.md │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ ├── bootstrap.min.js.map │ │ ├── esm │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ └── popper.min.js.map │ │ ├── index.d.ts │ │ ├── jquery-3.3.1.intellisense.js │ │ ├── jquery-3.3.1.js │ │ ├── jquery-3.3.1.min.js │ │ ├── jquery-3.3.1.min.map │ │ ├── jquery-3.3.1.slim.js │ │ ├── jquery-3.3.1.slim.min.js │ │ ├── jquery-3.3.1.slim.min.map │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ ├── popper.min.js.map │ │ ├── powerbi.js │ │ ├── powerbi.js.map │ │ ├── powerbi.min.js │ │ └── umd │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ └── popper.min.js.map └── UserOwsDataConsumerApp │ ├── .vscode │ └── launch.json │ ├── npm-shrinkwrap.json │ ├── package.json │ ├── src │ ├── AppSettings.ts │ ├── components │ │ ├── App.css │ │ ├── App.tsx │ │ ├── Banner.css │ │ ├── Banner.tsx │ │ ├── Login.css │ │ ├── Login.tsx │ │ ├── TopNav.css │ │ ├── TopNav.tsx │ │ ├── ViewDashboards │ │ │ ├── EmbeddedDashboard.tsx │ │ │ └── ViewDashboards.tsx │ │ ├── ViewHome │ │ │ ├── ViewHome.css │ │ │ └── ViewHome.tsx │ │ └── ViewReports │ │ │ ├── EmbeddedReport.tsx │ │ │ ├── EmbeddedReportToolbar.css │ │ │ ├── EmbeddedReportToolbar.tsx │ │ │ └── ViewReports.tsx │ ├── favicon.ico │ ├── images │ │ └── AppIcon.png │ ├── index.html │ ├── index.tsx │ ├── models │ │ ├── IUser.ts │ │ └── PowerBiModels.ts │ └── services │ │ ├── PowerBiEmbeddingService.ts │ │ ├── PowerBiService.ts │ │ └── SpaAuthService.ts │ ├── tsconfig.json │ └── webpack.config.js ├── LICENSE ├── PBIX ├── Northwind Retro.pbix ├── Wingtip Sales Analysis with RLS.pbix ├── Wingtip Sales Analysis.pbix └── Wingtip Sales DirectQuery.pbix ├── Presentations ├── DeveloperQuickStartIntoPowerBIEmbedding.pdf ├── Power BI Embedded - April 2018 - Summit in Dublin .pptx ├── Power BI Embedded - December 2017.pptx ├── PowerBiEmbedding_MBAS_July2018.pdf ├── PowerBiEmbedding_MBAS_July2018.pptx └── PowerBiEmbedding_Oct2018.pptx ├── README.md └── Scripts ├── AppOwnsDataApp.txt ├── CreateADGroupForPowerBiApps.ps1 ├── DisplayPowerBiAPiPermissions.ps1 ├── MyAzureADApp.txt ├── PowerBiServicePermissions.txt ├── RegisterAppOwnsDataApp.ps1 └── RegisterPowerBIDaySPA.ps1 /BRK3062 - Developing with Power BI Embedding.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/BRK3062 - Developing with Power BI Embedding.pdf -------------------------------------------------------------------------------- /BRK3062 - Developing with Power BI Embedding.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/BRK3062 - Developing with Power BI Embedding.pptx -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.572 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppOwnsDataApp", "AppOwnsDataApp\AppOwnsDataApp.csproj", "{49B2A2BA-496A-40D5-B4B8-ABDCD598271A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {49B2A2BA-496A-40D5-B4B8-ABDCD598271A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {49B2A2BA-496A-40D5-B4B8-ABDCD598271A}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {49B2A2BA-496A-40D5-B4B8-ABDCD598271A}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {49B2A2BA-496A-40D5-B4B8-ABDCD598271A}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B9EED8DB-16E2-40B9-ADFC-F669C9DE3331} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace AppOwnsDataApp 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-image: url(img/background.jpg); 3 | background-size: auto; 4 | background-repeat: round; 5 | } 6 | 7 | #banner { 8 | padding-left: 0px; 9 | padding-right: 0px; 10 | } 11 | 12 | #topnav { 13 | background-color: #000 !important; 14 | } 15 | 16 | .navbar-dark .navbar-nav .active > .nav-link { 17 | color: #FFC; 18 | } 19 | 20 | .navbar-dark .navbar-nav .nav-link { 21 | color: #F2C811; 22 | } 23 | 24 | .navbar-dark .navbar-nav .nav-link:hover { 25 | color: orange; 26 | } 27 | 28 | 29 | #toolbar { 30 | background-color: #666 !important; 31 | border-bottom: 1px solid #333; 32 | } 33 | 34 | #toolbar button { 35 | margin: 4px; 36 | font-size: 9px; 37 | font-weight: bold; 38 | padding: 2px; 39 | color: #222; 40 | background-color: #F2C811; 41 | border-color: #111; 42 | width: 92px; 43 | } 44 | 45 | 46 | #content-box { 47 | padding: 0px; 48 | background-color: #FFF; 49 | } 50 | 51 | #homePageContainer { 52 | padding: 24px; 53 | } 54 | 55 | 56 | .jumbotron { 57 | background-color: #FFFFF1; 58 | border: 1px solid #AAA; 59 | } 60 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Content/img/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/AppOwnsDataApp/AppOwnsDataApp/Content/img/background.jpg -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Web; 6 | using System.Web.Mvc; 7 | using AppOwnsDataApp.Models; 8 | 9 | namespace AppOwnsDataApp.Controllers { 10 | public class HomeController : Controller { 11 | 12 | public ActionResult Index() { 13 | return View(); 14 | } 15 | 16 | public async Task Report() { 17 | ReportEmbeddingData embeddingData = await PbiEmbeddingManager.GetReportEmbeddingData(); 18 | return View(embeddingData); 19 | } 20 | 21 | public async Task Dashboard() { 22 | DashboardEmbeddingData embeddingData = await PbiEmbeddingManager.GetDashboardEmbeddingData(); 23 | return View(embeddingData); 24 | } 25 | 26 | public async Task Qna() { 27 | QnaEmbeddingData embeddingData = await PbiEmbeddingManager.GetQnaEmbeddingData(); 28 | return View(embeddingData); 29 | } 30 | 31 | public async Task NewReport() { 32 | NewReportEmbeddingData embeddingData = await PbiEmbeddingManager.GetNewReportEmbeddingData(); 33 | return View(embeddingData); 34 | } 35 | 36 | public async Task Reports(string reportId) { 37 | 38 | ReportEmbeddingData embeddingData = 39 | await PbiEmbeddingManager.GetEmbeddingDataForReport(reportId); 40 | 41 | return View(embeddingData); 42 | } 43 | 44 | 45 | 46 | } 47 | } -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="AppOwnsDataApp.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace AppOwnsDataApp 9 | { 10 | public class MvcApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | AreaRegistration.RegisterAllAreas(); 15 | RouteConfig.RegisterRoutes(RouteTable.Routes); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Models/MvcViewModels.cs: -------------------------------------------------------------------------------- 1 | namespace AppOwnsDataApp.Models { 2 | 3 | // data required for embedding a report 4 | public class ReportEmbeddingData { 5 | public string reportId; 6 | public string reportName; 7 | public string embedUrl; 8 | public string accessToken; 9 | } 10 | 11 | // data required for embedding a new report 12 | public class NewReportEmbeddingData { 13 | public string workspaceId; 14 | public string datasetId; 15 | public string embedUrl; 16 | public string accessToken; 17 | } 18 | 19 | // data required for embedding a dashboard 20 | public class DashboardEmbeddingData { 21 | public string dashboardId; 22 | public string dashboardName; 23 | public string embedUrl; 24 | public string accessToken; 25 | } 26 | 27 | // data required for embedding a dashboard 28 | public class QnaEmbeddingData { 29 | public string datasetId; 30 | public string embedUrl; 31 | public string accessToken; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AppOwnsDataApp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AppOwnsDataApp")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("49b2a2ba-496a-40d5-b4b8-abdcd598271a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/Home/Dashboard.cshtml: -------------------------------------------------------------------------------- 1 | @model AppOwnsDataApp.Models.DashboardEmbeddingData 2 | 3 |
4 | 5 | 6 | 32 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 | 3 |
4 |

Welcome to the App-Owns-Data App

5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/Home/NewReport.cshtml: -------------------------------------------------------------------------------- 1 | @model AppOwnsDataApp.Models.NewReportEmbeddingData 2 | 3 |
4 | 5 | 6 | 38 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/Home/Qna.cshtml: -------------------------------------------------------------------------------- 1 | @model AppOwnsDataApp.Models.QnaEmbeddingData 2 | 3 |
4 | 5 | 6 | 33 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/Home/Report.cshtml: -------------------------------------------------------------------------------- 1 | @model AppOwnsDataApp.Models.ReportEmbeddingData 2 | 3 |
4 | 5 | @section toolbar { 6 | 11 | } 12 | 13 | 14 | 15 | 68 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/Home/Reports.cshtml: -------------------------------------------------------------------------------- 1 | @model AppOwnsDataApp.Models.ReportEmbeddingData 2 | 3 | @section toolbar { 4 | 9 | } 10 | 11 |
12 | 13 | 14 | 15 | 16 | 68 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | App-Owns-Data App 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 44 | 45 |
46 | @RenderBody() 47 |
48 | 49 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Views/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/AppOwnsDataApp/AppOwnsDataApp/favicon.ico -------------------------------------------------------------------------------- /Demos/AppOwnsDataApp/AppOwnsDataApp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "chrome", 9 | "request": "launch", 10 | "name": "Launch Chrome", 11 | "url": "http://localhost:8080", 12 | "webRoot": "${workspaceFolder}" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "power-bi-day-spa", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "start": "webpack-dev-server --open --history-api-fallback" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@types/react": "^16.4.18", 15 | "@types/react-dom": "^16.0.9", 16 | "@types/react-router": "^4.4.0", 17 | "@types/react-router-dom": "^4.3.1", 18 | "awesome-typescript-loader": "^5.2.1", 19 | "bootstrap": "^4.1.3", 20 | "clean-webpack-plugin": "^0.1.19", 21 | "copy-webpack-plugin": "^4.6.0", 22 | "css-loader": "^0.28.11", 23 | "expose-loader": "^0.7.5", 24 | "file-loader": "^1.1.11", 25 | "html-webpack-plugin": "^3.2.0", 26 | "jquery": "^3.3.1", 27 | "msal": "^1.0.1", 28 | "popper.js": "^1.14.4", 29 | "powerbi-client": "^2.7.4", 30 | "react": "^16.6.0", 31 | "react-dom": "^16.6.0", 32 | "react-router": "^4.3.1", 33 | "react-router-dom": "^4.3.1", 34 | "style-loader": "^0.21.0", 35 | "typescript": "^3.1.6", 36 | "url-loader": "^1.1.2", 37 | "webpack": "^4.24.0", 38 | "webpack-cli": "^3.1.2", 39 | "webpack-dev-server": "^3.1.10" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/AppSettings.ts: -------------------------------------------------------------------------------- 1 | export default class AppSettings { 2 | static aadTenant: string = "MY_TENANT.onMicrosoft.com"; 3 | static clientId: string = ""; 4 | static appWorkspaceId: string = ""; 5 | } -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | padding: 0px; 4 | background-color: orange; 5 | font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif 6 | } 7 | 8 | #left-nav-col { 9 | padding-left: 0; 10 | padding-right: 0; 11 | } 12 | 13 | #content-col { 14 | padding-left: 0; 15 | padding-right: 0; 16 | 17 | } 18 | 19 | #page-container{ 20 | background-color: white; 21 | min-height: 600px; 22 | border-bottom-left-radius: 8px; 23 | border-bottom-right-radius: 8px; 24 | border: 1px solid black; 25 | } 26 | 27 | #embed-container { 28 | height: 600px; 29 | min-height: 600px;; 30 | } 31 | 32 | .content-body { 33 | padding: 24px; 34 | } 35 | 36 | .message-body { 37 | padding-top: 18px; 38 | padding-left: 32px; 39 | font-size: 1.75em; 40 | color: #CCC; 41 | } 42 | 43 | .jumbotron { 44 | padding-top: 18px; 45 | padding-bottom: 16px; 46 | } 47 | 48 | #left-nav { 49 | padding: 8px; 50 | width: 100%; 51 | float: left; 52 | background-color: #EEE; 53 | border: 1px solid #999; 54 | border-bottom-right-radius: 8px; 55 | } 56 | 57 | #left-nav-header { 58 | color: darkblue; 59 | font-size: 14px; 60 | font-weight: bold; 61 | border-bottom: 1px solid darkblue; 62 | margin-bottom: 4px; 63 | } 64 | 65 | #left-nav ul { 66 | padding: 0px; 67 | margin: 0px; 68 | list-style-type: none; 69 | } 70 | 71 | #left-nav li { 72 | border: 0px; 73 | margin: 0px; 74 | } 75 | 76 | #left-nav a, 77 | #left-nav a:hover, 78 | #left-nav a:visited 79 | { 80 | margin: 2px; 81 | padding: 0; 82 | color: black; 83 | font-size: 12px; 84 | font-weight: bold; 85 | text-decoration: none; 86 | } 87 | 88 | 89 | 90 | #left-nav:empty { 91 | display: none; 92 | background-color: red; 93 | } 94 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/Banner.css: -------------------------------------------------------------------------------- 1 | #banner { 2 | padding: 0px; 3 | color: white; 4 | border-bottom: 1px solid black; 5 | } 6 | 7 | #app-icon { 8 | float: left; 9 | height: 47px; 10 | width: 47px; 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | background-image: url('./../images/AppIcon.png') 15 | } 16 | 17 | #app-title { 18 | color: white; 19 | float: left; 20 | display: flex; 21 | align-items: center; 22 | height: 48px; 23 | padding-left: 12px; 24 | font-size: 18px; 25 | } -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/Banner.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Link, NavLink } from 'react-router-dom'; 3 | 4 | import './Banner.css'; 5 | 6 | interface BannerProperties { 7 | appTitle: string; 8 | } 9 | 10 | export default class Banner extends React.Component { 11 | render() { 12 | return ( 13 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/Login.css: -------------------------------------------------------------------------------- 1 | #login { 2 | height: 48px; 3 | float: right; 4 | display: flex; 5 | align-items: center; 6 | padding-top: 6px; 7 | padding-right: 16px; 8 | } 9 | 10 | #login ul { 11 | line-height: 1em; 12 | padding-left: 24px; 13 | margin-bottom: 0; 14 | } 15 | 16 | 17 | #login ul li { 18 | display: inline-block; 19 | margin-right: 16px; 20 | color: #FEBF0F; 21 | } 22 | 23 | #login li a, 24 | #login li a:visited, 25 | #login li a:active{ 26 | color: #FEBF0F; 27 | text-decoration: none; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/Login.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import IUser from "./../models/IUser" 3 | import "./Login.css"; 4 | 5 | interface LoginProperties { 6 | user: IUser; 7 | } 8 | 9 | export default class Login extends React.Component { 10 | 11 | render() { 12 | return ( 13 |
14 | {this.props.user.IsAuthenticated ?
Hello {this.props.user.DisplayName}
: null} 15 |
    16 | {this.props.user.IsAuthenticated ? 17 |
  • Logout
  • : 18 |
  • Sign In
  • 19 | } 20 |
21 |
22 | ); 23 | } 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/TopNav.css: -------------------------------------------------------------------------------- 1 | #top-nav ul { 2 | line-height: 1em; 3 | padding-left: 24px; 4 | } 5 | 6 | #top-nav ul li { 7 | display: inline-block; 8 | margin-right: 16px; 9 | color: #FEBF0F; 10 | } 11 | 12 | #top-nav li a { 13 | color: #FEBF0F; 14 | font-size: 1.0em; 15 | text-decoration: none; 16 | } 17 | 18 | #top-nav li a.active-nav-link { 19 | color: yellow; 20 | } 21 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/TopNav.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Link, NavLink } from 'react-router-dom'; 3 | 4 | import "./TopNav.css"; 5 | 6 | export default class TopNav extends React.Component { 7 | 8 | render() { 9 | return ( 10 |
11 | 30 |
31 | ); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewDashboards/EmbeddedDashboard.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Link } from 'react-router-dom' 3 | 4 | import { PowerBiDashboard } from "./../../models/PowerBiModels"; 5 | import PowerBiEmbeddingService from "./../../services/PowerBiEmbeddingService"; 6 | 7 | interface EmbeddedDashboardProperties { 8 | dashboards: PowerBiDashboard[]; 9 | } 10 | 11 | interface EmbeddedDashboardRouteParams { 12 | id: string; 13 | } 14 | 15 | type EmbeddedDashboardPropertiesWithRouter = 16 | EmbeddedDashboardProperties & 17 | RouteComponentProps; 18 | 19 | class EmbeddedDashboard extends React.Component { 20 | 21 | render() { 22 | let dashboardIdRouteParam: string = this.props.match.params.id; 23 | let noDashboardId = (dashboardIdRouteParam === undefined); 24 | let dashboard: PowerBiDashboard | undefined = this.props.dashboards.find((dashboard: PowerBiDashboard) => dashboard.id == dashboardIdRouteParam); 25 | let badDashboardId: boolean = (dashboardIdRouteParam != "") && (dashboard === undefined) 26 | if (noDashboardId) { 27 | return ( 28 |
29 | click a report to embed it on this page 30 |
); 31 | } 32 | if (badDashboardId) { 33 | return ( 34 |
35 |
'{dashboardIdRouteParam}' is not a valid dashboard id
36 |
); 37 | } 38 | return ( 39 |
40 |
41 |
); 42 | } 43 | 44 | 45 | componentDidUpdate() { 46 | this.updateEmbeddedDashboard(); 47 | } 48 | componentDidMount() { 49 | this.updateEmbeddedDashboard(); 50 | } 51 | 52 | updateEmbeddedDashboard() { 53 | let dashboardIdRouteParam: string = this.props.match.params.id; 54 | let dashboard: PowerBiDashboard | undefined = this.props.dashboards.find((dashboard: PowerBiDashboard) => dashboard.id == dashboardIdRouteParam); 55 | if (dashboard) { 56 | var embedContainer: HTMLElement = document.getElementById('embed-container')!; 57 | PowerBiEmbeddingService.embedDashboard(dashboard!, embedContainer); 58 | } 59 | } 60 | 61 | 62 | } 63 | 64 | export default withRouter(EmbeddedDashboard); 65 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewDashboards/ViewDashboards.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Route, Switch, Link, match } from 'react-router-dom' 3 | 4 | import PowerBiService from "./../../services/PowerBiService"; 5 | 6 | import App from './../App' 7 | import EmbeddeDashboard from './EmbeddedDashboard'; 8 | 9 | import { 10 | PowerBiDashboard 11 | } from "./../../models/PowerBiModels"; 12 | import EmbeddedDashboard from './EmbeddedDashboard'; 13 | 14 | interface ViewDashboardsProperties { 15 | app: App 16 | } 17 | 18 | interface EmbeddedDashboardRouteParams { 19 | id: string; 20 | } 21 | 22 | type ViewDashboardsPropertiesWithRouter = 23 | ViewDashboardsProperties & 24 | RouteComponentProps; 25 | 26 | interface ViewDashboardsState { 27 | loadingDashboards: boolean 28 | } 29 | 30 | class ViewDashboards extends React.Component { 31 | 32 | state = { 33 | loadingDashboards: false 34 | }; 35 | 36 | render() { 37 | return ( 38 |
39 |
40 |
41 |
42 |
Embed Dashboards
43 | {this.state.loadingDashboards ?
loading...
: null} 44 | 51 |
52 |
53 |
54 | 55 |
56 |
57 |
58 | ); 59 | } 60 | 61 | 62 | componentDidMount() { 63 | this.getDashboards(); 64 | } 65 | 66 | getDashboards = () => { 67 | if (!this.props.app.state.dashboardsInCache) { 68 | this.setState({ loadingDashboards: true }); 69 | PowerBiService.GetDashboards().then((dashboards: PowerBiDashboard[]) => { 70 | this.props.app.setState({ 71 | dashboards: dashboards, 72 | dashboardsInCache: true 73 | }); 74 | this.setState({ loadingDashboards: false }); 75 | }); 76 | } 77 | } 78 | } 79 | 80 | export default withRouter(ViewDashboards); -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewDatasets/EmbeddedNewReport.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Link } from 'react-router-dom' 3 | 4 | import { PowerBiDataset } from "./../../models/PowerBiModels"; 5 | import PowerBiEmbeddingService from "./../../services/PowerBiEmbeddingService"; 6 | 7 | interface EmbeddedNewReportProperties { 8 | datasets: PowerBiDataset[] 9 | } 10 | 11 | interface EmbeddedNewReportRouteParams { 12 | id: string; 13 | } 14 | 15 | type EmbeddedNewReportPropertiesWithRouter = 16 | EmbeddedNewReportProperties & 17 | RouteComponentProps; 18 | 19 | class EmbeddedNewReport extends React.Component { 20 | render() { 21 | let datasetIdRouteParam: string = this.props.match.params.id; 22 | let noDatasetId = (datasetIdRouteParam === undefined); 23 | let dataset: PowerBiDataset | undefined = this.props.datasets.find((dataset: PowerBiDataset) => dataset.id == datasetIdRouteParam); 24 | let badDatasetId: boolean = (datasetIdRouteParam != "") && (dataset === undefined) 25 | if (noDatasetId) { 26 | return ( 27 |
28 | click dataset in left nav to create a new report 29 |
); 30 | } 31 | if (badDatasetId) { 32 | return ( 33 |
34 |
'{datasetIdRouteParam}' is not a valid dataset id
35 |
); 36 | } 37 | return ( 38 |
39 |
40 |
); 41 | } 42 | 43 | 44 | componentDidUpdate() { 45 | this.updateEmbeddedReport(); 46 | } 47 | componentDidMount() { 48 | this.updateEmbeddedReport(); 49 | } 50 | 51 | updateEmbeddedReport() { 52 | let datasetIdRouteParam: string = this.props.match.params.id; 53 | let dataset: PowerBiDataset | undefined = this.props.datasets.find((dataset: PowerBiDataset) => dataset.id == datasetIdRouteParam); 54 | if (dataset) { 55 | var embedContainer: HTMLElement = document.getElementById('embed-container')!; 56 | PowerBiEmbeddingService.embedNewReport(dataset!, embedContainer); 57 | } 58 | } 59 | } 60 | 61 | export default withRouter(EmbeddedNewReport); -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewDatasets/ViewDatasets.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Route, Switch, Link, match } from 'react-router-dom' 3 | 4 | import PowerBiService from "./../../services/PowerBiService"; 5 | 6 | import App from './../App' 7 | import EmbeddedNewReport from './EmbeddedNewReport'; 8 | 9 | import { PowerBiDataset } from "./../../models/PowerBiModels"; 10 | 11 | interface ViewDatasetsProperties { 12 | app: App 13 | } 14 | 15 | interface datasetIdRouteParams { 16 | id: string; 17 | } 18 | 19 | type ViewDatasetsPropertiesWithRouter = 20 | ViewDatasetsProperties & 21 | RouteComponentProps; 22 | 23 | interface ViewDatasetsState { 24 | loadingDatasets: boolean 25 | } 26 | 27 | class ViewDatasets extends React.Component { 28 | 29 | state = { 30 | loadingDatasets: false 31 | }; 32 | 33 | render() { 34 | return ( 35 |
36 |
37 |
38 |
39 |
Embed New Report
40 | {this.state.loadingDatasets ?
loading...
: null} 41 | 48 |
49 |
50 |
51 | 52 |
53 |
54 |
55 | ); 56 | } 57 | 58 | componentDidMount() { 59 | this.getDatasets(); 60 | } 61 | 62 | getDatasets = () => { 63 | if (!this.props.app.state.datasetsInCache) { 64 | this.setState({ loadingDatasets: true }); 65 | PowerBiService.GetDatasets().then((datasets: PowerBiDataset[]) => { 66 | this.props.app.setState({ 67 | datasets: datasets, 68 | datasetsInCache: true 69 | }); 70 | this.setState({ loadingDatasets: false }); 71 | }); 72 | } 73 | } 74 | 75 | } 76 | 77 | export default withRouter(ViewDatasets); -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewHome/ViewHome.css: -------------------------------------------------------------------------------- 1 | #view-home h4 { 2 | color: darkblue; 3 | border-bottom: 1px solid darkblue; 4 | } 5 | 6 | #view-home h4 { 7 | color: darkblue; 8 | border-bottom: 1px solid darkblue; 9 | } -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewHome/ViewHome.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './ViewHome.css'; 3 | 4 | export default class ViewHome extends React.Component { 5 | render() { 6 | return ( 7 |
8 |
9 |
10 |

React Power BI Demo App

11 |

This is a demo of a single page application (SPA) that use React.js and Power BI Embedding.

12 |
13 |
14 |
15 |
16 |

React.js is awesome

17 |
If you don't know how to develop using react.js, you should learn about this popular JavaScript library because it 18 | provides a powerful yet relatively simple way to develop single page applications with client-side behaviors. 19 |
20 |
21 |
22 |

Power BI Embedded is game changing

23 |
Learning how to develop with Power BI embedding will help you integrate professional looking reports and dashboards into your custom applications.
24 |
25 |
26 |
27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewReports/EmbeddedReport.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Link } from 'react-router-dom' 3 | 4 | import { PowerBiReport } from "./../../models/PowerBiModels"; 5 | import PowerBiEmbeddingService from "./../../services/PowerBiEmbeddingService"; 6 | 7 | import EmbeddedReportToolbar from './EmbeddedReportToolbar'; 8 | 9 | import * as powerbi from "powerbi-client"; 10 | import * as pbimodels from "powerbi-models"; 11 | 12 | interface EmbeddedReportProperties { 13 | reports: PowerBiReport[] 14 | } 15 | 16 | interface EmbeddedReportRouteParams { 17 | id: string; 18 | } 19 | 20 | type EmbeddedReportPropertiesWithRouter = 21 | EmbeddedReportProperties & 22 | RouteComponentProps; 23 | 24 | interface EmbeddedReportState { 25 | embeddedReport: powerbi.Report | undefined 26 | } 27 | 28 | class EmbeddedReport extends React.Component { 29 | 30 | state: EmbeddedReportState = { 31 | embeddedReport: undefined 32 | } 33 | 34 | render() { 35 | let reportIdRouteParam: string = this.props.match.params.id; 36 | let noReportId = (reportIdRouteParam === undefined); 37 | let report: PowerBiReport | undefined = this.props.reports.find((report: PowerBiReport) => report.id == reportIdRouteParam); 38 | let badReportId: boolean = (this.props.reports.length > 0) && (reportIdRouteParam != "") && (report === undefined) 39 | if (noReportId) { 40 | return ( 41 |
42 | click report in left nav to open it 43 |
); 44 | } 45 | if (badReportId) { 46 | return ( 47 |
48 |
'{reportIdRouteParam}' is not a valid report id
49 |
); 50 | } 51 | return ( 52 |
53 | {(this.state.embeddedReport !== undefined ? : null)} 54 |
55 |
); 56 | } 57 | 58 | 59 | componentWillUpdate() { 60 | 61 | } 62 | 63 | componentDidUpdate(previousProps: EmbeddedReportPropertiesWithRouter, PreviousState: any) { 64 | console.log("componentDidUpdate"); 65 | console.log(previousProps); 66 | console.log(this.props); 67 | let routeHasChanged: boolean = (this.props.match.params.id != previousProps.match.params.id); 68 | let reportsRefreshed = this.props.reports !== previousProps.reports; 69 | if (routeHasChanged || reportsRefreshed) { 70 | this.updateEmbeddedReport(); 71 | } 72 | } 73 | 74 | componentDidMount() { 75 | console.log("componentDidMount"); 76 | //this.updateEmbeddedReport(); 77 | } 78 | 79 | updateEmbeddedReport() { 80 | let reportIdRouteParam: string = this.props.match.params.id; 81 | let report: PowerBiReport | undefined = this.props.reports.find((report: PowerBiReport) => report.id == reportIdRouteParam); 82 | if (report) { 83 | var embedContainer: HTMLElement = document.getElementById('embed-container')!; 84 | var embeddedReport: powerbi.Report = PowerBiEmbeddingService.embedReport(report!, embedContainer); 85 | this.setState({ embeddedReport: embeddedReport }); 86 | } 87 | } 88 | } 89 | 90 | export default withRouter(EmbeddedReport); -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewReports/EmbeddedReportToolbar.css: -------------------------------------------------------------------------------- 1 | #embedded-report-toolbar{ 2 | background-color: #CCC; 3 | text-align: right; 4 | } 5 | 6 | #embedded-report-toolbar button { 7 | color: #333; 8 | border-style: none; 9 | padding: 2px; 10 | background-color: transparent; 11 | font-size: 0.7em; 12 | margin: 2px; 13 | margin-right: 8px; 14 | text-decoration: none; 15 | } 16 | 17 | 18 | #embedded-report-toolbar button:focus { 19 | outline:0; 20 | } -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewReports/EmbeddedReportToolbar.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import './EmbeddedReportToolbar.css'; 4 | 5 | import * as powerbi from "powerbi-client"; 6 | import * as pbimodels from "powerbi-models"; 7 | 8 | interface EmbeddedReportToolbarProperties { 9 | embeddedReport: powerbi.Report 10 | } 11 | 12 | export default class EmbeddedReport extends React.Component { 13 | 14 | render() { 15 | return ( 16 |
17 |
18 | 19 | 20 | 21 |
22 |
); 23 | } 24 | 25 | private viewMode = "view"; 26 | 27 | toggleReportEditMode() { 28 | this.viewMode = (this.viewMode == "view") ? "edit" : "view"; 29 | this.props.embeddedReport.switchMode(this.viewMode); 30 | // show filter pane when entering edit mode 31 | var showFilterPane = (this.viewMode == "edit"); 32 | this.props.embeddedReport.updateSettings({ 33 | "filterPaneEnabled": showFilterPane 34 | }); 35 | }; 36 | 37 | enterFullScreenMode() { 38 | this.props.embeddedReport.fullscreen(); 39 | } 40 | 41 | printReport() { 42 | this.props.embeddedReport.print(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/components/ViewReports/ViewReports.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Route, Switch, Link, match } from 'react-router-dom' 3 | 4 | import PowerBiService from "./../../services/PowerBiService"; 5 | 6 | import App from './../App' 7 | import EmbeddedReport from './EmbeddedReport'; 8 | 9 | import { 10 | PowerBiReport 11 | } from "./../../models/PowerBiModels"; 12 | 13 | interface ViewReportsProperties { 14 | app: App 15 | } 16 | 17 | interface EmbeddedReportRouteParams { 18 | id: string; 19 | } 20 | 21 | type ViewReportsPropertiesWithRouter = 22 | ViewReportsProperties & 23 | RouteComponentProps; 24 | 25 | interface ViewReportsState { 26 | loadingReports: boolean 27 | } 28 | 29 | class ViewReports extends React.Component { 30 | 31 | state = { 32 | loadingReports: false 33 | } 34 | 35 | render() { 36 | return ( 37 |
38 |
39 |
40 |
41 |
Embed Report
42 | {this.state.loadingReports ?
loading...
: null} 43 | 50 |
51 |
52 |
53 | 54 |
55 |
56 |
57 | ); 58 | } 59 | 60 | componentDidMount() { 61 | this.getReports(); 62 | } 63 | 64 | getReports = () => { 65 | if (!this.props.app.state.reportsInCache) { 66 | this.setState({ loadingReports: true }) 67 | PowerBiService.GetReports().then((reports: PowerBiReport[]) => { 68 | this.props.app.setState({ 69 | reports: reports, 70 | reportsInCache: true, 71 | }) 72 | this.setState({ loadingReports: false }) 73 | }); 74 | } 75 | } 76 | 77 | } 78 | 79 | export default withRouter(ViewReports); -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/PowerBiDaySPA/src/favicon.ico -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/images/AppIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/PowerBiDaySPA/src/images/AppIcon.png -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CPT React Demo App 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { render } from 'react-dom'; 3 | import App from './components/App'; 4 | import { HashRouter } from 'react-router-dom' 5 | 6 | var topLevelAppComponent = 7 | 8 | 9 | ; 10 | 11 | var target = document.getElementById('react-target'); 12 | 13 | render(topLevelAppComponent, target); 14 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/models/IUser.ts: -------------------------------------------------------------------------------- 1 | export default interface IUser { 2 | IsAuthenticated: boolean; 3 | DisplayName?: string; 4 | login(): void; 5 | logout(): void; 6 | } -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/models/PowerBiModels.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface PowerBiDashboardTile { 3 | dashboardId: string; 4 | tileId: string; 5 | title: string; 6 | embedUrl: string; 7 | } 8 | 9 | export interface PowerBiDashboard { 10 | displayName: string; 11 | embedUrl: string; 12 | id: string; 13 | } 14 | 15 | export interface PowerBiReport { 16 | id: string; 17 | embedUrl: string; 18 | name: string; 19 | webUrl: string; 20 | datasetId: string; 21 | } 22 | 23 | 24 | export interface PowerBiDataset { 25 | name: string; 26 | embedUrl: string; 27 | id: string; 28 | } 29 | 30 | export interface EmbedResources { 31 | dashboards: PowerBiDashboard[]; 32 | reports: PowerBiReport[]; 33 | datasets: PowerBiDataset[]; 34 | } 35 | 36 | export interface EmbedDataNewReport { 37 | workspaceId: string; 38 | datasetId: string; 39 | embedUrl: string; 40 | accessToken: string; 41 | } -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/src/services/PowerBiService.ts: -------------------------------------------------------------------------------- 1 | import AppSettings from './../AppSettings' 2 | 3 | import { 4 | PowerBiDashboard, 5 | PowerBiReport, 6 | PowerBiDataset, 7 | PowerBiDashboardTile 8 | } 9 | from "./../models/PowerBiModels"; 10 | 11 | import SpaAuthService from "./SpaAuthService"; 12 | 13 | export default class PowerBiService { 14 | 15 | static appWorkspaceId = AppSettings.appWorkspaceId; 16 | static apiRoot: string = "https://api.powerbi.com/v1.0/myorg/"; 17 | static appWorkspaceApiRoot = PowerBiService.apiRoot + "groups/" + PowerBiService.appWorkspaceId + "/"; 18 | 19 | static GetReports = (): Promise => { 20 | var restUrl = PowerBiService.appWorkspaceApiRoot + "Reports/"; 21 | return fetch(restUrl, { 22 | headers: { 23 | "Accept": "application/json;odata.metadata=minimal;", 24 | "Authorization": "Bearer " + SpaAuthService.accessToken 25 | } 26 | }).then(response => response.json()) 27 | .then(response => { return response.value; }); 28 | 29 | } 30 | 31 | static GetDashboards = (): Promise => { 32 | var restUrl = PowerBiService.appWorkspaceApiRoot + "Dashboards/"; 33 | return fetch(restUrl, { 34 | headers: { 35 | "Accept": "application/json;odata.metadata=minimal;", 36 | "Authorization": "Bearer " + SpaAuthService.accessToken 37 | } 38 | }).then(response => response.json()) 39 | .then(response => { return response.value; }); 40 | } 41 | 42 | static GetDashboardTiles = (dashboardId: string): Promise => { 43 | var restUrl = PowerBiService.appWorkspaceApiRoot + "Dashboards/" + dashboardId + "/tiles/"; 44 | return fetch(restUrl, { 45 | headers: { 46 | "Accept": "application/json;odata.metadata=minimal;", 47 | "Authorization": "Bearer " + SpaAuthService.accessToken 48 | } 49 | }).then(response => response.json()) 50 | .then(response => { return response.value; }); 51 | } 52 | 53 | static GetDatasets = (): Promise => { 54 | var restUrl = PowerBiService.appWorkspaceApiRoot + "Datasets/"; 55 | return fetch(restUrl, { 56 | headers: { 57 | "Accept": "application/json;odata.metadata=minimal;", 58 | "Authorization": "Bearer " + SpaAuthService.accessToken 59 | } 60 | }).then(response => response.json()) 61 | .then(response => { return response.value; }); 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "module": "commonjs", 5 | "sourceMap": true, 6 | "target": "es5", 7 | "lib": ["es6", "dom"], 8 | "noImplicitReturns": true, 9 | "noImplicitThis": true, 10 | "noImplicitAny": true, 11 | "strictNullChecks": true, 12 | "experimentalDecorators": true 13 | }, 14 | "exclude": [ 15 | "node_modules" 16 | ] 17 | } -------------------------------------------------------------------------------- /Demos/PowerBiDaySPA/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 5 | const CleanWebpackPlugin = require('clean-webpack-plugin') 6 | 7 | module.exports = { 8 | entry: './src/index.tsx', 9 | output: { 10 | filename: 'scripts/bundle.js', 11 | path: path.resolve(__dirname, 'dist'), 12 | }, 13 | resolve: { 14 | extensions: ['.js', '.json', '.ts', '.tsx'], 15 | }, 16 | plugins: [ 17 | new CleanWebpackPlugin(['dist']), 18 | new HtmlWebpackPlugin({ template: path.join(__dirname, 'src', 'index.html') }), 19 | new CopyWebpackPlugin([{ from: './src/favicon.ico', to: 'favicon.ico' }]) 20 | ], 21 | module: { 22 | rules: [ 23 | { test: /\.(ts|tsx)$/, loader: 'awesome-typescript-loader' }, 24 | { test: /\.css$/, use: ['style-loader', 'css-loader'] }, 25 | { test: /\.(png|jpg|gif)$/, use: [{ loader: 'url-loader', options: { limit: 8192 } }] } 26 | ], 27 | }, 28 | mode: "development", 29 | devtool: 'source-map', 30 | devtool: 'cheap-eval-source-map' 31 | }; -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2009 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerBiEmbeddedScratchpad", "PowerBiEmbeddedScratchpad\PowerBiEmbeddedScratchpad.csproj", "{4B97EA26-41A2-402A-9C0B-6A7669EE7FEB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4B97EA26-41A2-402A-9C0B-6A7669EE7FEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4B97EA26-41A2-402A-9C0B-6A7669EE7FEB}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4B97EA26-41A2-402A-9C0B-6A7669EE7FEB}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4B97EA26-41A2-402A-9C0B-6A7669EE7FEB}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CB017FF7-372B-4F05-BAFA-FF9ED39AC785} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/Models/EmbeddingDataModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace PowerBiEmbeddedScratchpad.Models { 8 | 9 | // data required for embedding a report 10 | class ReportEmbeddingData { 11 | public string reportId; 12 | public string reportName; 13 | public string embedUrl; 14 | public string accessToken; 15 | } 16 | 17 | // data required for embedding a dashboard 18 | class DashboardEmbeddingData { 19 | public string dashboardId; 20 | public string dashboardName; 21 | public string embedUrl; 22 | public string accessToken; 23 | } 24 | 25 | // data required for embedding a dashboard 26 | class DashboardTileEmbeddingData { 27 | public string dashboardId; 28 | public string TileId; 29 | public string TileTitle; 30 | public string embedUrl; 31 | public string accessToken; 32 | } 33 | 34 | // data required for embedding a new report 35 | class NewReportEmbeddingData { 36 | public string workspaceId; 37 | public string datasetId; 38 | public string embedUrl; 39 | public string accessToken; 40 | } 41 | 42 | // data required for embedding QnA experience 43 | class QnaEmbeddingData { 44 | public string datasetId; 45 | public string embedUrl; 46 | public string accessToken; 47 | } 48 | 49 | // 50 | class ReportWithRlsEmbeddingData { 51 | public string reportId; 52 | public string reportName; 53 | public string embedUrl; 54 | public string embedTokenAllData; 55 | public string embedTokenWesternSales; 56 | public string embedTokenCentralSales; 57 | public string embedTokenEasternSales; 58 | public string embedTokenCombo; 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedDashboard.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedDashboardTile.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedNewReport.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedQna.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedReport.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedReportVisual.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedReportWithBookmarkCarousel.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Navigating with Bookmarks 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 96 | 97 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedReportWithConfigurationOptions.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedReportWithFirstPartyToken.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/EmbedReportWithPhasedLoading.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | @AppName - Phased Loading 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background-color: #EEE; 5 | } 6 | 7 | #toolbar { 8 | padding: 8px; 9 | background-color: black; 10 | } 11 | 12 | #toolbar button { 13 | font-size: 24px; 14 | width: 150px 15 | } 16 | 17 | #leftnav { 18 | float: left; 19 | width: 240px; 20 | background-color: white; 21 | padding: 0px; 22 | border: solid 1px #333; 23 | } 24 | 25 | #leftnav h3 { 26 | margin: 0; 27 | padding: 4px; 28 | padding-left: 12px; 29 | color: white; 30 | background-color: black; 31 | font-size: 24px; 32 | } 33 | 34 | #leftnav h4 { 35 | margin: 0; 36 | padding: 4px; 37 | padding-bottom: 2px; 38 | padding-left: 12px; 39 | color: black; 40 | background-color: #BBB; 41 | font-size: 12px; 42 | } 43 | 44 | #leftnav ul { 45 | margin-top: 0; 46 | padding: 4px; 47 | } 48 | 49 | #leftnav li { 50 | margin: 8px; 51 | list-style-type: none; 52 | } 53 | 54 | #leftnav li a { 55 | color: darkblue; 56 | text-decoration: none; 57 | } 58 | leftnav-menu { 59 | width: 100px; 60 | } 61 | 62 | #loading img { 63 | width: 80px; 64 | margin-top: 36px; 65 | margin-left: 72px; 66 | } 67 | 68 | 69 | #output-display { 70 | background-color: white; 71 | padding: 8px; 72 | border: solid 1px #333; 73 | } 74 | 75 | #output-display h3 { 76 | margin: 0; 77 | border-bottom: solid 1px black; 78 | color: black; 79 | } 80 | 81 | #output-display h4 { 82 | margin: 0px; 83 | margin-bottom: 4px; 84 | background-color: black; 85 | color: white; 86 | padding: 4px; 87 | font-size: 0.9em; 88 | } 89 | 90 | #output-display div { 91 | margin: 4px; 92 | } 93 | 94 | #visual-table { 95 | width: 100%; 96 | border-collapse: collapse; 97 | margin-top: 0; 98 | } 99 | 100 | #visual-table thead td { 101 | color: white; 102 | background-color: black; 103 | font-size: 10px; 104 | padding: 4px; 105 | } 106 | 107 | #visual-table tr td { 108 | color: #222; 109 | border: 1px black solid; 110 | padding: 4px; 111 | background-color: White; 112 | border-collapse: collapse; 113 | font-size: 9px; 114 | } 115 | 116 | 117 | #state-picker { 118 | background-color: white; 119 | padding: 4px; 120 | padding-left: 6px; 121 | padding-top: 8px; 122 | padding-bottom: 8px; 123 | margin: 0px; 124 | width: auto; 125 | } 126 | 127 | 128 | .state-container { 129 | display: inline-block; 130 | width: 52px; 131 | margin: 1px; 132 | margin-left: 3px; 133 | background-color: white; 134 | border-radius: 2px; 135 | } 136 | 137 | .state-checkbox { 138 | vertical-align: middle; 139 | } 140 | 141 | .state-label { 142 | vertical-align: middle; 143 | font-size: 14px; 144 | padding: 0; 145 | margin-bottom: 0px; 146 | } 147 | 148 | #filter-buttons { 149 | text-align: center; 150 | } 151 | 152 | #filter-buttons input { 153 | margin-top: 12px; 154 | width: 92%; 155 | font-size: 16px; 156 | padding: 3px; 157 | border-radius: 4px; 158 | } -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/AppIcon_png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/AppIcon_png -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/favicon_ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/favicon_ico -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/loading2_gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/loading2_gif -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/loading3_gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/loading3_gif -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/loading_gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/PageTemplates/img/loading_gif -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using PowerBiEmbeddedScratchpad.Models; 3 | 4 | namespace PowerBiEmbeddedScratchpad { 5 | class Program { 6 | static void Main() { 7 | 8 | bool launchInBrowser = true; 9 | 10 | PageGenerator.GenerateReportPageWithFirstPartyEmbedding(launchInBrowser); 11 | //PageGenerator.GenerateReportPage(launchInBrowser); 12 | //PageGenerator.GenerateReportWithToolbarPage(launchInBrowser); 13 | //PageGenerator.GenerateDashboardPage(launchInBrowser); 14 | //PageGenerator.GenerateDashboardTilePage(launchInBrowser); 15 | //PageGenerator.GenerateNewReportPage(launchInBrowser); 16 | //PageGenerator.GenerateNewReportPageWithSaveAsRedirect(launchInBrowser); 17 | //PageGenerator.GenerateQnaPage(launchInBrowser); 18 | //PageGenerator.GenerateReportPageWithConfigurationOptions(launchInBrowser); 19 | //PageGenerator.GenerateReportWithPageNavigation(launchInBrowser); 20 | //PageGenerator.GenerateReportPageWithPhasedLoading(launchInBrowser); 21 | //PageGenerator.GenerateReportWithCustomFiltering(launchInBrowser); 22 | //PageGenerator.GenerateReportWithBookmarks(launchInBrowser); 23 | //PageGenerator.GenerateReportWithBookmarkCarousel(launchInBrowser); 24 | //PageGenerator.GenerateReportWithContextMenusPage(launchInBrowser); 25 | //PageGenerator.GenerateReportInspectorPage(launchInBrowser); 26 | //PageGenerator.GenerateReportVisualPage(launchInBrowser); 27 | 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PowerBiEmbeddedScratchpad")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PowerBiEmbeddedScratchpad")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4b97ea26-41a2-402a-9c0b-6a7669ee7feb")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Demos/PowerBiEmbeddedScratchpad/PowerBiEmbeddedScratchpad/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.102 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RowLevelSecurityDemo", "RowLevelSecurityDemo\RowLevelSecurityDemo.csproj", "{F040D70E-C6B2-4102-AA68-0D8CCEC47EF5}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {F040D70E-C6B2-4102-AA68-0D8CCEC47EF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {F040D70E-C6B2-4102-AA68-0D8CCEC47EF5}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {F040D70E-C6B2-4102-AA68-0D8CCEC47EF5}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {F040D70E-C6B2-4102-AA68-0D8CCEC47EF5}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {5321561F-EE6D-4440-AE0C-9D35248370AB} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/App_Start/IdentityConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Claims; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNet.Identity; 5 | using Microsoft.AspNet.Identity.EntityFramework; 6 | using Microsoft.AspNet.Identity.Owin; 7 | using Microsoft.Owin; 8 | using Microsoft.Owin.Security; 9 | using RowLevelSecurityDemo.Models; 10 | 11 | namespace RowLevelSecurityDemo { 12 | 13 | //public class EmailService : IIdentityMessageService { 14 | // public Task SendAsync(IdentityMessage message) { 15 | // return Task.FromResult(0); 16 | // } 17 | //} 18 | 19 | //public class SmsService : IIdentityMessageService { 20 | // public Task SendAsync(IdentityMessage message) { 21 | // return Task.FromResult(0); 22 | // } 23 | //} 24 | 25 | // Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application. 26 | public class ApplicationUserManager : UserManager { 27 | 28 | public ApplicationUserManager(IUserStore store) 29 | : base(store) { 30 | } 31 | 32 | public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) { 33 | 34 | var manager = new ApplicationUserManager(new UserStore(context.Get())); 35 | 36 | manager.UserValidator = new UserValidator(manager) { 37 | AllowOnlyAlphanumericUserNames = false, 38 | RequireUniqueEmail = true 39 | }; 40 | 41 | // Configure validation logic for passwords 42 | manager.PasswordValidator = new PasswordValidator { 43 | RequiredLength = 6, 44 | RequireDigit = false, 45 | RequireLowercase = false, 46 | RequireNonLetterOrDigit = false, 47 | RequireUppercase = false 48 | }; 49 | 50 | // Configure user lockout defaults 51 | manager.UserLockoutEnabledByDefault = false; 52 | manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); 53 | manager.MaxFailedAccessAttemptsBeforeLockout = 5; 54 | 55 | //manager.EmailService = new EmailService(); 56 | //manager.SmsService = new SmsService(); 57 | 58 | var dataProtectionProvider = options.DataProtectionProvider; 59 | if (dataProtectionProvider != null) { 60 | manager.UserTokenProvider = 61 | new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); 62 | } 63 | return manager; 64 | } 65 | } 66 | 67 | // Configure the application sign-in manager which is used in this application. 68 | public class ApplicationSignInManager : SignInManager { 69 | 70 | public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) 71 | : base(userManager, authenticationManager) { 72 | } 73 | 74 | public override Task CreateUserIdentityAsync(ApplicationUser user) { 75 | return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); 76 | } 77 | 78 | public static ApplicationSignInManager Create(IdentityFactoryOptions options, IOwinContext context) { 79 | return new ApplicationSignInManager(context.GetUserManager(), context.Authentication); 80 | } 81 | 82 | } 83 | 84 | 85 | 86 | 87 | 88 | } -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace RowLevelSecurityDemo 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/App_Start/Startup.Auth.cs: -------------------------------------------------------------------------------- 1 | using Owin; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Web; 6 | using RowLevelSecurityDemo.Models; 7 | using Microsoft.AspNet.Identity; 8 | using Microsoft.Owin.Security.Cookies; 9 | using Microsoft.Owin; 10 | using Microsoft.AspNet.Identity.Owin; 11 | 12 | namespace RowLevelSecurityDemo { 13 | public partial class Startup { 14 | 15 | public void ConfigureAuth(IAppBuilder app) { 16 | 17 | // Configure the db context, user manager and signin manager to use a single instance per request 18 | app.CreatePerOwinContext(ApplicationDbContext.Create); 19 | app.CreatePerOwinContext(ApplicationUserManager.Create); 20 | app.CreatePerOwinContext(ApplicationSignInManager.Create); 21 | 22 | app.UseCookieAuthentication(new CookieAuthenticationOptions { 23 | AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 24 | LoginPath = new PathString("/Account/Login"), 25 | Provider = new CookieAuthenticationProvider { 26 | // Enables the application to validate the security stamp when the user logs in. 27 | // This is a security feature which is used when you change a password or add an external login to your account. 28 | OnValidateIdentity = SecurityStampValidator.OnValidateIdentity( 29 | validateInterval: TimeSpan.FromMinutes(30), 30 | regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) 31 | } 32 | }); 33 | 34 | ApplicationDbContext db = new ApplicationDbContext(); 35 | db.Database.Initialize(true); 36 | 37 | 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #ccc; 3 | } 4 | 5 | #homePageContainer { 6 | padding: 24px; 7 | } 8 | 9 | #userInfoPageContainer { 10 | padding: 24px; 11 | } 12 | 13 | #userInfoPageContainer h2 { 14 | color: white; 15 | background-color: black; 16 | margin-bottom: 0px; 17 | padding: 4px; 18 | font-size: 1.25em; 19 | border-top-left-radius: 4px; 20 | border-top-right-radius: 4px; 21 | } 22 | 23 | 24 | #userInfoTable{ 25 | margin-top: 0px; 26 | } 27 | 28 | #userInfoTable td:first-child { 29 | width: 164px; 30 | } 31 | 32 | 33 | #userInfoTable ul { 34 | list-style-type: none; 35 | margin: 0px; 36 | padding: 0px; 37 | } 38 | 39 | #userInfoTable ul li { 40 | margin: 0px; 41 | padding: 0px; 42 | color: purple; 43 | } 44 | 45 | #content-box { 46 | padding: 0px; 47 | background-color: #FFF; 48 | } 49 | 50 | #banner { 51 | padding-left: 0px; 52 | padding-right: 0px; 53 | } 54 | 55 | #topnav { 56 | background-color: #000 !important; 57 | } 58 | 59 | #toolbar { 60 | background-color: #666 !important; 61 | border-bottom: 1px solid #333; 62 | } 63 | 64 | #toolbar button { 65 | width: 92px; 66 | margin: 4px; 67 | padding: 2px; 68 | font-size: 9px; 69 | font-weight: bold; 70 | color: #222; 71 | background-color: #F2C811; 72 | border-color: #111; 73 | } 74 | 75 | .navbar-dark .navbar-nav .active > .nav-link { 76 | color: #FFC; 77 | } 78 | 79 | .navbar-dark .navbar-nav .nav-link { 80 | color: #F2C811; 81 | } 82 | 83 | .navbar-dark .navbar-nav .nav-link:hover { 84 | color: orange; 85 | } 86 | 87 | .jumbotron { 88 | background-color: #FFFFF1; 89 | border: 1px solid #AAA; 90 | } 91 | 92 | #loginForm { 93 | margin-top: 64px; 94 | margin-left: 10%; 95 | background-color: #BBB; 96 | padding: 24px; 97 | width: 80%; 98 | margin-bottom: 128px; 99 | } 100 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using Microsoft.AspNet.Identity; 7 | using Microsoft.AspNet.Identity.EntityFramework; 8 | using RowLevelSecurityDemo.Models; 9 | 10 | namespace RowLevelSecurityDemo.Controllers { 11 | public class HomeController : Controller { 12 | 13 | public ActionResult Index() { 14 | return View(); 15 | } 16 | 17 | [Authorize] 18 | public ActionResult UserInfo() { 19 | 20 | UserIfoViewModel viewModel = new UserIfoViewModel { IsAuthenticated = false }; 21 | 22 | if (User.Identity.IsAuthenticated) { 23 | viewModel.IsAuthenticated = true; 24 | 25 | ApplicationDbContext context = new ApplicationDbContext(); 26 | var userManager = new UserManager(new UserStore(context)); 27 | ApplicationUser currentUser = userManager.FindByName(User.Identity.GetUserName()); 28 | 29 | viewModel.UserId = currentUser.Id; 30 | viewModel.UserEmail = currentUser.Email; 31 | viewModel.UserName = currentUser.UserName; 32 | viewModel.UserDisplayName = currentUser.DisplayName; 33 | 34 | var roleManager = new RoleManager(new RoleStore(context)); 35 | 36 | List roles = new List(); 37 | 38 | foreach (var role in currentUser.Roles) { 39 | roles.Add(roleManager.FindById(role.RoleId).Name); 40 | } 41 | 42 | viewModel.HasRoles = (roles.Count > 0); 43 | viewModel.Roles = roles.ToArray(); 44 | } 45 | 46 | 47 | 48 | return View(viewModel); 49 | } 50 | 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Controllers/ReportsController.cs: -------------------------------------------------------------------------------- 1 | using RowLevelSecurityDemo.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using System.Web; 7 | using System.Web.Mvc; 8 | 9 | namespace RowLevelSecurityDemo.Controllers { 10 | 11 | [Authorize] 12 | public class ReportsController : Controller { 13 | 14 | 15 | public async Task ReportByRole() { 16 | ReportEmbeddingData embeddingData = await PbiEmbeddedManager.GetReportEmbeddingDataWithRlsRoles(); 17 | return View(embeddingData); 18 | } 19 | 20 | public async Task ReportByState() { 21 | ReportEmbeddingData embeddingData = await PbiEmbeddedManager.GetReportEmbeddingDataWithStateClaims(); 22 | return View(embeddingData); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="RowLevelSecurityDemo.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace RowLevelSecurityDemo 9 | { 10 | public class MvcApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | AreaRegistration.RegisterAllAreas(); 15 | RouteConfig.RegisterRoutes(RouteTable.Routes); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Models/MvcViewModels.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | 5 | namespace RowLevelSecurityDemo.Models { 6 | 7 | public class UserIfoViewModel { 8 | public bool IsAuthenticated { get; set; } 9 | public bool IsAdmin { get; set; } 10 | public string UserId { get; set; } 11 | public string UserName { get; set; } 12 | public string UserEmail { get; set; } 13 | public string UserDisplayName { get; set; } 14 | public bool HasRoles { get; set; } 15 | public string[] Roles { get; set; } 16 | } 17 | 18 | public class LoginViewModel { 19 | 20 | [Required] 21 | [Display(Name = "User Name")] 22 | public string UserName{ get; set; } 23 | 24 | [Required] 25 | [DataType(DataType.Password)] 26 | [Display(Name = "Password")] 27 | public string Password { get; set; } 28 | 29 | [Display(Name = "Remember me?")] 30 | public bool RememberMe { get; set; } 31 | 32 | } 33 | 34 | 35 | } -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Models/PbiEmbeddingModels.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace RowLevelSecurityDemo.Models { 3 | 4 | // data required for embedding a report 5 | public class ReportEmbeddingData { 6 | public string reportId; 7 | public string reportName; 8 | public string embedUrl; 9 | public string accessToken; 10 | } 11 | 12 | // data required for embedding a new report 13 | public class NewReportEmbeddingData { 14 | public string workspaceId; 15 | public string datasetId; 16 | public string embedUrl; 17 | public string accessToken; 18 | } 19 | 20 | // data required for embedding a dashboard 21 | public class DashboardEmbeddingData { 22 | public string dashboardId; 23 | public string dashboardName; 24 | public string embedUrl; 25 | public string accessToken; 26 | } 27 | 28 | // data required for embedding a dashboard 29 | public class QnaEmbeddingData { 30 | public string datasetId; 31 | public string embedUrl; 32 | public string accessToken; 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RowLevelSecurityDemo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RowLevelSecurityDemo")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f040d70e-c6b2-4102-aa68-0d8ccec47ef5")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Startup.cs: -------------------------------------------------------------------------------- 1 | using Owin; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Web; 6 | 7 | namespace RowLevelSecurityDemo { 8 | 9 | public partial class Startup { 10 | 11 | 12 | public void Configuration(IAppBuilder app) { 13 | ConfigureAuth(app); 14 | } 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using RowLevelSecurityDemo.Models 2 | @model LoginViewModel 3 | 4 |
5 |
6 |
7 | @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { 8 | @Html.AntiForgeryToken() 9 |

Enter Wingtip Customer account credentials

10 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 11 |
12 | @Html.LabelFor(m => m.UserName, new { @class = "col-md-4 control-label" }) 13 |
14 | @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" }) 15 | @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" }) 16 |
17 |
18 |
19 | @Html.LabelFor(m => m.Password, new { @class = "col-md-4 control-label" }) 20 |
21 | @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 22 | @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" }) 23 |
24 |
25 |
26 |
27 |
28 | @Html.CheckBoxFor(m => m.RememberMe) 29 | @Html.LabelFor(m => m.RememberMe) 30 |
31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 | } 39 |
40 |
41 | 42 |
43 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 |  2 |
3 | 4 |
5 |

Power BI Embedding with RLS Demo

6 | 7 | @if (!User.Identity.IsAuthenticated) { 8 |
Click the log in link to sign in
9 | } 10 | else { 11 |
The user is currently authenticated as @User.Identity.Name
12 |
Navigate to the @Html.ActionLink("User Info View", "UserInfo", "Home") to see detailed information about the current user. 13 |
14 | } 15 |
16 | 17 |
-------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/Home/UserInfo.cshtml: -------------------------------------------------------------------------------- 1 | @model RowLevelSecurityDemo.Models.UserIfoViewModel 2 | 3 | @{ 4 | var currentUser = Model; 5 | } 6 | 7 |
8 | 9 |

Current User Info

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | @if (currentUser.HasRoles) { 36 | 37 | 38 | 45 | 46 | } 47 |
User ID@currentUser.UserId
User Name@currentUser.UserName
User Email@currentUser.UserEmail
User Display Name@currentUser.UserDisplayName
User is Admin@currentUser.IsAdmin
User Has Roles@currentUser.HasRoles
User Roles 39 |
    40 | @foreach (var role in currentUser.Roles) { 41 |
  • @role
  • 42 | } 43 |
44 |
48 | 49 |
-------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/Reports/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model RowLevelSecurityDemo.Models.ReportEmbeddingData 2 | 3 | @if (User.IsInRole("Admin")) { 4 | @section toolbar { 5 | 9 | } 10 | } 11 | 12 | 13 |
14 | 15 | 16 | 17 | 70 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/Reports/ReportByRole.cshtml: -------------------------------------------------------------------------------- 1 | @model RowLevelSecurityDemo.Models.ReportEmbeddingData 2 | 3 | @if (User.IsInRole("Admin")) { 4 | @section toolbar { 5 | 9 | } 10 | } 11 | 12 | 13 |
14 | 15 | 16 | 17 | 70 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/Reports/ReportByState.cshtml: -------------------------------------------------------------------------------- 1 | @model RowLevelSecurityDemo.Models.ReportEmbeddingData 2 | 3 | @if (User.IsInRole("Admin")) { 4 | @section toolbar { 5 | 9 | } 10 | } 11 | 12 | 13 |
14 | 15 | 16 | 17 | 70 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Row Level Security Demo 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 37 | 38 | 39 |
40 | @RenderBody() 41 |
42 | 43 | 44 | 45 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNet.Identity 2 | @using RowLevelSecurityDemo.Models 3 | @using Microsoft.AspNet.Identity.EntityFramework 4 | 5 | @if (Request.IsAuthenticated) { 6 | using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "ml-auto" })) { 7 | @Html.AntiForgeryToken() 8 | 9 | 10 | 11 | ApplicationDbContext context = new ApplicationDbContext(); 12 | var UserManager = new UserManager(new UserStore(context)); 13 | ApplicationUser currentUser = UserManager.FindByName(User.Identity.GetUserName()); 14 | 15 | string ID = currentUser.Id; 16 | string Email = currentUser.Email; 17 | string Username = currentUser.UserName; 18 | 19 | 20 | 27 | } 28 | } 29 | else { 30 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Views/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Demos/RowLevelSecurityDemo/RowLevelSecurityDemo/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.102 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThirdPartyEmbeddingDemo", "ThirdPartyEmbeddingDemo\ThirdPartyEmbeddingDemo.csproj", "{1142F710-F95C-4333-B06B-7B3AD35F04A4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {1142F710-F95C-4333-B06B-7B3AD35F04A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {1142F710-F95C-4333-B06B-7B3AD35F04A4}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {1142F710-F95C-4333-B06B-7B3AD35F04A4}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {1142F710-F95C-4333-B06B-7B3AD35F04A4}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {F6BE54C4-9A17-4BC8-B6EC-C23E8AA627C9} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/App_Start/IdentityConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Claims; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNet.Identity; 5 | using Microsoft.AspNet.Identity.EntityFramework; 6 | using Microsoft.AspNet.Identity.Owin; 7 | using Microsoft.Owin; 8 | using Microsoft.Owin.Security; 9 | using ThirdPartyEmbeddingDemo.Models; 10 | 11 | namespace ThirdPartyEmbeddingDemo { 12 | 13 | // Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application. 14 | public class ApplicationUserManager : UserManager { 15 | 16 | public ApplicationUserManager(IUserStore store) 17 | : base(store) { 18 | } 19 | 20 | public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) { 21 | 22 | var manager = new ApplicationUserManager(new UserStore(context.Get())); 23 | 24 | manager.UserValidator = new UserValidator(manager) { 25 | AllowOnlyAlphanumericUserNames = false, 26 | RequireUniqueEmail = true 27 | }; 28 | 29 | // Configure validation logic for passwords 30 | manager.PasswordValidator = new PasswordValidator { 31 | RequiredLength = 6, 32 | RequireDigit = false, 33 | RequireLowercase = false, 34 | RequireNonLetterOrDigit = false, 35 | RequireUppercase = false 36 | }; 37 | 38 | // Configure user lockout defaults 39 | manager.UserLockoutEnabledByDefault = false; 40 | manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); 41 | manager.MaxFailedAccessAttemptsBeforeLockout = 5; 42 | 43 | var dataProtectionProvider = options.DataProtectionProvider; 44 | if (dataProtectionProvider != null) { 45 | manager.UserTokenProvider = 46 | new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); 47 | } 48 | return manager; 49 | } 50 | } 51 | 52 | // Configure the application sign-in manager which is used in this application. 53 | public class ApplicationSignInManager : SignInManager { 54 | 55 | public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) 56 | : base(userManager, authenticationManager) { 57 | } 58 | 59 | public override Task CreateUserIdentityAsync(ApplicationUser user) { 60 | return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); 61 | } 62 | 63 | public static ApplicationSignInManager Create(IdentityFactoryOptions options, IOwinContext context) { 64 | return new ApplicationSignInManager(context.GetUserManager(), context.Authentication); 65 | } 66 | 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace ThirdPartyEmbeddingDemo 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/App_Start/Startup.Auth.cs: -------------------------------------------------------------------------------- 1 | using Owin; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Web; 6 | using ThirdPartyEmbeddingDemo.Models; 7 | using Microsoft.AspNet.Identity; 8 | using Microsoft.Owin.Security.Cookies; 9 | using Microsoft.Owin; 10 | using Microsoft.AspNet.Identity.Owin; 11 | 12 | namespace ThirdPartyEmbeddingDemo { 13 | public partial class Startup { 14 | 15 | public void ConfigureAuth(IAppBuilder app) { 16 | 17 | // Configure the db context, user manager and signin manager to use a single instance per request 18 | app.CreatePerOwinContext(ApplicationDbContext.Create); 19 | app.CreatePerOwinContext(ApplicationUserManager.Create); 20 | app.CreatePerOwinContext(ApplicationSignInManager.Create); 21 | 22 | app.UseCookieAuthentication(new CookieAuthenticationOptions { 23 | AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 24 | LoginPath = new PathString("/Account/Login"), 25 | Provider = new CookieAuthenticationProvider { 26 | // Enables the application to validate the security stamp when the user logs in. 27 | // This is a security feature which is used when you change a password or add an external login to your account. 28 | OnValidateIdentity = SecurityStampValidator.OnValidateIdentity( 29 | validateInterval: TimeSpan.FromMinutes(30), 30 | regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) 31 | } 32 | }); 33 | 34 | ApplicationDbContext db = new ApplicationDbContext(); 35 | db.Database.Initialize(true); 36 | 37 | 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Certificates/AppCert1.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Certificates/AppCert1.cer -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Certificates/AppCert1.json.txt: -------------------------------------------------------------------------------- 1 | { 2 | "customKeyIdentifier": "Ox+W3Svn7qZZ8qIS+qjv1rcWvjQ=", 3 | "keyId": "fce49340-e071-4a4e-8732-36ca2f5c8ea1", 4 | "type": "AsymmetricX509Cert", 5 | "usage": "Verify", 6 | "value": "MIIDADCCAeigAwIBAgIQQjTZdA03Mq5CSypvtMvZHzANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhBcHBDZXJ0MTAeFw0xOTAzMTUxNTQwNDFaFw0yMTAzMTUxNTUwNDFaMBMxETAPBgNVBAMMCEFwcENlcnQxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7znQ+XS2UYcUhwfmFarGV5CKhmA2p6bHQdYn/LoTfCkTiBUMXJwg7CelA0drV3XleaPhPDTei7gCZek2pVx7ciT4AlNoPkfT70gXmFsZEMzmi8pjs1LfpPd/ucTuPE9MHAwhkP+jm8npnrV7D+9Zd+cY0x+hCgssdFYIgy1hrupk8ew1JHcaCiUE9CCusHoblscuCI2R31oU03SK3KtYYSjogoiUNzz/lh8XmVXjZDP4OwtrQyBj2sURRQkmwaSCVgGPpFEIWp8AE5LgwMuFhMpmZxg3noVRFEFRVwZwxRm269Rrs6O01qNAZDtYc6JMemJ3N+d/kMZFQGFDDylywQIDAQABo1AwTjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBRMpjDcCO2M+txPMyCzb/4oIyHQZDANBgkqhkiG9w0BAQsFAAOCAQEAY4N8blhJRjIvnU+E2FaZT4YZ+wRM6NdXGin7n5FWqTHV2uDmgjWdNzMSc5MXaf7/7iGXrtBt4wBPsVoO8tcWPv9iR/YQGe95nqvK7yqCki7Qjlgkc31YI5h3THqfoza6WwQvWGxWjV5WLlly8ZIxLGDBUfUm6SDrqA39zRQMMQP2bz4eXol3+Lb618nEh+SM9XnRJgQqf3d9kfta0Cmu0mj6QSp7Xme3VvKunPHQ1SpBfKAi5RvFxnW9aV4pHR7l/p+OTNn+jPAH7+zv+/AVKTw3ZnBUO/X6kUBT4jGBGTD0dmbO4PHU83lzQGa/PLIkCTCAkyagBJp/yrz9i8sdWg==" 7 | } 8 | 9 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #ccc; 3 | } 4 | 5 | #homePageContainer { 6 | padding: 24px; 7 | } 8 | 9 | #userInfoPageContainer { 10 | padding: 24px; 11 | } 12 | 13 | #userInfoPageContainer h2 { 14 | color: white; 15 | background-color: black; 16 | margin-bottom: 0px; 17 | padding: 4px; 18 | font-size: 1.25em; 19 | border-top-left-radius: 4px; 20 | border-top-right-radius: 4px; 21 | } 22 | 23 | 24 | #userInfoTable{ 25 | margin-top: 0px; 26 | } 27 | 28 | #userInfoTable td:first-child { 29 | width: 164px; 30 | } 31 | 32 | 33 | #userInfoTable ul { 34 | list-style-type: none; 35 | margin: 0px; 36 | padding: 0px; 37 | } 38 | 39 | #userInfoTable ul li { 40 | margin: 0px; 41 | padding: 0px; 42 | color: purple; 43 | } 44 | 45 | #content-box { 46 | padding: 0px; 47 | background-color: #FFF; 48 | } 49 | 50 | #banner { 51 | padding-left: 0px; 52 | padding-right: 0px; 53 | } 54 | 55 | #topnav { 56 | background-color: #000 !important; 57 | } 58 | 59 | #toolbar { 60 | background-color: #666 !important; 61 | border-bottom: 1px solid #333; 62 | } 63 | 64 | #toolbar button { 65 | width: 92px; 66 | margin: 4px; 67 | padding: 2px; 68 | font-size: 9px; 69 | font-weight: bold; 70 | color: #222; 71 | background-color: #F2C811; 72 | border-color: #111; 73 | } 74 | 75 | .navbar-dark .navbar-nav .active > .nav-link { 76 | color: #FFC; 77 | } 78 | 79 | .navbar-dark .navbar-nav .nav-link { 80 | color: #F2C811; 81 | } 82 | 83 | .navbar-dark .navbar-nav .nav-link:hover { 84 | color: orange; 85 | } 86 | 87 | .jumbotron { 88 | background-color: #FFFFF1; 89 | border: 1px solid #AAA; 90 | } 91 | 92 | #loginForm { 93 | margin-top: 64px; 94 | margin-left: 10%; 95 | background-color: #BBB; 96 | padding: 24px; 97 | width: 80%; 98 | margin-bottom: 128px; 99 | } 100 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using Microsoft.AspNet.Identity; 7 | using Microsoft.AspNet.Identity.EntityFramework; 8 | using ThirdPartyEmbeddingDemo.Models; 9 | 10 | namespace ThirdPartyEmbeddingDemo.Controllers { 11 | public class HomeController : Controller { 12 | 13 | public ActionResult Index() { 14 | return View(); 15 | } 16 | 17 | [Authorize] 18 | public ActionResult UserInfo() { 19 | 20 | UserIfoViewModel viewModel = new UserIfoViewModel { IsAuthenticated = false }; 21 | 22 | if (User.Identity.IsAuthenticated) { 23 | viewModel.IsAuthenticated = true; 24 | 25 | ApplicationDbContext context = new ApplicationDbContext(); 26 | var userManager = new UserManager(new UserStore(context)); 27 | ApplicationUser currentUser = userManager.FindByName(User.Identity.GetUserName()); 28 | 29 | viewModel.UserId = currentUser.Id; 30 | viewModel.UserEmail = currentUser.Email; 31 | viewModel.UserName = currentUser.UserName; 32 | viewModel.UserDisplayName = currentUser.DisplayName; 33 | 34 | var roleManager = new RoleManager(new RoleStore(context)); 35 | 36 | List roles = new List(); 37 | 38 | foreach (var role in currentUser.Roles) { 39 | roles.Add(roleManager.FindById(role.RoleId).Name); 40 | } 41 | 42 | viewModel.HasRoles = (roles.Count > 0); 43 | viewModel.Roles = roles.ToArray(); 44 | } 45 | 46 | 47 | 48 | return View(viewModel); 49 | } 50 | 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Controllers/ReportsController.cs: -------------------------------------------------------------------------------- 1 | using ThirdPartyEmbeddingDemo.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using System.Web; 7 | using System.Web.Mvc; 8 | 9 | namespace ThirdPartyEmbeddingDemo.Controllers { 10 | 11 | [Authorize] 12 | public class ReportsController : Controller { 13 | 14 | 15 | public async Task Index() { 16 | ReportEmbeddingData embeddingData = await PbiEmbeddedManager.GetReportEmbeddingData(); 17 | return View(embeddingData); 18 | } 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="ThirdPartyEmbeddingDemo.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace ThirdPartyEmbeddingDemo 9 | { 10 | public class MvcApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | AreaRegistration.RegisterAllAreas(); 15 | RouteConfig.RegisterRoutes(RouteTable.Routes); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Models/IdentityModels.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Entity; 2 | using System.Security.Claims; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNet.Identity; 5 | using Microsoft.AspNet.Identity.EntityFramework; 6 | 7 | namespace ThirdPartyEmbeddingDemo.Models { 8 | 9 | public class ApplicationUser : IdentityUser { 10 | 11 | // add custom properties to user profile 12 | public string DisplayName { get; set; } 13 | 14 | public async Task GenerateUserIdentityAsync(UserManager manager) { 15 | // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 16 | var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 17 | return userIdentity; 18 | } 19 | } 20 | 21 | public class ApplicationDbContext : IdentityDbContext { 22 | public ApplicationDbContext() 23 | : base("DefaultConnection", throwIfV1Schema: false) { 24 | Database.SetInitializer(new IdentityDropCreateInitializer()); 25 | } 26 | 27 | public static ApplicationDbContext Create() { 28 | return new ApplicationDbContext(); 29 | } 30 | } 31 | 32 | public class IdentityDropCreateInitializer : DropCreateDatabaseAlways { 33 | 34 | protected override void Seed(ApplicationDbContext context) { 35 | 36 | //Seed identity tables here 37 | var userManager = new UserManager(new UserStore(new ApplicationDbContext())); 38 | var roleManager = new RoleManager(new RoleStore(new ApplicationDbContext())); 39 | 40 | roleManager.Create(new IdentityRole { Id = "Admin", Name = "Admin" }); 41 | 42 | userManager.Create(new ApplicationUser { Email = "JasonB@cpt.net", UserName = "JasonB", DisplayName = "Jason Borne" }, "Password1"); 43 | userManager.AddToRole(userManager.FindByEmail("JasonB@cpt.net").Id, "Admin"); 44 | 45 | userManager.Create(new ApplicationUser { Email = "JamesB@cpt.net", UserName = "JamesB", DisplayName = "James Bond" }, "Password1"); 46 | userManager.Create(new ApplicationUser { Email = "MaxwellS@cpt.net", UserName = "MaxwellS", DisplayName = "Maxwell Smart" }, "Password1"); 47 | userManager.Create(new ApplicationUser { Email = "EmmaP@cpt.net", UserName = "EmmaP", DisplayName = "Emma Peel" }, "Password1"); 48 | userManager.Create(new ApplicationUser { Email = "AustinP@cpt.net", UserName = "AustinP", DisplayName = "Austin Powers" }, "Password1"); 49 | 50 | context.SaveChanges(); 51 | 52 | } 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Models/MvcViewModels.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | 5 | namespace ThirdPartyEmbeddingDemo.Models { 6 | 7 | public class UserIfoViewModel { 8 | public bool IsAuthenticated { get; set; } 9 | public bool IsAdmin { get; set; } 10 | public string UserId { get; set; } 11 | public string UserName { get; set; } 12 | public string UserEmail { get; set; } 13 | public string UserDisplayName { get; set; } 14 | public bool HasRoles { get; set; } 15 | public string[] Roles { get; set; } 16 | } 17 | 18 | public class LoginViewModel { 19 | 20 | [Required] 21 | [Display(Name = "User Name")] 22 | public string UserName{ get; set; } 23 | 24 | [Required] 25 | [DataType(DataType.Password)] 26 | [Display(Name = "Password")] 27 | public string Password { get; set; } 28 | 29 | [Display(Name = "Remember me?")] 30 | public bool RememberMe { get; set; } 31 | 32 | } 33 | 34 | 35 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Models/PbiEmbeddingModels.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace ThirdPartyEmbeddingDemo.Models { 3 | 4 | // data required for embedding a report 5 | public class ReportEmbeddingData { 6 | public string reportId; 7 | public string reportName; 8 | public string embedUrl; 9 | public string accessToken; 10 | } 11 | 12 | // data required for embedding a new report 13 | public class NewReportEmbeddingData { 14 | public string workspaceId; 15 | public string datasetId; 16 | public string embedUrl; 17 | public string accessToken; 18 | } 19 | 20 | // data required for embedding a dashboard 21 | public class DashboardEmbeddingData { 22 | public string dashboardId; 23 | public string dashboardName; 24 | public string embedUrl; 25 | public string accessToken; 26 | } 27 | 28 | // data required for embedding a dashboard 29 | public class QnaEmbeddingData { 30 | public string datasetId; 31 | public string embedUrl; 32 | public string accessToken; 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ThirdPartyEmbeddingDemo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ThirdPartyEmbeddingDemo")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1142f710-f95c-4333-b06b-7b3ad35f04a4")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Startup.cs: -------------------------------------------------------------------------------- 1 | using Owin; 2 | 3 | namespace ThirdPartyEmbeddingDemo { 4 | 5 | public partial class Startup { 6 | public void Configuration(IAppBuilder app) { 7 | ConfigureAuth(app); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using ThirdPartyEmbeddingDemo.Models 2 | @model LoginViewModel 3 | 4 |
5 |
6 |
7 | @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { 8 | @Html.AntiForgeryToken() 9 |

Enter Wingtip Customer account credentials

10 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 11 |
12 | @Html.LabelFor(m => m.UserName, new { @class = "col-md-4 control-label" }) 13 |
14 | @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" }) 15 | @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" }) 16 |
17 |
18 |
19 | @Html.LabelFor(m => m.Password, new { @class = "col-md-4 control-label" }) 20 |
21 | @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 22 | @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" }) 23 |
24 |
25 |
26 |
27 |
28 | @Html.CheckBoxFor(m => m.RememberMe) 29 | @Html.LabelFor(m => m.RememberMe) 30 |
31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 | } 39 |
40 |
41 | 42 |
43 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 |  2 |
3 | 4 |
5 |

Third-party Power BI Embedding Demo

6 | 7 | @if (!User.Identity.IsAuthenticated) { 8 |
Click the log in link to sign in
9 | } 10 | else { 11 |
The user is currently authenticated as @User.Identity.Name
12 |
13 |
Navigate to the @Html.ActionLink("User Info View", "UserInfo", "Home") to see detailed information about the current user. 14 |
15 | } 16 |
17 | 18 |
-------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Views/Home/UserInfo.cshtml: -------------------------------------------------------------------------------- 1 | @model ThirdPartyEmbeddingDemo.Models.UserIfoViewModel 2 | 3 | @{ 4 | var currentUser = Model; 5 | } 6 | 7 |
8 | 9 |

Current User Info

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | @if (currentUser.HasRoles) { 36 | 37 | 38 | 45 | 46 | } 47 |
User ID@currentUser.UserId
User Name@currentUser.UserName
User Email@currentUser.UserEmail
User Display Name@currentUser.UserDisplayName
User is Admin@currentUser.IsAdmin
User Has Roles@currentUser.HasRoles
User Roles 39 |
    40 | @foreach (var role in currentUser.Roles) { 41 |
  • @role
  • 42 | } 43 |
44 |
48 | 49 |
-------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Views/Reports/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model ThirdPartyEmbeddingDemo.Models.ReportEmbeddingData 2 | 3 | @if (User.IsInRole("Admin")) { 4 | @section toolbar { 5 | 9 | } 10 | } 11 | 12 | 13 |
14 | 15 | 16 | 17 | 70 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Third-Party Embedding Demo 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 33 | 34 | 35 |
36 | @RenderBody() 37 |
38 | 39 | 40 | 41 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNet.Identity 2 | @using ThirdPartyEmbeddingDemo.Models 3 | @using Microsoft.AspNet.Identity.EntityFramework 4 | 5 | @if (Request.IsAuthenticated) { 6 | using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "ml-auto" })) { 7 | @Html.AntiForgeryToken() 8 | 9 | 10 | 11 | ApplicationDbContext context = new ApplicationDbContext(); 12 | var UserManager = new UserManager(new UserStore(context)); 13 | ApplicationUser currentUser = UserManager.FindByName(User.Identity.GetUserName()); 14 | 15 | string ID = currentUser.Id; 16 | string Email = currentUser.Email; 17 | string Username = currentUser.UserName; 18 | 19 | 20 | 27 | } 28 | } 29 | else { 30 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Views/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Demos/ThirdPartyEmbeddingDemo/ThirdPartyEmbeddingDemo/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "chrome", 9 | "request": "launch", 10 | "name": "Launch Chrome", 11 | "url": "http://localhost:8080", 12 | "webRoot": "${workspaceFolder}" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-owns-data-consumer-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "start": "webpack-dev-server --open --history-api-fallback" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@types/react": "^16.4.18", 15 | "@types/react-dom": "^16.0.9", 16 | "@types/react-router": "^4.4.0", 17 | "@types/react-router-dom": "^4.3.1", 18 | "awesome-typescript-loader": "^5.2.1", 19 | "bootstrap": "^4.1.3", 20 | "clean-webpack-plugin": "^0.1.19", 21 | "copy-webpack-plugin": "^4.6.0", 22 | "css-loader": "^0.28.11", 23 | "expose-loader": "^0.7.5", 24 | "file-loader": "^1.1.11", 25 | "html-webpack-plugin": "^3.2.0", 26 | "jquery": "^3.3.1", 27 | "msal": "^1.0.1", 28 | "popper.js": "^1.14.4", 29 | "powerbi-client": "^2.7.4", 30 | "react": "^16.6.0", 31 | "react-dom": "^16.6.0", 32 | "react-router": "^4.3.1", 33 | "react-router-dom": "^4.3.1", 34 | "style-loader": "^0.21.0", 35 | "typescript": "^3.1.6", 36 | "url-loader": "^1.1.2", 37 | "webpack": "^4.24.0", 38 | "webpack-cli": "^3.1.2", 39 | "webpack-dev-server": "^3.1.10" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/AppSettings.ts: -------------------------------------------------------------------------------- 1 | export default class AppSettings { 2 | static aadTenant: string = "MY_TENANT.onMicrosoft.com"; 3 | static clientId: string = ""; 4 | static appId: string = ""; 5 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | padding: 0px; 4 | background-color: orange; 5 | font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif 6 | } 7 | 8 | #left-nav-col { 9 | padding-left: 0; 10 | padding-right: 0; 11 | } 12 | 13 | #content-col { 14 | padding-left: 0; 15 | padding-right: 0; 16 | 17 | } 18 | 19 | #page-container{ 20 | background-color: white; 21 | min-height: 600px; 22 | border-bottom-left-radius: 8px; 23 | border-bottom-right-radius: 8px; 24 | border: 1px solid black; 25 | } 26 | 27 | #embed-container { 28 | height: 600px; 29 | min-height: 600px;; 30 | } 31 | 32 | .content-body { 33 | padding: 24px; 34 | } 35 | 36 | .message-body { 37 | padding-top: 18px; 38 | padding-left: 32px; 39 | font-size: 1.75em; 40 | color: #CCC; 41 | } 42 | 43 | .jumbotron { 44 | padding-top: 18px; 45 | padding-bottom: 16px; 46 | } 47 | 48 | #left-nav { 49 | padding: 8px; 50 | width: 100%; 51 | float: left; 52 | background-color: #EEE; 53 | border: 1px solid #999; 54 | border-bottom-right-radius: 8px; 55 | } 56 | 57 | #left-nav-header { 58 | color: darkblue; 59 | font-size: 14px; 60 | font-weight: bold; 61 | border-bottom: 1px solid darkblue; 62 | margin-bottom: 4px; 63 | } 64 | 65 | #left-nav ul { 66 | padding: 0px; 67 | margin: 0px; 68 | list-style-type: none; 69 | } 70 | 71 | #left-nav li { 72 | border: 0px; 73 | margin: 0px; 74 | } 75 | 76 | #left-nav a, 77 | #left-nav a:hover, 78 | #left-nav a:visited 79 | { 80 | margin: 2px; 81 | padding: 0; 82 | color: black; 83 | font-size: 12px; 84 | font-weight: bold; 85 | text-decoration: none; 86 | } 87 | 88 | 89 | 90 | #left-nav:empty { 91 | display: none; 92 | background-color: red; 93 | } 94 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Link, Route, Switch } from 'react-router-dom'; 3 | 4 | import Banner from "./Banner"; 5 | import TopNav from "./Topnav"; 6 | import Login from "./Login"; 7 | 8 | import ViewHome from './ViewHome/ViewHome'; 9 | import ViewDashboards from './ViewDashboards/ViewDashboards' 10 | import EmbeddedReport from './ViewReports/EmbeddedReport' 11 | import ViewReports from './ViewReports/ViewReports'; 12 | 13 | import SpaAuthService from "./../services/SpaAuthService"; 14 | import PowerBiService from "./../services/PowerBiService"; 15 | 16 | import 'bootstrap/dist/css/bootstrap.min.css'; 17 | import 'bootstrap'; 18 | import './App.css'; 19 | 20 | import IUser from "./../models/IUser"; 21 | 22 | import { 23 | PowerBiDashboard, 24 | PowerBiReport, 25 | PowerBiDataset, 26 | EmbedResources 27 | } from "./../models/PowerBiModels"; 28 | 29 | export interface AppState { 30 | user: IUser; 31 | dashboards: PowerBiDashboard[]; 32 | dashboardsInCache: boolean; 33 | reports: PowerBiReport[]; 34 | reportsInCache: boolean; 35 | datasets: PowerBiDataset[]; 36 | datasetsInCache: boolean 37 | } 38 | 39 | export default class App extends React.Component { 40 | 41 | state: AppState = { 42 | dashboards: [], 43 | reports: [], 44 | datasets: [], 45 | dashboardsInCache: false, 46 | reportsInCache: false, 47 | datasetsInCache: false, 48 | user: { 49 | IsAuthenticated: false, 50 | DisplayName: "", 51 | login: () => { this.loginUser(); }, 52 | logout: () => { this.logoutUser(); } 53 | } 54 | }; 55 | 56 | loginUser = () => { 57 | SpaAuthService.login(); 58 | }; 59 | 60 | logoutUser = () => { 61 | SpaAuthService.logout(); 62 | this.setState({ 63 | user: { 64 | IsAuthenticated: false, 65 | DisplayName: "", 66 | login: this.state.user.login, 67 | logout: this.state.user.logout 68 | } 69 | }); 70 | }; 71 | 72 | 73 | render() { 74 | 75 | return ( 76 |
77 | 78 | 79 | {this.state.user.IsAuthenticated ? : null} 80 | 81 | 82 | 83 | 84 | 85 | } /> 86 | } /> 87 | 88 | 89 |
); 90 | } 91 | 92 | componentDidMount() { 93 | 94 | SpaAuthService.uiUpdateCallback = (userIsAuthenticated: boolean) => { 95 | if (SpaAuthService.userIsAuthenticated) { 96 | console.log(SpaAuthService.userName + " has been authenticated"); 97 | this.setState({ 98 | user: { 99 | IsAuthenticated: true, 100 | DisplayName: SpaAuthService.userDisplayName, 101 | login: this.state.user.login, 102 | logout: this.state.user.logout 103 | } 104 | }); 105 | } 106 | }; 107 | SpaAuthService.init(); 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/Banner.css: -------------------------------------------------------------------------------- 1 | #banner { 2 | padding: 0px; 3 | color: white; 4 | border-bottom: 1px solid black; 5 | } 6 | 7 | #app-icon { 8 | float: left; 9 | height: 47px; 10 | width: 47px; 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | background-image: url('./../images/AppIcon.png') 15 | } 16 | 17 | #app-title { 18 | color: white; 19 | float: left; 20 | display: flex; 21 | align-items: center; 22 | height: 48px; 23 | padding-left: 12px; 24 | font-size: 18px; 25 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/Banner.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Link, NavLink } from 'react-router-dom'; 3 | 4 | import './Banner.css'; 5 | 6 | interface BannerProperties { 7 | appTitle: string; 8 | } 9 | 10 | export default class Banner extends React.Component { 11 | render() { 12 | return ( 13 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/Login.css: -------------------------------------------------------------------------------- 1 | #login { 2 | height: 48px; 3 | float: right; 4 | display: flex; 5 | align-items: center; 6 | padding-top: 6px; 7 | padding-right: 16px; 8 | } 9 | 10 | #login ul { 11 | line-height: 1em; 12 | padding-left: 24px; 13 | margin-bottom: 0; 14 | } 15 | 16 | 17 | #login ul li { 18 | display: inline-block; 19 | margin-right: 16px; 20 | color: #FEBF0F; 21 | } 22 | 23 | #login li a, 24 | #login li a:visited, 25 | #login li a:active{ 26 | color: #FEBF0F; 27 | text-decoration: none; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/Login.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import IUser from "./../models/IUser" 3 | import "./Login.css"; 4 | 5 | interface LoginProperties { 6 | user: IUser; 7 | } 8 | 9 | export default class Login extends React.Component { 10 | 11 | render() { 12 | return ( 13 |
14 | {this.props.user.IsAuthenticated ?
Hello {this.props.user.DisplayName}
: null} 15 |
    16 | {this.props.user.IsAuthenticated ? 17 |
  • Logout
  • : 18 |
  • Sign In
  • 19 | } 20 |
21 |
22 | ); 23 | } 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/TopNav.css: -------------------------------------------------------------------------------- 1 | #top-nav ul { 2 | line-height: 1em; 3 | padding-left: 24px; 4 | } 5 | 6 | #top-nav ul li { 7 | display: inline-block; 8 | margin-right: 16px; 9 | color: #FEBF0F; 10 | } 11 | 12 | #top-nav li a { 13 | color: #FEBF0F; 14 | font-size: 1.0em; 15 | text-decoration: none; 16 | } 17 | 18 | #top-nav li a.active-nav-link { 19 | color: yellow; 20 | } 21 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/TopNav.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Link, NavLink } from 'react-router-dom'; 3 | 4 | import "./TopNav.css"; 5 | 6 | export default class TopNav extends React.Component { 7 | 8 | render() { 9 | return ( 10 |
11 | 25 |
26 | ); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/ViewDashboards/EmbeddedDashboard.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Link } from 'react-router-dom' 3 | 4 | import { PowerBiDashboard } from "./../../models/PowerBiModels"; 5 | import PowerBiEmbeddingService from "./../../services/PowerBiEmbeddingService"; 6 | 7 | interface EmbeddedDashboardProperties { 8 | dashboards: PowerBiDashboard[]; 9 | } 10 | 11 | interface EmbeddedDashboardRouteParams { 12 | id: string; 13 | } 14 | 15 | type EmbeddedDashboardPropertiesWithRouter = 16 | EmbeddedDashboardProperties & 17 | RouteComponentProps; 18 | 19 | class EmbeddedDashboard extends React.Component { 20 | 21 | render() { 22 | let dashboardIdRouteParam: string = this.props.match.params.id; 23 | let noDashboardId = (dashboardIdRouteParam === undefined); 24 | let dashboard: PowerBiDashboard | undefined = this.props.dashboards.find((dashboard: PowerBiDashboard) => dashboard.id == dashboardIdRouteParam); 25 | let badDashboardId: boolean = (dashboardIdRouteParam != "") && (dashboard === undefined) 26 | if (noDashboardId) { 27 | return ( 28 |
29 | click a report to embed it on this page 30 |
); 31 | } 32 | if (badDashboardId) { 33 | return ( 34 |
35 |
'{dashboardIdRouteParam}' is not a valid dashboard id
36 |
); 37 | } 38 | return ( 39 |
40 |
41 |
); 42 | } 43 | 44 | 45 | componentDidUpdate() { 46 | this.updateEmbeddedDashboard(); 47 | } 48 | componentDidMount() { 49 | this.updateEmbeddedDashboard(); 50 | } 51 | 52 | updateEmbeddedDashboard() { 53 | let dashboardIdRouteParam: string = this.props.match.params.id; 54 | let dashboard: PowerBiDashboard | undefined = this.props.dashboards.find((dashboard: PowerBiDashboard) => dashboard.id == dashboardIdRouteParam); 55 | if (dashboard) { 56 | var embedContainer: HTMLElement = document.getElementById('embed-container')!; 57 | PowerBiEmbeddingService.embedDashboard(dashboard!, embedContainer); 58 | } 59 | } 60 | 61 | 62 | } 63 | 64 | export default withRouter(EmbeddedDashboard); 65 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/ViewDashboards/ViewDashboards.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Route, Switch, Link, match } from 'react-router-dom' 3 | 4 | import PowerBiService from "./../../services/PowerBiService"; 5 | 6 | import App from './../App' 7 | import EmbeddeDashboard from './EmbeddedDashboard'; 8 | 9 | import { 10 | PowerBiDashboard 11 | } from "./../../models/PowerBiModels"; 12 | import EmbeddedDashboard from './EmbeddedDashboard'; 13 | 14 | interface ViewDashboardsProperties { 15 | app: App 16 | } 17 | 18 | interface EmbeddedDashboardRouteParams { 19 | id: string; 20 | } 21 | 22 | type ViewDashboardsPropertiesWithRouter = 23 | ViewDashboardsProperties & 24 | RouteComponentProps; 25 | 26 | interface ViewDashboardsState { 27 | loadingDashboards: boolean 28 | } 29 | 30 | class ViewDashboards extends React.Component { 31 | 32 | state = { 33 | loadingDashboards: false 34 | }; 35 | 36 | render() { 37 | return ( 38 |
39 |
40 |
41 |
42 |
Embed Dashboards
43 | {this.state.loadingDashboards ?
loading...
: null} 44 | 51 |
52 |
53 |
54 | 55 |
56 |
57 |
58 | ); 59 | } 60 | 61 | 62 | componentDidMount() { 63 | this.getDashboards(); 64 | } 65 | 66 | getDashboards = () => { 67 | if (!this.props.app.state.dashboardsInCache) { 68 | this.setState({ loadingDashboards: true }); 69 | PowerBiService.GetDashboards().then((dashboards: PowerBiDashboard[]) => { 70 | this.props.app.setState({ 71 | dashboards: dashboards, 72 | dashboardsInCache: true 73 | }); 74 | this.setState({ loadingDashboards: false }); 75 | }); 76 | } 77 | } 78 | } 79 | 80 | export default withRouter(ViewDashboards); -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/ViewHome/ViewHome.css: -------------------------------------------------------------------------------- 1 | #view-home h4 { 2 | color: darkblue; 3 | border-bottom: 1px solid darkblue; 4 | } 5 | 6 | #view-home h4 { 7 | color: darkblue; 8 | border-bottom: 1px solid darkblue; 9 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/ViewHome/ViewHome.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './ViewHome.css'; 3 | 4 | export default class ViewHome extends React.Component { 5 | render() { 6 | return ( 7 |
8 |
9 |
10 |

React Power BI Demo App

11 |

This is a demo of a single page application (SPA) that use React.js and Power BI Embedding.

12 |
13 |
14 |
15 |
16 |

React.js is awesome

17 |
If you don't know how to develop using react.js, you should learn about this popular JavaScript library because it 18 | provides a powerful yet relatively simple way to develop single page applications with client-side behaviors. 19 |
20 |
21 |
22 |

Power BI Embedded is game changing

23 |
Learning how to develop with Power BI embedding will help you integrate professional looking reports and dashboards into your custom applications.
24 |
25 |
26 |
27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/ViewReports/EmbeddedReport.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Link } from 'react-router-dom' 3 | 4 | import { PowerBiReport } from "./../../models/PowerBiModels"; 5 | import PowerBiEmbeddingService from "./../../services/PowerBiEmbeddingService"; 6 | 7 | import EmbeddedReportToolbar from './EmbeddedReportToolbar'; 8 | 9 | import * as powerbi from "powerbi-client"; 10 | import * as pbimodels from "powerbi-models"; 11 | 12 | interface EmbeddedReportProperties { 13 | reports: PowerBiReport[] 14 | } 15 | 16 | interface EmbeddedReportRouteParams { 17 | id: string; 18 | } 19 | 20 | type EmbeddedReportPropertiesWithRouter = 21 | EmbeddedReportProperties & 22 | RouteComponentProps; 23 | 24 | interface EmbeddedReportState { 25 | embeddedReport: powerbi.Report | undefined 26 | } 27 | 28 | class EmbeddedReport extends React.Component { 29 | 30 | state: EmbeddedReportState = { 31 | embeddedReport: undefined 32 | } 33 | 34 | render() { 35 | let reportIdRouteParam: string = this.props.match.params.id; 36 | let noReportId = (reportIdRouteParam === undefined); 37 | let report: PowerBiReport | undefined = this.props.reports.find((report: PowerBiReport) => report.id == reportIdRouteParam); 38 | let badReportId: boolean = (this.props.reports.length > 0) && (reportIdRouteParam != "") && (report === undefined) 39 | if (noReportId) { 40 | return ( 41 |
42 | click report in left nav to open it 43 |
); 44 | } 45 | if (badReportId) { 46 | return ( 47 |
48 |
'{reportIdRouteParam}' is not a valid report id
49 |
); 50 | } 51 | return ( 52 |
53 | {(this.state.embeddedReport !== undefined ? : null)} 54 |
55 |
); 56 | } 57 | 58 | 59 | componentWillUpdate() { 60 | 61 | } 62 | 63 | componentDidUpdate(previousProps: EmbeddedReportPropertiesWithRouter, PreviousState: any) { 64 | console.log("componentDidUpdate"); 65 | console.log(previousProps); 66 | console.log(this.props); 67 | let routeHasChanged: boolean = (this.props.match.params.id != previousProps.match.params.id); 68 | let reportsRefreshed = this.props.reports !== previousProps.reports; 69 | if (routeHasChanged || reportsRefreshed) { 70 | this.updateEmbeddedReport(); 71 | } 72 | } 73 | 74 | componentDidMount() { 75 | console.log("componentDidMount"); 76 | //this.updateEmbeddedReport(); 77 | } 78 | 79 | updateEmbeddedReport() { 80 | let reportIdRouteParam: string = this.props.match.params.id; 81 | let report: PowerBiReport | undefined = this.props.reports.find((report: PowerBiReport) => report.id == reportIdRouteParam); 82 | if (report) { 83 | var embedContainer: HTMLElement = document.getElementById('embed-container')!; 84 | var embeddedReport: powerbi.Report = PowerBiEmbeddingService.embedReport(report!, embedContainer); 85 | this.setState({ embeddedReport: embeddedReport }); 86 | } 87 | } 88 | } 89 | 90 | export default withRouter(EmbeddedReport); -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/ViewReports/EmbeddedReportToolbar.css: -------------------------------------------------------------------------------- 1 | #embedded-report-toolbar{ 2 | background-color: #CCC; 3 | text-align: right; 4 | } 5 | 6 | #embedded-report-toolbar button { 7 | color: #333; 8 | border-style: none; 9 | padding: 2px; 10 | background-color: transparent; 11 | font-size: 0.7em; 12 | margin: 2px; 13 | margin-right: 8px; 14 | text-decoration: none; 15 | } 16 | 17 | 18 | #embedded-report-toolbar button:focus { 19 | outline:0; 20 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/ViewReports/EmbeddedReportToolbar.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import './EmbeddedReportToolbar.css'; 4 | 5 | import * as powerbi from "powerbi-client"; 6 | import * as pbimodels from "powerbi-models"; 7 | 8 | interface EmbeddedReportToolbarProperties { 9 | embeddedReport: powerbi.Report 10 | } 11 | export default class EmbeddedReport extends React.Component { 12 | 13 | render() { 14 | return ( 15 |
16 |
17 | 18 | 19 |
20 |
); 21 | } 22 | 23 | private viewMode = "view"; 24 | 25 | enterFullScreenMode() { 26 | this.props.embeddedReport.fullscreen(); 27 | } 28 | 29 | printReport() { 30 | this.props.embeddedReport.print(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/components/ViewReports/ViewReports.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { withRouter, RouteComponentProps, Route, Switch, Link, match } from 'react-router-dom' 3 | 4 | import PowerBiService from "./../../services/PowerBiService"; 5 | 6 | import App from './../App' 7 | import EmbeddedReport from './EmbeddedReport'; 8 | 9 | import { 10 | PowerBiReport 11 | } from "./../../models/PowerBiModels"; 12 | 13 | interface ViewReportsProperties { 14 | app: App 15 | } 16 | 17 | interface EmbeddedReportRouteParams { 18 | id: string; 19 | } 20 | 21 | type ViewReportsPropertiesWithRouter = 22 | ViewReportsProperties & 23 | RouteComponentProps; 24 | 25 | interface ViewReportsState { 26 | loadingReports: boolean 27 | } 28 | 29 | class ViewReports extends React.Component { 30 | 31 | state = { 32 | loadingReports: false 33 | } 34 | 35 | render() { 36 | return ( 37 |
38 |
39 |
40 |
41 |
Embed Report
42 | {this.state.loadingReports ?
loading...
: null} 43 | 50 |
51 |
52 |
53 | 54 |
55 |
56 |
57 | ); 58 | } 59 | 60 | componentDidMount() { 61 | this.getReports(); 62 | } 63 | 64 | getReports = () => { 65 | if (!this.props.app.state.reportsInCache) { 66 | this.setState({ loadingReports: true }) 67 | PowerBiService.GetReports().then((reports: PowerBiReport[]) => { 68 | this.props.app.setState({ 69 | reports: reports, 70 | reportsInCache: true, 71 | }) 72 | this.setState({ loadingReports: false }) 73 | }); 74 | } 75 | } 76 | 77 | } 78 | 79 | export default withRouter(ViewReports); -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/UserOwsDataConsumerApp/src/favicon.ico -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/images/AppIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Demos/UserOwsDataConsumerApp/src/images/AppIcon.png -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CPT React Demo App 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { render } from 'react-dom'; 3 | import App from './components/App'; 4 | import { HashRouter } from 'react-router-dom' 5 | 6 | var topLevelAppComponent = 7 | 8 | 9 | ; 10 | 11 | var target = document.getElementById('react-target'); 12 | 13 | render(topLevelAppComponent, target); 14 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/models/IUser.ts: -------------------------------------------------------------------------------- 1 | export default interface IUser { 2 | IsAuthenticated: boolean; 3 | DisplayName?: string; 4 | login(): void; 5 | logout(): void; 6 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/models/PowerBiModels.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface PowerBiDashboardTile { 3 | dashboardId: string; 4 | tileId: string; 5 | title: string; 6 | embedUrl: string; 7 | } 8 | 9 | export interface PowerBiDashboard { 10 | displayName: string; 11 | embedUrl: string; 12 | id: string; 13 | } 14 | 15 | export interface PowerBiReport { 16 | id: string; 17 | embedUrl: string; 18 | name: string; 19 | webUrl: string; 20 | datasetId: string; 21 | } 22 | 23 | 24 | export interface PowerBiDataset { 25 | name: string; 26 | embedUrl: string; 27 | id: string; 28 | } 29 | 30 | export interface EmbedResources { 31 | dashboards: PowerBiDashboard[]; 32 | reports: PowerBiReport[]; 33 | datasets: PowerBiDataset[]; 34 | } 35 | 36 | export interface EmbedDataNewReport { 37 | workspaceId: string; 38 | datasetId: string; 39 | embedUrl: string; 40 | accessToken: string; 41 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/src/services/PowerBiService.ts: -------------------------------------------------------------------------------- 1 | import AppSettings from './../AppSettings' 2 | 3 | import { 4 | PowerBiDashboard, 5 | PowerBiReport, 6 | PowerBiDataset, 7 | PowerBiDashboardTile 8 | } 9 | from "./../models/PowerBiModels"; 10 | 11 | import SpaAuthService from "./SpaAuthService"; 12 | 13 | export default class PowerBiService { 14 | 15 | static appId = AppSettings.appId; 16 | static apiRoot: string = "https://api.powerbi.com/v1.0/myorg/"; 17 | static appApiRoot = PowerBiService.apiRoot + "apps/" + PowerBiService.appId + "/"; 18 | 19 | static GetReports = (): Promise => { 20 | var restUrl = PowerBiService.appApiRoot + "Reports/"; 21 | return fetch(restUrl, { 22 | headers: { 23 | "Accept": "application/json;odata.metadata=minimal;", 24 | "Authorization": "Bearer " + SpaAuthService.accessToken 25 | } 26 | }).then(response => response.json()) 27 | .then(response => { return response.value; }); 28 | } 29 | 30 | static GetDashboards = (): Promise => { 31 | var restUrl = PowerBiService.appApiRoot + "Dashboards/"; 32 | return fetch(restUrl, { 33 | headers: { 34 | "Accept": "application/json;odata.metadata=minimal;", 35 | "Authorization": "Bearer " + SpaAuthService.accessToken 36 | } 37 | }).then(response => response.json()) 38 | .then(response => { return response.value; }); 39 | } 40 | 41 | static GetDashboardTiles = (dashboardId: string): Promise => { 42 | var restUrl = PowerBiService.appApiRoot + "Dashboards/" + dashboardId + "/tiles/"; 43 | return fetch(restUrl, { 44 | headers: { 45 | "Accept": "application/json;odata.metadata=minimal;", 46 | "Authorization": "Bearer " + SpaAuthService.accessToken 47 | } 48 | }).then(response => response.json()) 49 | .then(response => { return response.value; }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "module": "commonjs", 5 | "sourceMap": true, 6 | "target": "es5", 7 | "lib": ["es6", "dom"], 8 | "noImplicitReturns": true, 9 | "noImplicitThis": true, 10 | "noImplicitAny": true, 11 | "strictNullChecks": true, 12 | "experimentalDecorators": true 13 | }, 14 | "exclude": [ 15 | "node_modules" 16 | ] 17 | } -------------------------------------------------------------------------------- /Demos/UserOwsDataConsumerApp/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 5 | const CleanWebpackPlugin = require('clean-webpack-plugin') 6 | 7 | module.exports = { 8 | entry: './src/index.tsx', 9 | output: { 10 | filename: 'scripts/bundle.js', 11 | path: path.resolve(__dirname, 'dist'), 12 | }, 13 | resolve: { 14 | extensions: ['.js', '.json', '.ts', '.tsx'], 15 | }, 16 | plugins: [ 17 | new CleanWebpackPlugin(['dist']), 18 | new HtmlWebpackPlugin({ template: path.join(__dirname, 'src', 'index.html') }), 19 | new CopyWebpackPlugin([{ from: './src/favicon.ico', to: 'favicon.ico' }]) 20 | ], 21 | module: { 22 | rules: [ 23 | { test: /\.(ts|tsx)$/, loader: 'awesome-typescript-loader' }, 24 | { test: /\.css$/, use: ['style-loader', 'css-loader'] }, 25 | { test: /\.(png|jpg|gif)$/, use: [{ loader: 'url-loader', options: { limit: 8192 } }] } 26 | ], 27 | }, 28 | mode: "development", 29 | devtool: 'source-map', 30 | devtool: 'cheap-eval-source-map' 31 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Critical Path Training 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 | -------------------------------------------------------------------------------- /PBIX/Northwind Retro.pbix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/PBIX/Northwind Retro.pbix -------------------------------------------------------------------------------- /PBIX/Wingtip Sales Analysis with RLS.pbix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/PBIX/Wingtip Sales Analysis with RLS.pbix -------------------------------------------------------------------------------- /PBIX/Wingtip Sales Analysis.pbix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/PBIX/Wingtip Sales Analysis.pbix -------------------------------------------------------------------------------- /PBIX/Wingtip Sales DirectQuery.pbix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/PBIX/Wingtip Sales DirectQuery.pbix -------------------------------------------------------------------------------- /Presentations/DeveloperQuickStartIntoPowerBIEmbedding.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Presentations/DeveloperQuickStartIntoPowerBIEmbedding.pdf -------------------------------------------------------------------------------- /Presentations/Power BI Embedded - April 2018 - Summit in Dublin .pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Presentations/Power BI Embedded - April 2018 - Summit in Dublin .pptx -------------------------------------------------------------------------------- /Presentations/Power BI Embedded - December 2017.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Presentations/Power BI Embedded - December 2017.pptx -------------------------------------------------------------------------------- /Presentations/PowerBiEmbedding_MBAS_July2018.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Presentations/PowerBiEmbedding_MBAS_July2018.pdf -------------------------------------------------------------------------------- /Presentations/PowerBiEmbedding_MBAS_July2018.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Presentations/PowerBiEmbedding_MBAS_July2018.pptx -------------------------------------------------------------------------------- /Presentations/PowerBiEmbedding_Oct2018.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Presentations/PowerBiEmbedding_Oct2018.pptx -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ted Pattison's Power BI Embedded Demo Files 2 | This repository contain the resources and sample files associated with Ted Pattison's Power BI Embedded webinar 3 | -------------------------------------------------------------------------------- /Scripts/AppOwnsDataApp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Scripts/AppOwnsDataApp.txt -------------------------------------------------------------------------------- /Scripts/CreateADGroupForPowerBiApps.ps1: -------------------------------------------------------------------------------- 1 | # log into Azure AD 2 | $userName = "user1@MY_TENANT.onMicrosoft.com" 3 | $password = "" 4 | 5 | $securePassword = ConvertTo-SecureString –String $password –AsPlainText -Force 6 | $credential = New-Object –TypeName System.Management.Automation.PSCredential ` 7 | –ArgumentList $userName, $securePassword 8 | 9 | $authResult = Connect-AzureAD -Credential $credential 10 | 11 | $adSecurityGroupName = "Power BI Apps" 12 | 13 | $adSecurityGroup = 14 | `New-AzureADGroup ` 15 | -DisplayName $adSecurityGroupName ` 16 | -SecurityEnabled $true ` 17 | -MailEnabled $false ` 18 | -MailNickName notSet 19 | 20 | $adSecurityGroup | Format-Table DisplayName, ObjectId -------------------------------------------------------------------------------- /Scripts/DisplayPowerBiAPiPermissions.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Scripts/DisplayPowerBiAPiPermissions.ps1 -------------------------------------------------------------------------------- /Scripts/MyAzureADApp.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Scripts/MyAzureADApp.txt -------------------------------------------------------------------------------- /Scripts/PowerBiServicePermissions.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Scripts/PowerBiServicePermissions.txt -------------------------------------------------------------------------------- /Scripts/RegisterPowerBIDaySPA.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CriticalPathTraining/PowerBiEmbedded/e20bc19e3f4fd933f00014cbfc3d3b031bb84748/Scripts/RegisterPowerBIDaySPA.ps1 --------------------------------------------------------------------------------