├── .gitignore ├── Capabilities ├── AdvancedEditMode.md ├── Capabilities.md ├── DataViewMappings.md ├── Drilldown.md ├── Gradient.md ├── Highlighting.md ├── Objects.md ├── Sorting.md └── images │ ├── CategoricalData.png │ ├── CategoricalDataView.png │ ├── CategoricalValuesDataView.png │ ├── DataAggregation.png │ ├── EditMode.PNG │ ├── SampleData.png │ ├── Sorting.png │ ├── TableData.png │ ├── TableDataView.png │ ├── addDrillDown2.PNG │ ├── highlightDataView.png │ └── highlightDataViewSupports.png ├── ChangeLog.md ├── Glossary.md ├── RVisualTutorial ├── CorrplotScript.md ├── CreateNewVisual.md ├── CreateRHTML.md ├── InputValidationInR.md ├── PropertiesPane.md ├── TutorialFunnelPlot │ ├── README.md │ ├── RscriptShowcase │ │ ├── Icon4Store300x300.png │ │ ├── ScriptInstallPackagesWithWorkaroundsFunnel.R │ │ └── funnelPlot_RinPBI_showcase.pbix │ ├── chapter1_R │ │ ├── dataset.csv │ │ ├── script_R_v1_00.r │ │ └── script_R_v1_01.r │ ├── chapter2_Rvisual │ │ ├── dataset.csv │ │ ├── funnelPlot_Rvisual.pbix │ │ └── script_RV_v2_00.r │ ├── chapter3_RCustomVisual │ │ ├── dataset.csv │ │ ├── funnelPlot_RCustomVisual.pbix │ │ ├── funnelRvisual_v01 │ │ │ ├── .npmignore │ │ │ ├── .vscode │ │ │ │ ├── launch.json │ │ │ │ └── settings.json │ │ │ ├── assets │ │ │ │ └── icon.png │ │ │ ├── capabilities.json │ │ │ ├── capabilities_changes.PNG │ │ │ ├── capabilities_old.json │ │ │ ├── dependencies.json │ │ │ ├── dependencies_changes.PNG │ │ │ ├── dependencies_old.json │ │ │ ├── dist │ │ │ │ └── funnelRvisualVer01.pbiviz │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── pbiviz.json │ │ │ ├── script.r │ │ │ ├── src │ │ │ │ ├── settings.ts │ │ │ │ └── visual.ts │ │ │ ├── style │ │ │ │ └── visual.less │ │ │ ├── tsconfig.json │ │ │ └── tslint.json │ │ ├── funnelRvisual_v02 │ │ │ ├── .npmignore │ │ │ ├── .vscode │ │ │ │ ├── launch.json │ │ │ │ └── settings.json │ │ │ ├── assets │ │ │ │ └── icon.png │ │ │ ├── capabilities.json │ │ │ ├── capabilities_before_vs_after.PNG │ │ │ ├── capabilities_old.json │ │ │ ├── dependencies.json │ │ │ ├── dist │ │ │ │ └── funnelRvisualVer02.pbiviz │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── pbiviz.json │ │ │ ├── script.r │ │ │ ├── script_old.r │ │ │ ├── script_r_before_vs_after.PNG │ │ │ ├── src │ │ │ │ ├── settings.ts │ │ │ │ └── visual.ts │ │ │ ├── style │ │ │ │ └── visual.less │ │ │ ├── tsconfig.json │ │ │ └── tslint.json │ │ └── funnelRvisual_v03 │ │ │ ├── .npmignore │ │ │ ├── .vscode │ │ │ ├── launch.json │ │ │ └── settings.json │ │ │ ├── assets │ │ │ └── icon.png │ │ │ ├── capabilities.json │ │ │ ├── capabilities_before_after.PNG │ │ │ ├── capabilities_old.json │ │ │ ├── dependencies.json │ │ │ ├── dist │ │ │ └── funnelRvisualVer03.pbiviz │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── pbiviz.json │ │ │ ├── script.r │ │ │ ├── script_old.r │ │ │ ├── script_r_before_after_1.png │ │ │ ├── settings_ts_before_after.PNG │ │ │ ├── src │ │ │ ├── settings.ts │ │ │ ├── settings_old.ts │ │ │ └── visual.ts │ │ │ ├── style │ │ │ └── visual.less │ │ │ ├── tsconfig.json │ │ │ └── tslint.json │ ├── chapter4_RHTMLCustomVisual │ │ ├── funnelRHTMLvisual_v01 │ │ │ ├── .npmignore │ │ │ ├── .vscode │ │ │ │ ├── launch.json │ │ │ │ └── settings.json │ │ │ ├── assets │ │ │ │ ├── icon.png │ │ │ │ └── icon_old.png │ │ │ ├── capabilities.json │ │ │ ├── capabilities_befor_after.PNG │ │ │ ├── capabilities_old.json │ │ │ ├── dependencies.json │ │ │ ├── dependencies_old.json │ │ │ ├── dist │ │ │ │ └── funnelRHTMLvisual.pbiviz │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── pbiviz.json │ │ │ ├── r_files │ │ │ │ ├── flatten_HTML.r │ │ │ │ └── utils.r │ │ │ ├── script.r │ │ │ ├── script_befor_after_1.PNG │ │ │ ├── script_befor_after_2.PNG │ │ │ ├── script_old.r │ │ │ ├── script_template.r │ │ │ ├── src │ │ │ │ ├── htmlInjectionUtility.ts │ │ │ │ ├── settings.ts │ │ │ │ ├── settings_old.ts │ │ │ │ └── visual.ts │ │ │ ├── style │ │ │ │ └── visual.less │ │ │ ├── tsconfig.json │ │ │ └── tslint.json │ │ └── multipleRHTML │ │ │ ├── .vscode │ │ │ ├── launch.json │ │ │ └── settings.json │ │ │ ├── assets │ │ │ ├── Capture.PNG │ │ │ ├── CaptureSample.PNG │ │ │ ├── CaptureSampleService.PNG │ │ │ ├── icon.png │ │ │ └── sample.pbix │ │ │ ├── capabilities.json │ │ │ ├── dependencies.json │ │ │ ├── dist │ │ │ └── multipleRHTML.pbiviz │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── pbiviz.json │ │ │ ├── r_files │ │ │ ├── ScriptInstallPackagesWithWorkaroundsMultipleHTML.R │ │ │ └── flatten_HTML.r │ │ │ ├── script.r │ │ │ ├── src │ │ │ ├── htmlInjectionUtility.ts │ │ │ ├── settings.ts │ │ │ └── visual.ts │ │ │ ├── style │ │ │ └── visual.less │ │ │ ├── tsconfig.json │ │ │ └── tslint.json │ ├── dataset.csv │ ├── fp.JPG │ ├── funnelPlot_RinPBI.pbix │ ├── imgs │ │ ├── Capture01TO02.PNG │ │ ├── Capture02TO03.PNG │ │ ├── CaptureCV01.PNG │ │ ├── CaptureCV02.PNG │ │ ├── CaptureCV02_1.PNG │ │ ├── CaptureCV03.PNG │ │ ├── CaptureNetworkD3.PNG │ │ └── out.html │ └── tutorialScript.txt └── images │ ├── BasicCorrplot.png │ ├── BasicHTMLPlot.png │ ├── BasicPlot.png │ ├── EnumPropertyPane.png │ └── PieMethod.png ├── Readme.md ├── Roadmap └── README.md ├── Samples └── circle.ts ├── Tutorial ├── @Types.md ├── BookmarksSupport.md ├── ColorPalette.md ├── DataBinding.md ├── DataBoundObjects.md ├── ExternalLibraries.md ├── LaunchURL.md ├── MobileGuideline.md ├── ProfessionalVisualGuidline.md ├── SampleSlicerSync.pbix ├── Selection.md ├── SlicerSynchronizationSupport.md ├── SliderControl.md ├── StaticObjects.md ├── StaticVisual.md ├── SubmissionCommonProblems.md ├── SubmissionTesting.md ├── SubmittingToGallery.md ├── ToolTips.md ├── Utils.md ├── VisualsAPIsMigrationGuidline.md └── images │ ├── AddTypings.png │ ├── DataBinding.png │ ├── ExternalLibraries.png │ ├── InstallTypings.png │ ├── MakeExternalsDirectory.png │ ├── ObjectDataBoundProperty.png │ ├── ObjectDataBoundPropertyInSrc.png │ ├── ObjectShowProperty.png │ ├── PropertyPane.png │ ├── SampleBarChart.png │ ├── TimelinesBookmarksSupport.png │ ├── UsingTypings.png │ ├── enabled-sync-slicer-in-capabilities.PNG │ ├── launchURLtoggle.png │ └── sync-slicers-panel.PNG ├── Visual ├── AllowInteractions.md ├── IVisualApi.md ├── IVisualHost.md ├── Locale.md ├── Selection.md ├── Tooltips.md ├── Visual.md └── fetchMoreData.md ├── VisualProject.md ├── images ├── CreateLocalizationManager.png ├── DataRoleDisplay.png ├── DataViewMappingResultSingle.png ├── GetDisplayName.png ├── LocaleInSampleBarChart.png ├── MultiVisualSelection.png ├── NewResjson.png ├── NewStringsEn.png ├── NewStringsRu.png ├── StackedColumnSelected.png ├── StackedColumnSelectedBetter.png ├── TooltipsInSampleBarChart.png ├── WebServiceSettings.png ├── addDrillDown2.png ├── displayNameKey.png ├── hebrewStringResource.png ├── localizedPropertyPane.png ├── propertyPane.png ├── stringResourcePath.png └── stringResourcesFiles.png └── tools ├── CertificateAddOSX.md ├── CertificateAddWindows.md ├── CertificateRemoveOSX.md ├── CertificateRemoveWindows.md ├── CertificateSetup.md ├── CreateCertificate.md ├── DebugVisualSetup.md ├── README.md ├── debugging.md ├── images ├── breakOnErrors_chrome.png ├── breakOnErrors_edge.png ├── debugVisual.png ├── mac0.png ├── mac1.png ├── mac2.png ├── macRemove1.png ├── macRemove2.png ├── macRemove3.png ├── macRemove4.png ├── pbivizStart.png ├── portalEnable1.png ├── portalEnable2.png ├── portalEnable3.png ├── portalEnable4.png ├── windows0.png ├── windows1.png ├── windows2.png ├── windows3.png ├── windows4.png ├── windows5.png ├── windows6.png ├── windowsRemove1.png ├── windowsRemove2.png ├── windowsRemove3.png ├── windowsRemove4.png └── windowsRemove5.png └── usage.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .tmp 4 | .api 5 | .api/* 6 | *.log 7 | RVisualTutorial/TutorialFunnelPlot/chapter1_R/.Rhistory 8 | -------------------------------------------------------------------------------- /Capabilities/AdvancedEditMode.md: -------------------------------------------------------------------------------- 1 | # Advanced Edit Mode Support 2 | 3 | Visuals that require advanced UI controls can declare support of Advanced Edit Mode. 4 | If supported, when in report editing mode, an `Edit` button will appear in the visual's menu. 5 | When the `Edit` button is clicked, EditMode is set to `Advanced`. 6 | The visual can use the EditMode flag to determine whether or not it should display such UI controls. 7 | 8 | By default, the visual does not support Advanced Edit Mode. 9 | If a different behavior is required, it should be explicitly stated in the visual's `capabilities.json` file, by setting the `advancedEditModeSupport` property. 10 | 11 | The possible values are: 12 | 13 | - 0 - NotSupported 14 | 15 | - 1 - SupportedNoAction 16 | 17 | - 2 - SupportedInFocus 18 | 19 | ## Entering Advanced Edit Mode 20 | `Edit` button will be visible if: 21 | - 1 - `advancedEditModeSupport` property set in capabilities.json to either `SupportedNoAction` or `SupportedInFocus` 22 | - 2 - The visual is viewed in report editing mode. 23 | If `advancedEditModeSupport` property is missing from capabilities.json, or set to `NotSupported`, the 'Edit' button will not appear. 24 | 25 | 26 | ![Enter edit mode](images/EditMode.PNG) 27 | 28 | When the user clicks on `Edit`, the visual will get an update() call with EditMode set to `Advanced`. 29 | According to the value set in the capabilities, the following will occur: 30 | * `SupportedNoAction` - No further action by the host. 31 | * `SupportedInFocus` - The host pops out the visual into in focus mode. 32 | -------------------------------------------------------------------------------- /Capabilities/Drilldown.md: -------------------------------------------------------------------------------- 1 | # Drill down in a custom visual 2 | 3 | Custom visuals are capable of using PowerBI's drill down. 4 | 5 | Read more about Power BI drill down [here](https://powerbi.microsoft.com/en-us/documentation/powerbi-service-drill-down-in-a-visualization/) 6 | 7 | 8 | ## How to add drill down support to your custom visual 9 | 10 | To support drill down in your visual, add a new field to "capabilities.json" named `drilldown` which has one property: 11 | 12 | **roles** - the name of the dataRole you want to enable drill down on. 13 | > **NOTE:** 14 | The drill down dataRole must be of 'Grouping' type. 15 | "max" property in the dataRole conditions must be set to 1. 16 | 17 | Once you add the role to `drilldown`, users can drag multiple fields into the data role. 18 | 19 | example: 20 | 21 | ![Adding Drill down](../images/addDrillDown2.png) 22 | -------------------------------------------------------------------------------- /Capabilities/Gradient.md: -------------------------------------------------------------------------------- 1 | # Gradient property 2 | The gradient property is a property that cannot be set as a standard property. Instead, you need to set a rule for substitution of the color picker property (fill type). See the example below. 3 | 4 | ```json 5 | "properties": { 6 | "showAllDataPoints": { 7 | "displayName": "Show all", 8 | "displayNameKey": "Visual_DataPoint_Show_All", 9 | "type": { 10 | "bool": true 11 | } 12 | }, 13 | "fill": { 14 | "displayName": "Fill", 15 | "displayNameKey": "Visual_Fill", 16 | "type": { 17 | "fill": { 18 | "solid": { 19 | "color": true 20 | } 21 | } 22 | } 23 | }, 24 | "fillRule": { 25 | "displayName": "Color saturation", 26 | "displayNameKey": "Visual_ColorSaturation", 27 | "type": { 28 | "fillRule": {} 29 | }, 30 | "rule": { 31 | "inputRole": "Gradient", 32 | "output": { 33 | "property": "fill", 34 | "selector": [ 35 | "Category" 36 | ] 37 | } 38 | } 39 | } 40 | } 41 | ``` 42 | Please, pay attention to the `"fill"` and `"fillRule"` properties. The first is the color picker, the second is the substitution rule for gradient that will substitute the "fill" property `visually` when the rule conditions will be met. 43 | 44 | This link between the fill property and the substitution rule is set in `"rule"`->`"output"` section of the `"fillRule"` property. 45 | 46 | `"Rule"`->`"InputRole"` sets which data role triggers the rule (condition). In this example, if data role `"Gradient"` contains data then the rule will be applied for the `"fill"` property. 47 | 48 | Below you can see an example of the data role that triggers the fill rule (`the last item`). 49 | 50 | ```json 51 | "dataRoles": [ 52 | { 53 | "name": "Category", 54 | "kind": "Grouping", 55 | "displayName": "Details", 56 | "displayNameKey": "Role_DisplayName_Details" 57 | }, 58 | { 59 | "name": "Series", 60 | "kind": "Grouping", 61 | "displayName": "Legend", 62 | "displayNameKey": "Role_DisplayName_Legend" 63 | }, 64 | { 65 | "name": "Gradient", 66 | "kind": "Measure", 67 | "displayName": "Color saturation", 68 | "displayNameKey": "Role_DisplayName_Gradient" 69 | } 70 | ] 71 | ``` 72 | -------------------------------------------------------------------------------- /Capabilities/Highlighting.md: -------------------------------------------------------------------------------- 1 | # Highlighting 2 | 3 | By default whenever an element is selected the `values` array in the `dataView` object will be filtered to just the selected values. This will cause all other visuals on the page to display just the selected data. 4 | 5 | ![highlight dataview default behavior](images/highlightDataView.png) 6 | 7 | ## supportsHighlight 8 | 9 | If you set the `supportsHighlight` property in your `capabilities.json` to `true` you will receive the full unfiltered `values` array along with a `highlights` array. The `highlights` array will be the same length as the values array and any non-selected values will be set to `null`. With this property enabled it is the visual's responsiblity to highlight the appropriate data by comparing the `values` array to the `highlights` array. 10 | 11 | ![highlight dataview supportsHighlight](images/highlightDataViewSupports.png) 12 | 13 | In the example above you'll notice that the one bar that is selected is the only value in the highlights array. It is also important to note there could be multiple selections and partial highlight (where the corresponding numeric value in the values and highlights arrays will be present but different) -------------------------------------------------------------------------------- /Capabilities/Sorting.md: -------------------------------------------------------------------------------- 1 | # Sorting 2 | 3 | `Sorting` specifies the default sorting behavior for the visual. 4 | Capability requires one of the parameters described below: 5 | 6 | ## Default sorting 7 | 8 | The `default` option is the simplest form. It allows sorting the data presented in the 'DataMappings' section. 9 | This option enables sorting of the 'DataMappings' by the user and to specify the sorting direction. 10 | 11 | ```json 12 | "sorting": { 13 | "default": { } 14 | } 15 | ``` 16 | 17 | ![](images/Sorting.png) 18 | 19 | ## Implicit sorting 20 | 21 | `implicit` is sorting with array parameter - `clauses` which describes sorting for each data roles. 22 | `implicit` means that visual's user can't change the sorting order. 23 | Power BI will not display sorting options in visual's menu. However, Power BI will sort data according to specified settings. 24 | 25 | `clauses` params can contain several objects with two parameters: 26 | 27 | - `role` - determines `DataMapping` for sorting. 28 | 29 | - `direction` - determines sort direction (1 = Ascending, 2 = Descending). 30 | 31 | ```json 32 | "sorting": { 33 | "implicit": { 34 | "clauses": [ 35 | { 36 | "role": "category", 37 | "direction": 1 38 | }, 39 | { 40 | "role": "measure", 41 | "direction": 2 42 | } 43 | ] 44 | } 45 | } 46 | ``` 47 | 48 | ## Custom sorting 49 | 50 | `custom` means the sorting is managed by developer in visual's code -------------------------------------------------------------------------------- /Capabilities/images/CategoricalData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/CategoricalData.png -------------------------------------------------------------------------------- /Capabilities/images/CategoricalDataView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/CategoricalDataView.png -------------------------------------------------------------------------------- /Capabilities/images/CategoricalValuesDataView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/CategoricalValuesDataView.png -------------------------------------------------------------------------------- /Capabilities/images/DataAggregation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/DataAggregation.png -------------------------------------------------------------------------------- /Capabilities/images/EditMode.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/EditMode.PNG -------------------------------------------------------------------------------- /Capabilities/images/SampleData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/SampleData.png -------------------------------------------------------------------------------- /Capabilities/images/Sorting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/Sorting.png -------------------------------------------------------------------------------- /Capabilities/images/TableData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/TableData.png -------------------------------------------------------------------------------- /Capabilities/images/TableDataView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/TableDataView.png -------------------------------------------------------------------------------- /Capabilities/images/addDrillDown2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/addDrillDown2.PNG -------------------------------------------------------------------------------- /Capabilities/images/highlightDataView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/highlightDataView.png -------------------------------------------------------------------------------- /Capabilities/images/highlightDataViewSupports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/Capabilities/images/highlightDataViewSupports.png -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Change Log - Visuals API 2 | 3 | The page contains a quick summary of the API versions. 4 | 5 | Versions listed on this page are considered stable and should not change. For information about upcoming versions and features see the [Roadmap](./Roadmap/README.md) 6 | 7 | ## Utility libraries 8 | * [Color Utils](https://github.com/Microsoft/powerbi-visuals-utils-colorutils) 9 | * [Formatting Utils](https://github.com/Microsoft/powerbi-visuals-utils-formattingutils) 10 | * [Dataview Utils](https://github.com/Microsoft/powerbi-visuals-utils-dataviewutils) 11 | * [Type Utils](https://github.com/Microsoft/powerbi-visuals-utils-typeutils) 12 | * [Interactivity Utils](https://github.com/Microsoft/powerbi-visuals-utils-interactivityutils) 13 | * [SVG Utils](https://github.com/Microsoft/powerbi-visuals-utils-svgutils) 14 | * [Tooltip Utils](https://github.com/Microsoft/powerbi-visuals-utils-tooltiputils) 15 | * [Chart Utils](https://github.com/Microsoft/powerbi-visuals-utils-chartutils) 16 | * [Test Utils](https://github.com/Microsoft/powerbi-visuals-utils-testutils) 17 | 18 | ## API Version v1.6.2 19 | * **[localization](https://github.com/Microsoft/PowerBI-visuals/blob/master/Visual/Locale.md)** - support for visual localization 20 | * **[Edit mode](https://github.com/Microsoft/PowerBI-visuals/blob/master/Capabilities/AdvancedEditMode.md)** - support for visual to enter in-visual edit mode 21 | * **[Interactive (html) R custom visuals](https://github.com/Microsoft/PowerBI-visuals/blob/master/RVisualTutorial/CreateRHTML.md)** - support for creating interactive R custom visuals, based on html 22 | 23 | ## API Version v1.5.0 24 | * **[allowInteractions](https://github.com/Microsoft/PowerBI-visuals/blob/master/Visual/AllowInteractions.md)** - support for visual interactivity 25 | 26 | ## API Version v1.4.0 27 | * **[locale](https://github.com/Microsoft/PowerBI-visuals/blob/master/Visual/Locale.md)** - support for locale 28 | 29 | ## API Version 1.3.0 30 | * **[tooltips](https://github.com/Microsoft/PowerBI-visuals/blob/master/Visual/Tooltips.md)** - support for tooltips 31 | 32 | ## API Version 1.2.0 33 | * **colorPallette** - manage the colors used on your visual. 34 | * **Multiple selection** - selectionManager can accept an array of `SelectionId`. 35 | * **[R visuals](https://github.com/Microsoft/PowerBI-visuals/tree/master/RVisualTutorial)** - support for custom visuals using R scripts 36 | 37 | ## API Version 1.1.0 38 | * Debug visual in iFrame 39 | * Light weight sandbox - faster initialization of the iFrame 40 | 41 | * Visual Host Addtions 42 | * **createSelectionIdBuilder** - allows for creation of unique identifiers used for data selection 43 | * **createSelectionManager** - manages the selection state of the visual and communicates changes to the visual host 44 | * **colors** - an array of default colors to use in your visual 45 | 46 | ## API Version v1.0.0 47 | 48 | * Initial API release 49 | -------------------------------------------------------------------------------- /Glossary.md: -------------------------------------------------------------------------------- 1 | # Glossary 2 | 3 | * **DataRole** - DataRole(s) are used to define data bindings for your visual. They are displayed as fields in the Power BI interface. 4 | * **DataView** - DataView is a JavaScript object model for canonical representations of data. The lifeblood of Power BI visuals. 5 | * **IVisual** - The interface that all visuals must implement. Also, commonly used to refer to a PowerBI Visual. 6 | * **Visual Host** - The platform that contains the `IVisual` -------------------------------------------------------------------------------- /RVisualTutorial/CorrplotScript.md: -------------------------------------------------------------------------------- 1 | # Editing the R Script 2 | When creating a R Powered Custom Visual, the template "rvisual" creates a file in the root folder of the visual called "script.r". 3 | This file will hold the R script you want to execute to generate the image the user will see. 4 | 5 | In this stage, we will change the default R script to start using the Corrplot package. 6 | We will follow the corrplot [introduction](https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html) from [cran.r-project.org](https://cran.r-project.org/) 7 | 8 | ## Editing the R Script 9 | Open the `script.r` file and paste the following code: 10 | 11 | ```r 12 | library(corrplot) 13 | M <- cor(Values) 14 | corrplot(M, method="circle") 15 | ``` 16 | 17 | Now add the `corrplot` package to the CRAN dependencies of this visual in the `dependencies.json` file: 18 | ```json 19 | { 20 | "cranPackages": [ 21 | { 22 | "name": "corrplot", 23 | "displayName": "corrplot", 24 | "url": "https://cran.r-project.org/web/packages/corrplot/" 25 | } 26 | ] 27 | } 28 | ``` 29 | 30 | Now you can package the visual and try it out (or you can use the `pbiviz start` feature to debug the visual in [PowerBI.com](https://powerbi.microsoft.com/)) 31 | 32 | ![Basic Corrplot Visual](./images/BasicCorrplot.png) 33 | 34 | See [commit](https://github.com/Microsoft/PowerBI-visuals-sampleCorrPlotRVisual/commit/19f587c499511a19533dfedd86a25f0707f375a8) for what was added at this step. -------------------------------------------------------------------------------- /RVisualTutorial/CreateNewVisual.md: -------------------------------------------------------------------------------- 1 | # Building new R Powered Custom Visual 2 | In order to create a new R Powered Custom Visual we will run the following command: 3 | 4 | ``` 5 | pbiviz new sampleCorrPlotRVisual -t rvisual 6 | ``` 7 | 8 | This command will create a new folder stracture based on the template `rvisual` 9 | 10 | This template includes a very basic ready to run R Visual which will actually run the following R script: 11 | 12 | ```r 13 | plot(Values) 14 | ``` 15 | 16 | This R script calls a generic function for plotting of R object. The data frame "Values" will contain columns in "Values" data role. 17 | 18 | ![Basic Plot Script Result](images/BasicPlot.png) 19 | 20 | See [commit](https://github.com/Microsoft/PowerBI-visuals-sampleCorrPlotRVisual/commit/e7d31301bfa0ba9419e67383a9f27ae340e79fee) for what was added at this step. 21 | 22 | ## Enable HTML output 23 | The static output image can be replaced by an HTML output, unlocking new possibilities to R powered custom visuals. 24 | The 'rhtml' template is used in this case: 25 | 26 | ``` 27 | pbiviz new sampleRHTMLVisual -t rhtml 28 | ``` 29 | ![Basic HTML Plot Script Result](images/BasicHTMLPlot.png) 30 | 31 | In this sample the HTML has several capabilities, such as displaying data values and enables zooming. 32 | 33 | For more information see [R HTML](CreateRHTML.md) 34 | See [commit](https://github.com/Microsoft/PowerBI-visuals-tools/commit/3e03b7595c69929716772e4f58f192d08e103619) for what was added at this step. 35 | -------------------------------------------------------------------------------- /RVisualTutorial/CreateRHTML.md: -------------------------------------------------------------------------------- 1 | # Building R Powered Custom Visual with HTML output 2 | Regular R Powered Custom Visual capture the output plot and displays it as a static image, the same way it is done in R Visuals. 3 | In order to create an HTML output the "rhtml" template is used for creating a basic project: 4 | 5 | ``` 6 | pbiviz new sampleRHTMLVisual -t rhtml 7 | ``` 8 | This template includes a very basic ready to run R Visual that can create HTML output: 9 | 10 | ``` 11 | source('./r_files/flatten_HTML.r') 12 | 13 | ############### Library Declarations ############### 14 | libraryRequireInstall("ggplot2"); 15 | libraryRequireInstall("plotly") 16 | #################################################### 17 | 18 | ################### Actual code #################### 19 | g = qplot(`Petal.Length`, data = iris, fill = `Species`, main = Sys.time()); 20 | #################################################### 21 | 22 | ############# Create and save widget ############### 23 | p = ggplotly(g); 24 | internalSaveWidget(p, 'out.html'); 25 | #################################################### 26 | ``` 27 | 28 | This R script calls a function from [`ggplot2`](http://ggplot2.org/) package, which plots a pre-defined dataset, and is using the [`Plotly`](https://plot.ly/) package for converting it into HTML. 29 | 30 | ![Basic HTML Plot Script Result](images/BasicHTMLPlot.png) 31 | 32 | In this sample the HTML has several capabilities, such as displaying data values and enables zooming. 33 | 34 | ## Creating HTML output in R 35 | In order to create HTML output in R we are using the [`HTMLWidgets`](http://www.htmlwidgets.org/) package. It supports saving to HTML of output which was created by other packages. In the sample we used `ggplot2` and `plotly`, but other packages are also supported. See the full list of [supported R Packages in the service](https://powerbi.microsoft.com/en-us/documentation/powerbi-service-r-packages-support/). 36 | The output is created as a widget which is saved to HTML file. The system supports the creation of a single file, without external dependencies. The function `internalSaveWidget` is saving the widget and merge all the external files into a single one (it supports only several packages, such as `plotly` and `networkD3`). 37 | 38 | ## Tips and best practice 39 | ### General tips 40 | - The suffix of the output file must be 'html'. 41 | - For better performance, reduce the size of the created HTML (i.e. plotting data after processing and aggregation) 42 | - All the features of R Powered Custom Visuals are supported, including properties in the Property Pane. 43 | 44 | ### Loading the `head` data once 45 | In many cases, the custom visual is using the same package for all rendering. In these cases the same scripts are being loaded to the `head` section of the HTML, while the main differernce is in the `body` section. 46 | 47 | There is a flag in `visual.ts` which can choose between updating the `head` section after each load or only in the first one: 48 | ``` 49 | const updateHTMLHead: boolean = false; 50 | ``` 51 | The default is `false`, which means that the scripts will only be loaded to the DOM once. 52 | -------------------------------------------------------------------------------- /RVisualTutorial/InputValidationInR.md: -------------------------------------------------------------------------------- 1 | # Input Validation in R Script 2 | In order to write a truly robust R Powered Custom Visual, you should validate all the input you get before running some R function that expects specific values to be given. 3 | 4 | For example, the corrplot function needs to run on at least two columns and at least two rows. 5 | If the function gets one row, the function will fail. 6 | `corrplot` also require that all column types will be numeric and non-constant 7 | 8 | So you should prepare to validate your input prior to running the code. 9 | 10 | ## Example for input validation in R code 11 | 12 | ### Validate number of columns and rows 13 | Here is an example for validating that we got the right columns types and at least two columns and at lease two rows: 14 | 15 | ```r 16 | errorText <- NULL 17 | #filter out non-numeric columns and constant columns 18 | correctColumn <- function(someColumn) { is.numeric(someColumn) && length(unique(someColumn)) > 1 } 19 | useColumns <- sapply(Values,correctColumn) 20 | if(sum(useColumns) < ncol(Values)) 21 | errorText <- "Filtered out non numeric columns and constant columns" 22 | 23 | Values <- as.data.frame(Values[,useColumns]) 24 | 25 | columnCount <- ncol(Values) 26 | rowCount <- nrow(Values) 27 | 28 | if (rowCount < 2 || columnCount < 2) { 29 | plot.new() 30 | errorText<-paste(errorText, "Not enough input dimensions", sep="\n") 31 | title(main = NULL, sub = errorText, outer = FALSE, col.sub = "gray50", cex.sub = 0.75) 32 | quit() 33 | } 34 | ``` 35 | 36 | In this example, if we get one row or one column, we will print some error message into the graphical device instead of leting the `corrplot` function to fail 37 | 38 | ### Validate column types 39 | 40 | 41 | See [commit](https://github.com/Microsoft/PowerBI-visuals-sampleCorrPlotRVisual/commit/988057e9845ef24374b83ea0e15ae3c1f1873c90) for what was added at this step. -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/RscriptShowcase/Icon4Store300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/RscriptShowcase/Icon4Store300x300.png -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/RscriptShowcase/ScriptInstallPackagesWithWorkaroundsFunnel.R: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | 3 | 4 | libraryRequireInstallWithWorkarounds = function(packageName, ...) 5 | { 6 | print(paste("***", packageName, "***")) 7 | if(!require(packageName, character.only = TRUE)) 8 | { 9 | install.packages(packageName,repos = "http://cran.us.r-project.org", ... ) 10 | packOK = require(packageName, character.only = TRUE) 11 | } 12 | if(!require(packageName, character.only = TRUE)) 13 | { 14 | install.packages(packageName,repos = "https://cloud.r-project.org", ... ) 15 | packOK = require(packageName, character.only = TRUE) 16 | } 17 | 18 | if(!require(packageName, character.only = TRUE)) 19 | { 20 | install.packages(packageName,repos = "http://cran.rstudio.com/", ... ) 21 | packOK = require(packageName, character.only = TRUE) 22 | } 23 | if(!require(packageName, character.only = TRUE)) 24 | { 25 | install.packages(packageName,repos = "https://cran.r-project.org", ... ) 26 | packOK = require(packageName, character.only = TRUE) 27 | } 28 | 29 | if(!require(packageName, character.only = TRUE)) 30 | { 31 | if(!(as.numeric(version$major)>=3 && as.numeric(version$minor)>= 3.0 )) 32 | setInternet2(use = TRUE) 33 | 34 | install.packages(packageName) 35 | packOK = require(packageName, character.only = TRUE) 36 | } 37 | 38 | } 39 | 40 | 41 | allpackages = c("scales", "reshape", "ggplot2", "htmlwidgets", "XML", "plotly") 42 | 43 | 44 | sapply(allpackages,libraryRequireInstallWithWorkarounds) 45 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/RscriptShowcase/funnelPlot_RinPBI_showcase.pbix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/RscriptShowcase/funnelPlot_RinPBI_showcase.pbix -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter1_R/script_R_v1_00.r: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | 3 | # Third Party Programs. This software enables you to obtain software applications from other sources. 4 | # Those applications are offered and distributed by third parties under their own license terms. 5 | # Microsoft is not developing, distributing or licensing those applications to you, but instead, 6 | # as a convenience, enables you to use this software to obtain those applications directly from 7 | # the application providers. 8 | # By using the software, you acknowledge and agree that you are obtaining the applications directly 9 | # from the third party providers and under separate license terms, and that it is your responsibility to locate, 10 | # understand and comply with those license terms. 11 | # Microsoft grants you no license rights for third-party software or applications that is obtained using this software. 12 | 13 | # See also: 14 | # http://stats.stackexchange.com/questions/5195/how-to-draw-funnel-plot-using-ggplot2-in-r/5210#5210 15 | 16 | 17 | dataset = read.csv(file = "dataset.csv", header = TRUE, sep = ",", stringsAsFactors = FALSE) 18 | 19 | 20 | ###############Library Declarations############### 21 | 22 | library("ggplot2") 23 | library("scales") 24 | 25 | 26 | ###############Internal parameters definitions################# 27 | 28 | ##PBI_PARAM Color of scatterplot points 29 | pointsCol = "orange" 30 | 31 | #PBI_PARAM Transparency of scatterplot points 32 | transparency = 0.4 33 | 34 | ##PBI_PARAM Color of baseline 35 | lineColor = "blue" 36 | 37 | #PBI_PARAM Size of points on the plot 38 | pointCex = 1 39 | 40 | #PBI_PARAM Confidence level line 41 | conf1 = 0.95 42 | 43 | #PBI_PARAM Confidence level line #2 44 | conf2 = 0.99 45 | 46 | 47 | ############# Main code ##################### 48 | 49 | countValue = dataset[,1] 50 | p = dataset[,2]/dataset[,1] 51 | p.se <- sqrt((p*(1-p)) / (countValue)) 52 | df <- data.frame(p, countValue, p.se) 53 | 54 | ## common effect (fixed effect model) 55 | p.fem <- weighted.mean(p[p.se>0], 1/p.se[p.se>0]^2) 56 | 57 | ## lower and upper limits, based on FEM estimator 58 | zLow = qnorm(conf1) 59 | zUp = qnorm(conf2) 60 | 61 | 62 | number.seq <- seq(min(countValue), max(countValue), 1000) 63 | number.llconf1 <- (p.fem - zLow * sqrt((p.fem*(1-p.fem)) / (number.seq))) 64 | number.ulconf1 <- (p.fem + zLow * sqrt((p.fem*(1-p.fem)) / (number.seq))) 65 | number.llconf2 <- (p.fem - zUp * sqrt((p.fem*(1-p.fem)) / (number.seq))) 66 | number.ulconf2 <- (p.fem + zUp * sqrt((p.fem*(1-p.fem)) / (number.seq))) 67 | 68 | dfCI <- data.frame(number.llconf1, number.ulconf1, number.llconf2, number.ulconf2, number.seq, p.fem) 69 | 70 | # Visualization only 71 | fp <- ggplot(aes(x = countValue, y = p), data = df) 72 | fp <- fp + geom_point(shape = 19, colour = alpha(pointsCol,transparency), size = pointCex*2 ) 73 | fp <- fp + geom_line(aes(x = number.seq, y = number.llconf1),linetype = 1, colour = "green",data = dfCI) 74 | fp <- fp + geom_line(aes(x = number.seq, y = number.ulconf1),linetype = 1, colour = "green", data = dfCI) 75 | fp <- fp + geom_line(aes(x = number.seq, y = number.llconf2),linetype = 2, colour = "red",data = dfCI) 76 | fp <- fp + geom_line(aes(x = number.seq, y = number.ulconf2), linetype = 2, colour = "red",data = dfCI) 77 | fp <- fp + geom_hline(aes(yintercept = p.fem), data = dfCI, colour = lineColor, linetype = 4) 78 | print(fp) 79 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter2_Rvisual/funnelPlot_Rvisual.pbix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter2_Rvisual/funnelPlot_Rvisual.pbix -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelPlot_RCustomVisual.pbix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelPlot_RCustomVisual.pbix -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/.npmignore: -------------------------------------------------------------------------------- 1 | typings 2 | node_modules 3 | .DS_Store 4 | .tmp 5 | dist -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "configurations": [ 4 | { 5 | "name": "Debugger", 6 | "type": "chrome", 7 | "request": "attach", 8 | "port": 9222, 9 | "sourceMaps": true, 10 | "webRoot": "${cwd}/" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 4, 3 | "editor.insertSpaces": true, 4 | "files.eol": "\n", 5 | "files.watcherExclude": { 6 | "**/.git/objects/**": true, 7 | "**/node_modules/**": true, 8 | ".tmp": true 9 | }, 10 | "files.exclude": { 11 | ".tmp": true 12 | }, 13 | "search.exclude": { 14 | ".tmp": true, 15 | "typings": true 16 | }, 17 | "json.schemas": [ 18 | { 19 | "fileMatch": [ 20 | "/pbiviz.json" 21 | ], 22 | "url": "./.api/v1.10.0/schema.pbiviz.json" 23 | }, 24 | { 25 | "fileMatch": [ 26 | "/capabilities.json" 27 | ], 28 | "url": "./.api/v1.10.0/schema.capabilities.json" 29 | }, 30 | { 31 | "fileMatch": [ 32 | "/dependencies.json" 33 | ], 34 | "url": "./.api/v1.10.0/schema.dependencies.json" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/assets/icon.png -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/capabilities.json: -------------------------------------------------------------------------------- 1 | { 2 | "dataRoles": [ 3 | { 4 | "displayName": "dataset", 5 | "kind": "GroupingOrMeasure", 6 | "name": "dataset" 7 | } 8 | ], 9 | "dataViewMappings": [ 10 | { 11 | "scriptResult": { 12 | "dataInput": { 13 | "table": { 14 | "rows": { 15 | "select": [ 16 | { 17 | "for": { 18 | "in": "dataset" 19 | } 20 | } 21 | ], 22 | "dataReductionAlgorithm": { 23 | "top": {} 24 | } 25 | } 26 | } 27 | }, 28 | "script": { 29 | "scriptProviderDefault": "R", 30 | "scriptOutputType": "png", 31 | "source": { 32 | "objectName": "rcv_script", 33 | "propertyName": "source" 34 | }, 35 | "provider": { 36 | "objectName": "rcv_script", 37 | "propertyName": "provider" 38 | } 39 | } 40 | } 41 | } 42 | ], 43 | "objects": { 44 | "rcv_script": { 45 | "properties": { 46 | "provider": { 47 | "type": { 48 | "text": true 49 | } 50 | }, 51 | "source": { 52 | "type": { 53 | "scripting": { 54 | "source": true 55 | } 56 | } 57 | } 58 | } 59 | } 60 | }, 61 | "suppressDefaultTitle": true 62 | } 63 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/capabilities_changes.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/capabilities_changes.PNG -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/capabilities_old.json: -------------------------------------------------------------------------------- 1 | { 2 | "dataRoles": [ 3 | { 4 | "displayName": "Values", 5 | "kind": "GroupingOrMeasure", 6 | "name": "Values" 7 | } 8 | ], 9 | "dataViewMappings": [ 10 | { 11 | "scriptResult": { 12 | "dataInput": { 13 | "table": { 14 | "rows": { 15 | "select": [ 16 | { 17 | "for": { 18 | "in": "Values" 19 | } 20 | } 21 | ], 22 | "dataReductionAlgorithm": { 23 | "top": {} 24 | } 25 | } 26 | } 27 | }, 28 | "script": { 29 | "scriptProviderDefault": "R", 30 | "scriptOutputType": "png", 31 | "source": { 32 | "objectName": "rcv_script", 33 | "propertyName": "source" 34 | }, 35 | "provider": { 36 | "objectName": "rcv_script", 37 | "propertyName": "provider" 38 | } 39 | } 40 | } 41 | } 42 | ], 43 | "objects": { 44 | "rcv_script": { 45 | "properties": { 46 | "provider": { 47 | "type": { 48 | "text": true 49 | } 50 | }, 51 | "source": { 52 | "type": { 53 | "scripting": { 54 | "source": true 55 | } 56 | } 57 | } 58 | } 59 | } 60 | }, 61 | "suppressDefaultTitle": true 62 | } 63 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "cranPackages": [ 3 | { 4 | "name": "ggplot2", 5 | "displayName": "GG Plot 2", 6 | "url": "https://cran.r-project.org/web/packages/ggplot2/index.html" 7 | }, 8 | { 9 | "name": "scales", 10 | "displayName": "scales: Scale Functions for Visualization", 11 | "url": "https://cran.r-project.org/web/packages/scales/index.html" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/dependencies_changes.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/dependencies_changes.PNG -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/dependencies_old.json: -------------------------------------------------------------------------------- 1 | { 2 | "cranPackages": [ 3 | { 4 | "name": "ggplot2", 5 | "displayName": "GG Plot 2", 6 | "url": "https://cran.r-project.org/web/packages/ggplot2/index.html" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/dist/funnelRvisualVer01.pbiviz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/dist/funnelRvisualVer01.pbiviz -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visual", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "powerbi-visuals-utils-dataviewutils": { 7 | "version": "1.2.0", 8 | "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-dataviewutils/-/powerbi-visuals-utils-dataviewutils-1.2.0.tgz", 9 | "integrity": "sha1-WaHJgzVclYoj2ZAYlPZfFXUZMhM=", 10 | "dev": true 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visual", 3 | "devDependencies": { 4 | "powerbi-visuals-utils-dataviewutils": "1.2.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/pbiviz.json: -------------------------------------------------------------------------------- 1 | { 2 | "visual": { 3 | "name": "funnelRvisualVer01", 4 | "displayName": "funnelRvisualVer01", 5 | "guid": "funnelRvisualVer01_FEFF3", 6 | "visualClassName": "Visual", 7 | "version": "1.0.0", 8 | "description": "", 9 | "supportUrl": "", 10 | "gitHubUrl": "" 11 | }, 12 | "apiVersion": "1.10.0", 13 | "author": { 14 | "name": "", 15 | "email": "" 16 | }, 17 | "assets": { 18 | "icon": "assets/icon.png" 19 | }, 20 | "externalJS": [ 21 | "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js" 22 | ], 23 | "style": "style/visual.less", 24 | "capabilities": "capabilities.json", 25 | "dependencies": "dependencies.json", 26 | "stringResources": [] 27 | } 28 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/src/settings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | module powerbi.extensibility.visual { 28 | "use strict"; 29 | import DataViewObjectsParser = powerbi.extensibility.utils.dataview.DataViewObjectsParser; 30 | 31 | export class VisualSettings extends DataViewObjectsParser { 32 | public rcv_script: rcv_scriptSettings = new rcv_scriptSettings(); 33 | } 34 | 35 | export class rcv_scriptSettings { 36 | // undefined 37 | public provider // undefined 38 | public source } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/src/visual.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visual CLI 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | module powerbi.extensibility.visual { 27 | "use strict"; 28 | export class Visual implements IVisual { 29 | private imageDiv: HTMLDivElement; 30 | private imageElement: HTMLImageElement; 31 | private settings: VisualSettings; 32 | 33 | public constructor(options: VisualConstructorOptions) { 34 | this.imageDiv = document.createElement("div"); 35 | this.imageDiv.className = "rcv_autoScaleImageContainer"; 36 | this.imageElement = document.createElement("img"); 37 | this.imageElement.className = "rcv_autoScaleImage"; 38 | this.imageDiv.appendChild(this.imageElement); 39 | options.element.appendChild(this.imageDiv); 40 | } 41 | 42 | public update(options: VisualUpdateOptions): void { 43 | if (!options || 44 | !options.type || 45 | !options.viewport || 46 | !options.dataViews || 47 | options.dataViews.length === 0 || 48 | !options.dataViews[0]) { 49 | return; 50 | } 51 | const dataView: DataView = options.dataViews[0]; 52 | 53 | this.settings = Visual.parseSettings(dataView); 54 | 55 | let imageUrl: string = null; 56 | if (dataView.scriptResult && dataView.scriptResult.payloadBase64) { 57 | imageUrl = "data:image/png;base64," + dataView.scriptResult.payloadBase64; 58 | } 59 | 60 | if (imageUrl) { 61 | this.imageElement.src = imageUrl; 62 | } else { 63 | this.imageElement.src = null; 64 | } 65 | 66 | this.onResizing(options.viewport); 67 | } 68 | 69 | public onResizing(finalViewport: IViewport): void { 70 | this.imageDiv.style.height = finalViewport.height + "px"; 71 | this.imageDiv.style.width = finalViewport.width + "px"; 72 | } 73 | 74 | private static parseSettings(dataView: DataView): VisualSettings { 75 | return VisualSettings.parse(dataView) as VisualSettings; 76 | } 77 | /** 78 | * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the 79 | * objects and properties you want to expose to the users in the property pane. 80 | */ 81 | public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): 82 | VisualObjectInstance[] | VisualObjectInstanceEnumerationObject { 83 | return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/style/visual.less: -------------------------------------------------------------------------------- 1 | .rcv_autoScaleImageContainer { 2 | position: relative; 3 | 4 | .rcv_autoScaleImage { 5 | max-width: 100%; 6 | max-height: 100%; 7 | position: absolute; 8 | top: 50%; 9 | /* @noflip */ 10 | left: 50%; 11 | transform: translateY(-50%) translateX(-50%); 12 | -webkit-transform: translateY(-50%) translateX(-50%); 13 | } 14 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "target": "ES5", 7 | "sourceMap": true, 8 | "out": "./.tmp/build/visual.js" 9 | }, 10 | "files": [ 11 | ".api/v1.10.0/PowerBI-visuals.d.ts", 12 | "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.d.ts", 13 | "src/settings.ts", 14 | "src/visual.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v01/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "indent": [ 9 | true, 10 | "spaces" 11 | ], 12 | "no-duplicate-variable": true, 13 | "no-eval": true, 14 | "no-internal-module": false, 15 | "no-trailing-whitespace": true, 16 | "no-unsafe-finally": true, 17 | "no-var-keyword": true, 18 | "one-line": [ 19 | true, 20 | "check-open-brace", 21 | "check-whitespace" 22 | ], 23 | "quotemark": [ 24 | false, 25 | "double" 26 | ], 27 | "semicolon": [ 28 | true, 29 | "always" 30 | ], 31 | "triple-equals": [ 32 | true, 33 | "allow-null-check" 34 | ], 35 | "typedef-whitespace": [ 36 | true, 37 | { 38 | "call-signature": "nospace", 39 | "index-signature": "nospace", 40 | "parameter": "nospace", 41 | "property-declaration": "nospace", 42 | "variable-declaration": "nospace" 43 | } 44 | ], 45 | "variable-name": [ 46 | true, 47 | "ban-keywords" 48 | ], 49 | "whitespace": [ 50 | true, 51 | "check-branch", 52 | "check-decl", 53 | "check-operator", 54 | "check-separator", 55 | "check-type" 56 | ], 57 | "insecure-random": true, 58 | "no-banned-terms": true, 59 | "no-cookies": true, 60 | "no-delete-expression": true, 61 | "no-disable-auto-sanitization": true, 62 | "no-document-domain": true, 63 | "no-document-write": true, 64 | "no-exec-script": true, 65 | "no-function-constructor-with-string-args": true, 66 | "no-http-string": [true, "http://www.example.com/?.*", "http://www.examples.com/?.*"], 67 | "no-inner-html": true, 68 | "no-octal-literal": true, 69 | "no-reserved-keywords": true, 70 | "no-string-based-set-immediate": true, 71 | "no-string-based-set-interval": true, 72 | "no-string-based-set-timeout": true, 73 | "non-literal-require": true, 74 | "possible-timing-attack": true, 75 | "react-anchor-blank-noopener": true, 76 | "react-iframe-missing-sandbox": true, 77 | "react-no-dangerous-html": true 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/.npmignore: -------------------------------------------------------------------------------- 1 | typings 2 | node_modules 3 | .DS_Store 4 | .tmp 5 | dist -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "configurations": [ 4 | { 5 | "name": "Debugger", 6 | "type": "chrome", 7 | "request": "attach", 8 | "port": 9222, 9 | "sourceMaps": true, 10 | "webRoot": "${cwd}/" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 4, 3 | "editor.insertSpaces": true, 4 | "files.eol": "\n", 5 | "files.watcherExclude": { 6 | "**/.git/objects/**": true, 7 | "**/node_modules/**": true, 8 | ".tmp": true 9 | }, 10 | "files.exclude": { 11 | ".tmp": true 12 | }, 13 | "search.exclude": { 14 | ".tmp": true, 15 | "typings": true 16 | }, 17 | "json.schemas": [ 18 | { 19 | "fileMatch": [ 20 | "/pbiviz.json" 21 | ], 22 | "url": "./.api/v1.10.0/schema.pbiviz.json" 23 | }, 24 | { 25 | "fileMatch": [ 26 | "/capabilities.json" 27 | ], 28 | "url": "./.api/v1.10.0/schema.capabilities.json" 29 | }, 30 | { 31 | "fileMatch": [ 32 | "/dependencies.json" 33 | ], 34 | "url": "./.api/v1.10.0/schema.dependencies.json" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/assets/icon.png -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/capabilities.json: -------------------------------------------------------------------------------- 1 | { 2 | "dataRoles": [ 3 | { 4 | "displayName": "Population", 5 | "description": "Numeric variable (positive integer)", 6 | "kind": "GroupingOrMeasure", 7 | "name": "population" 8 | }, 9 | { 10 | "displayName": "Occurrence", 11 | "description": "Numeric variable (nonnegative integer). Must be smaller than 'Population'", 12 | "kind": "GroupingOrMeasure", 13 | "name": "occurrence" 14 | }, 15 | { 16 | "displayName": "Tooltips", 17 | "description": "Fields to be used as mouseover tooltips", 18 | "kind": "Grouping", 19 | "name": "tooltips" 20 | } 21 | ], 22 | "dataViewMappings": [ 23 | { 24 | "conditions": [ 25 | { 26 | "population": { 27 | "max": 1 28 | }, 29 | "occurrence": { 30 | "max": 1 31 | }, 32 | "tooltips": { 33 | "max": 7 34 | } 35 | } 36 | ], 37 | "scriptResult": { 38 | "dataInput": { 39 | "table": { 40 | "rows": { 41 | "select": [ 42 | { 43 | "for": { 44 | "in": "population" 45 | } 46 | }, 47 | { 48 | "for": { 49 | "in": "occurrence" 50 | } 51 | }, 52 | { 53 | "for": { 54 | "in": "tooltips" 55 | } 56 | } 57 | ], 58 | "dataReductionAlgorithm": { 59 | "top": {} 60 | } 61 | } 62 | } 63 | }, 64 | "script": { 65 | "scriptProviderDefault": "R", 66 | "scriptOutputType": "png", 67 | "source": { 68 | "objectName": "rcv_script", 69 | "propertyName": "source" 70 | }, 71 | "provider": { 72 | "objectName": "rcv_script", 73 | "propertyName": "provider" 74 | } 75 | } 76 | } 77 | } 78 | ], 79 | "objects": { 80 | "rcv_script": { 81 | "properties": { 82 | "provider": { 83 | "type": { 84 | "text": true 85 | } 86 | }, 87 | "source": { 88 | "type": { 89 | "scripting": { 90 | "source": true 91 | } 92 | } 93 | } 94 | } 95 | } 96 | }, 97 | "suppressDefaultTitle": true 98 | } 99 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/capabilities_before_vs_after.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/capabilities_before_vs_after.PNG -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/capabilities_old.json: -------------------------------------------------------------------------------- 1 | { 2 | "dataRoles": [ 3 | { 4 | "displayName": "dataset", 5 | "kind": "GroupingOrMeasure", 6 | "name": "dataset" 7 | } 8 | ], 9 | "dataViewMappings": [ 10 | { 11 | "scriptResult": { 12 | "dataInput": { 13 | "table": { 14 | "rows": { 15 | "select": [ 16 | { 17 | "for": { 18 | "in": "dataset" 19 | } 20 | } 21 | ], 22 | "dataReductionAlgorithm": { 23 | "top": {} 24 | } 25 | } 26 | } 27 | }, 28 | "script": { 29 | "scriptProviderDefault": "R", 30 | "scriptOutputType": "png", 31 | "source": { 32 | "objectName": "rcv_script", 33 | "propertyName": "source" 34 | }, 35 | "provider": { 36 | "objectName": "rcv_script", 37 | "propertyName": "provider" 38 | } 39 | } 40 | } 41 | } 42 | ], 43 | "objects": { 44 | "rcv_script": { 45 | "properties": { 46 | "provider": { 47 | "type": { 48 | "text": true 49 | } 50 | }, 51 | "source": { 52 | "type": { 53 | "scripting": { 54 | "source": true 55 | } 56 | } 57 | } 58 | } 59 | } 60 | }, 61 | "suppressDefaultTitle": true 62 | } 63 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "cranPackages": [ 3 | { 4 | "name": "ggplot2", 5 | "displayName": "GG Plot 2", 6 | "url": "https://cran.r-project.org/web/packages/ggplot2/index.html" 7 | }, 8 | { 9 | "name": "scales", 10 | "displayName": "scales: Scale Functions for Visualization", 11 | "url": "https://cran.r-project.org/web/packages/scales/index.html" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/dist/funnelRvisualVer02.pbiviz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/dist/funnelRvisualVer02.pbiviz -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visual", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "powerbi-visuals-utils-dataviewutils": { 7 | "version": "1.2.0", 8 | "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-dataviewutils/-/powerbi-visuals-utils-dataviewutils-1.2.0.tgz", 9 | "integrity": "sha1-WaHJgzVclYoj2ZAYlPZfFXUZMhM=", 10 | "dev": true 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visual", 3 | "devDependencies": { 4 | "powerbi-visuals-utils-dataviewutils": "1.2.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/pbiviz.json: -------------------------------------------------------------------------------- 1 | { 2 | "visual": { 3 | "name": "funnelRvisualVer02", 4 | "displayName": "funnelRvisualVer02", 5 | "guid": "funnelRvisualVer02_FEFF3", 6 | "visualClassName": "Visual", 7 | "version": "1.0.0", 8 | "description": "", 9 | "supportUrl": "", 10 | "gitHubUrl": "" 11 | }, 12 | "apiVersion": "1.10.0", 13 | "author": { 14 | "name": "", 15 | "email": "" 16 | }, 17 | "assets": { 18 | "icon": "assets/icon.png" 19 | }, 20 | "externalJS": [ 21 | "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js" 22 | ], 23 | "style": "style/visual.less", 24 | "capabilities": "capabilities.json", 25 | "dependencies": "dependencies.json", 26 | "stringResources": [] 27 | } 28 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/script_r_before_vs_after.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/script_r_before_vs_after.PNG -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/src/settings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | module powerbi.extensibility.visual { 28 | "use strict"; 29 | import DataViewObjectsParser = powerbi.extensibility.utils.dataview.DataViewObjectsParser; 30 | 31 | export class VisualSettings extends DataViewObjectsParser { 32 | public rcv_script: rcv_scriptSettings = new rcv_scriptSettings(); 33 | } 34 | 35 | export class rcv_scriptSettings { 36 | // undefined 37 | public provider // undefined 38 | public source } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/src/visual.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visual CLI 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | module powerbi.extensibility.visual { 27 | "use strict"; 28 | export class Visual implements IVisual { 29 | private imageDiv: HTMLDivElement; 30 | private imageElement: HTMLImageElement; 31 | private settings: VisualSettings; 32 | 33 | public constructor(options: VisualConstructorOptions) { 34 | this.imageDiv = document.createElement("div"); 35 | this.imageDiv.className = "rcv_autoScaleImageContainer"; 36 | this.imageElement = document.createElement("img"); 37 | this.imageElement.className = "rcv_autoScaleImage"; 38 | this.imageDiv.appendChild(this.imageElement); 39 | options.element.appendChild(this.imageDiv); 40 | } 41 | 42 | public update(options: VisualUpdateOptions): void { 43 | if (!options || 44 | !options.type || 45 | !options.viewport || 46 | !options.dataViews || 47 | options.dataViews.length === 0 || 48 | !options.dataViews[0]) { 49 | return; 50 | } 51 | const dataView: DataView = options.dataViews[0]; 52 | 53 | this.settings = Visual.parseSettings(dataView); 54 | 55 | let imageUrl: string = null; 56 | if (dataView.scriptResult && dataView.scriptResult.payloadBase64) { 57 | imageUrl = "data:image/png;base64," + dataView.scriptResult.payloadBase64; 58 | } 59 | 60 | if (imageUrl) { 61 | this.imageElement.src = imageUrl; 62 | } else { 63 | this.imageElement.src = null; 64 | } 65 | 66 | this.onResizing(options.viewport); 67 | } 68 | 69 | public onResizing(finalViewport: IViewport): void { 70 | this.imageDiv.style.height = finalViewport.height + "px"; 71 | this.imageDiv.style.width = finalViewport.width + "px"; 72 | } 73 | 74 | private static parseSettings(dataView: DataView): VisualSettings { 75 | return VisualSettings.parse(dataView) as VisualSettings; 76 | } 77 | /** 78 | * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the 79 | * objects and properties you want to expose to the users in the property pane. 80 | */ 81 | public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): 82 | VisualObjectInstance[] | VisualObjectInstanceEnumerationObject { 83 | return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/style/visual.less: -------------------------------------------------------------------------------- 1 | .rcv_autoScaleImageContainer { 2 | position: relative; 3 | 4 | .rcv_autoScaleImage { 5 | max-width: 100%; 6 | max-height: 100%; 7 | position: absolute; 8 | top: 50%; 9 | /* @noflip */ 10 | left: 50%; 11 | transform: translateY(-50%) translateX(-50%); 12 | -webkit-transform: translateY(-50%) translateX(-50%); 13 | } 14 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "target": "ES5", 7 | "sourceMap": true, 8 | "out": "./.tmp/build/visual.js" 9 | }, 10 | "files": [ 11 | ".api/v1.10.0/PowerBI-visuals.d.ts", 12 | "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.d.ts", 13 | "src/settings.ts", 14 | "src/visual.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v02/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "indent": [ 9 | true, 10 | "spaces" 11 | ], 12 | "no-duplicate-variable": true, 13 | "no-eval": true, 14 | "no-internal-module": false, 15 | "no-trailing-whitespace": true, 16 | "no-unsafe-finally": true, 17 | "no-var-keyword": true, 18 | "one-line": [ 19 | true, 20 | "check-open-brace", 21 | "check-whitespace" 22 | ], 23 | "quotemark": [ 24 | false, 25 | "double" 26 | ], 27 | "semicolon": [ 28 | true, 29 | "always" 30 | ], 31 | "triple-equals": [ 32 | true, 33 | "allow-null-check" 34 | ], 35 | "typedef-whitespace": [ 36 | true, 37 | { 38 | "call-signature": "nospace", 39 | "index-signature": "nospace", 40 | "parameter": "nospace", 41 | "property-declaration": "nospace", 42 | "variable-declaration": "nospace" 43 | } 44 | ], 45 | "variable-name": [ 46 | true, 47 | "ban-keywords" 48 | ], 49 | "whitespace": [ 50 | true, 51 | "check-branch", 52 | "check-decl", 53 | "check-operator", 54 | "check-separator", 55 | "check-type" 56 | ], 57 | "insecure-random": true, 58 | "no-banned-terms": true, 59 | "no-cookies": true, 60 | "no-delete-expression": true, 61 | "no-disable-auto-sanitization": true, 62 | "no-document-domain": true, 63 | "no-document-write": true, 64 | "no-exec-script": true, 65 | "no-function-constructor-with-string-args": true, 66 | "no-http-string": [true, "http://www.example.com/?.*", "http://www.examples.com/?.*"], 67 | "no-inner-html": true, 68 | "no-octal-literal": true, 69 | "no-reserved-keywords": true, 70 | "no-string-based-set-immediate": true, 71 | "no-string-based-set-interval": true, 72 | "no-string-based-set-timeout": true, 73 | "non-literal-require": true, 74 | "possible-timing-attack": true, 75 | "react-anchor-blank-noopener": true, 76 | "react-iframe-missing-sandbox": true, 77 | "react-no-dangerous-html": true 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/.npmignore: -------------------------------------------------------------------------------- 1 | typings 2 | node_modules 3 | .DS_Store 4 | .tmp 5 | dist -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "configurations": [ 4 | { 5 | "name": "Debugger", 6 | "type": "chrome", 7 | "request": "attach", 8 | "port": 9222, 9 | "sourceMaps": true, 10 | "webRoot": "${cwd}/" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 4, 3 | "editor.insertSpaces": true, 4 | "files.eol": "\n", 5 | "files.watcherExclude": { 6 | "**/.git/objects/**": true, 7 | "**/node_modules/**": true, 8 | ".tmp": true 9 | }, 10 | "files.exclude": { 11 | ".tmp": true 12 | }, 13 | "search.exclude": { 14 | ".tmp": true, 15 | "typings": true 16 | }, 17 | "json.schemas": [ 18 | { 19 | "fileMatch": [ 20 | "/pbiviz.json" 21 | ], 22 | "url": "./.api/v1.10.0/schema.pbiviz.json" 23 | }, 24 | { 25 | "fileMatch": [ 26 | "/capabilities.json" 27 | ], 28 | "url": "./.api/v1.10.0/schema.capabilities.json" 29 | }, 30 | { 31 | "fileMatch": [ 32 | "/dependencies.json" 33 | ], 34 | "url": "./.api/v1.10.0/schema.dependencies.json" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/assets/icon.png -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/capabilities_before_after.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/capabilities_before_after.PNG -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/capabilities_old.json: -------------------------------------------------------------------------------- 1 | { 2 | "dataRoles": [ 3 | { 4 | "displayName": "Population", 5 | "description": "Numeric variable (positive integer)", 6 | "kind": "GroupingOrMeasure", 7 | "name": "population" 8 | }, 9 | { 10 | "displayName": "Occurrence", 11 | "description": "Numeric variable (nonnegative integer). Must be smaller than 'Population'", 12 | "kind": "GroupingOrMeasure", 13 | "name": "occurrence" 14 | }, 15 | { 16 | "displayName": "Tooltips", 17 | "description": "Fields to be used as mouseover tooltips", 18 | "kind": "Grouping", 19 | "name": "tooltips" 20 | } 21 | ], 22 | "dataViewMappings": [ 23 | { 24 | "conditions": [ 25 | { 26 | "population": { 27 | "max": 1 28 | }, 29 | "occurrence": { 30 | "max": 1 31 | }, 32 | "tooltips": { 33 | "max": 7 34 | } 35 | } 36 | ], 37 | "scriptResult": { 38 | "dataInput": { 39 | "table": { 40 | "rows": { 41 | "select": [ 42 | { 43 | "for": { 44 | "in": "population" 45 | } 46 | }, 47 | { 48 | "for": { 49 | "in": "occurrence" 50 | } 51 | }, 52 | { 53 | "for": { 54 | "in": "tooltips" 55 | } 56 | } 57 | ], 58 | "dataReductionAlgorithm": { 59 | "top": {} 60 | } 61 | } 62 | } 63 | }, 64 | "script": { 65 | "scriptProviderDefault": "R", 66 | "scriptOutputType": "png", 67 | "source": { 68 | "objectName": "rcv_script", 69 | "propertyName": "source" 70 | }, 71 | "provider": { 72 | "objectName": "rcv_script", 73 | "propertyName": "provider" 74 | } 75 | } 76 | } 77 | } 78 | ], 79 | "objects": { 80 | "rcv_script": { 81 | "properties": { 82 | "provider": { 83 | "type": { 84 | "text": true 85 | } 86 | }, 87 | "source": { 88 | "type": { 89 | "scripting": { 90 | "source": true 91 | } 92 | } 93 | } 94 | } 95 | } 96 | }, 97 | "suppressDefaultTitle": true 98 | } 99 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "cranPackages": [ 3 | { 4 | "name": "ggplot2", 5 | "displayName": "GG Plot 2", 6 | "url": "https://cran.r-project.org/web/packages/ggplot2/index.html" 7 | }, 8 | { 9 | "name": "scales", 10 | "displayName": "scales: Scale Functions for Visualization", 11 | "url": "https://cran.r-project.org/web/packages/scales/index.html" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/dist/funnelRvisualVer03.pbiviz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/dist/funnelRvisualVer03.pbiviz -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visual", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "powerbi-visuals-utils-dataviewutils": { 7 | "version": "1.2.0", 8 | "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-dataviewutils/-/powerbi-visuals-utils-dataviewutils-1.2.0.tgz", 9 | "integrity": "sha1-WaHJgzVclYoj2ZAYlPZfFXUZMhM=", 10 | "dev": true 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visual", 3 | "devDependencies": { 4 | "powerbi-visuals-utils-dataviewutils": "1.2.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/pbiviz.json: -------------------------------------------------------------------------------- 1 | { 2 | "visual": { 3 | "name": "funnelRvisualVer03", 4 | "displayName": "funnelRvisualVer03", 5 | "guid": "funnelRvisualVer03_FEFF3", 6 | "visualClassName": "Visual", 7 | "version": "1.0.0", 8 | "description": "", 9 | "supportUrl": "", 10 | "gitHubUrl": "" 11 | }, 12 | "apiVersion": "1.10.0", 13 | "author": { 14 | "name": "", 15 | "email": "" 16 | }, 17 | "assets": { 18 | "icon": "assets/icon.png" 19 | }, 20 | "externalJS": [ 21 | "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js" 22 | ], 23 | "style": "style/visual.less", 24 | "capabilities": "capabilities.json", 25 | "dependencies": "dependencies.json", 26 | "stringResources": [] 27 | } 28 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/script_r_before_after_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/script_r_before_after_1.png -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/settings_ts_before_after.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/settings_ts_before_after.PNG -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/src/settings.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | module powerbi.extensibility.visual { 28 | "use strict"; 29 | import DataViewObjectsParser = powerbi.extensibility.utils.dataview.DataViewObjectsParser; 30 | 31 | export class VisualSettings extends DataViewObjectsParser { 32 | //RVIZ_IN_PBI_GUIDE:BEGIN:Added to enable user parameters 33 | public settings_funnel_params: settings_funnel_params = new settings_funnel_params(); 34 | public settings_scatter_params: settings_scatter_params = new settings_scatter_params(); 35 | public settings_axes_params: settings_axes_params = new settings_axes_params(); 36 | //RVIZ_IN_PBI_GUIDE:END:Added to enable user parameters 37 | } 38 | 39 | //RVIZ_IN_PBI_GUIDE:BEGIN:Added to enable user parameters 40 | export class settings_funnel_params { 41 | public lineColor: string = "blue"; 42 | public conf1: string = "0.95"; 43 | public conf2: string = "0.99"; 44 | } 45 | 46 | export class settings_scatter_params { 47 | public pointColor: string = "orange"; 48 | public weight: number = 10; 49 | public percentile: number = 40; 50 | public sparsify: boolean = true; 51 | } 52 | 53 | export class settings_axes_params { 54 | public colLabel: string = "gray"; 55 | public textSize: number = 12; 56 | public axisXisPercentage: boolean = true; 57 | public scaleXformat: string = "comma"; 58 | public scaleYformat: string = "none"; 59 | public sizeTicks: string = "6"; 60 | } 61 | //RVIZ_IN_PBI_GUIDE:END:Added to enable user parameters 62 | } 63 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/src/settings_old.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visualizations 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | module powerbi.extensibility.visual { 28 | "use strict"; 29 | import DataViewObjectsParser = powerbi.extensibility.utils.dataview.DataViewObjectsParser; 30 | 31 | export class VisualSettings extends DataViewObjectsParser { 32 | public rcv_script: rcv_scriptSettings = new rcv_scriptSettings(); 33 | } 34 | 35 | export class rcv_scriptSettings { 36 | // undefined 37 | public provider // undefined 38 | public source } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/src/visual.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Power BI Visual CLI 3 | * 4 | * Copyright (c) Microsoft Corporation 5 | * All rights reserved. 6 | * MIT License 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the ""Software""), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | module powerbi.extensibility.visual { 27 | "use strict"; 28 | export class Visual implements IVisual { 29 | private imageDiv: HTMLDivElement; 30 | private imageElement: HTMLImageElement; 31 | private settings: VisualSettings; 32 | 33 | public constructor(options: VisualConstructorOptions) { 34 | this.imageDiv = document.createElement("div"); 35 | this.imageDiv.className = "rcv_autoScaleImageContainer"; 36 | this.imageElement = document.createElement("img"); 37 | this.imageElement.className = "rcv_autoScaleImage"; 38 | this.imageDiv.appendChild(this.imageElement); 39 | options.element.appendChild(this.imageDiv); 40 | } 41 | 42 | public update(options: VisualUpdateOptions): void { 43 | if (!options || 44 | !options.type || 45 | !options.viewport || 46 | !options.dataViews || 47 | options.dataViews.length === 0 || 48 | !options.dataViews[0]) { 49 | return; 50 | } 51 | const dataView: DataView = options.dataViews[0]; 52 | 53 | this.settings = Visual.parseSettings(dataView); 54 | 55 | let imageUrl: string = null; 56 | if (dataView.scriptResult && dataView.scriptResult.payloadBase64) { 57 | imageUrl = "data:image/png;base64," + dataView.scriptResult.payloadBase64; 58 | } 59 | 60 | if (imageUrl) { 61 | this.imageElement.src = imageUrl; 62 | } else { 63 | this.imageElement.src = null; 64 | } 65 | 66 | this.onResizing(options.viewport); 67 | } 68 | 69 | public onResizing(finalViewport: IViewport): void { 70 | this.imageDiv.style.height = finalViewport.height + "px"; 71 | this.imageDiv.style.width = finalViewport.width + "px"; 72 | } 73 | 74 | private static parseSettings(dataView: DataView): VisualSettings { 75 | return VisualSettings.parse(dataView) as VisualSettings; 76 | } 77 | /** 78 | * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the 79 | * objects and properties you want to expose to the users in the property pane. 80 | */ 81 | public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): 82 | VisualObjectInstance[] | VisualObjectInstanceEnumerationObject { 83 | return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/style/visual.less: -------------------------------------------------------------------------------- 1 | .rcv_autoScaleImageContainer { 2 | position: relative; 3 | 4 | .rcv_autoScaleImage { 5 | max-width: 100%; 6 | max-height: 100%; 7 | position: absolute; 8 | top: 50%; 9 | /* @noflip */ 10 | left: 50%; 11 | transform: translateY(-50%) translateX(-50%); 12 | -webkit-transform: translateY(-50%) translateX(-50%); 13 | } 14 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "target": "ES5", 7 | "sourceMap": true, 8 | "out": "./.tmp/build/visual.js" 9 | }, 10 | "files": [ 11 | ".api/v1.10.0/PowerBI-visuals.d.ts", 12 | "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.d.ts", 13 | "src/settings.ts", 14 | "src/visual.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter3_RCustomVisual/funnelRvisual_v03/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "indent": [ 9 | true, 10 | "spaces" 11 | ], 12 | "no-duplicate-variable": true, 13 | "no-eval": true, 14 | "no-internal-module": false, 15 | "no-trailing-whitespace": true, 16 | "no-unsafe-finally": true, 17 | "no-var-keyword": true, 18 | "one-line": [ 19 | true, 20 | "check-open-brace", 21 | "check-whitespace" 22 | ], 23 | "quotemark": [ 24 | false, 25 | "double" 26 | ], 27 | "semicolon": [ 28 | true, 29 | "always" 30 | ], 31 | "triple-equals": [ 32 | true, 33 | "allow-null-check" 34 | ], 35 | "typedef-whitespace": [ 36 | true, 37 | { 38 | "call-signature": "nospace", 39 | "index-signature": "nospace", 40 | "parameter": "nospace", 41 | "property-declaration": "nospace", 42 | "variable-declaration": "nospace" 43 | } 44 | ], 45 | "variable-name": [ 46 | true, 47 | "ban-keywords" 48 | ], 49 | "whitespace": [ 50 | true, 51 | "check-branch", 52 | "check-decl", 53 | "check-operator", 54 | "check-separator", 55 | "check-type" 56 | ], 57 | "insecure-random": true, 58 | "no-banned-terms": true, 59 | "no-cookies": true, 60 | "no-delete-expression": true, 61 | "no-disable-auto-sanitization": true, 62 | "no-document-domain": true, 63 | "no-document-write": true, 64 | "no-exec-script": true, 65 | "no-function-constructor-with-string-args": true, 66 | "no-http-string": [true, "http://www.example.com/?.*", "http://www.examples.com/?.*"], 67 | "no-inner-html": true, 68 | "no-octal-literal": true, 69 | "no-reserved-keywords": true, 70 | "no-string-based-set-immediate": true, 71 | "no-string-based-set-interval": true, 72 | "no-string-based-set-timeout": true, 73 | "non-literal-require": true, 74 | "possible-timing-attack": true, 75 | "react-anchor-blank-noopener": true, 76 | "react-iframe-missing-sandbox": true, 77 | "react-no-dangerous-html": true 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/.npmignore: -------------------------------------------------------------------------------- 1 | typings 2 | node_modules 3 | .DS_Store 4 | .tmp 5 | dist -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "configurations": [ 4 | { 5 | "name": "Debugger", 6 | "type": "chrome", 7 | "request": "attach", 8 | "port": 9222, 9 | "sourceMaps": true, 10 | "webRoot": "${cwd}/" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 4, 3 | "editor.insertSpaces": true, 4 | "files.eol": "\n", 5 | "files.watcherExclude": { 6 | "**/.git/objects/**": true, 7 | "**/node_modules/**": true, 8 | ".tmp": true 9 | }, 10 | "files.exclude": { 11 | ".tmp": true 12 | }, 13 | "search.exclude": { 14 | ".tmp": true, 15 | "typings": true 16 | }, 17 | "json.schemas": [ 18 | { 19 | "fileMatch": [ 20 | "/pbiviz.json" 21 | ], 22 | "url": "./.api/v1.10.0/schema.pbiviz.json" 23 | }, 24 | { 25 | "fileMatch": [ 26 | "/capabilities.json" 27 | ], 28 | "url": "./.api/v1.10.0/schema.capabilities.json" 29 | }, 30 | { 31 | "fileMatch": [ 32 | "/dependencies.json" 33 | ], 34 | "url": "./.api/v1.10.0/schema.dependencies.json" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/assets/icon.png -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/assets/icon_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/assets/icon_old.png -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/capabilities_befor_after.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/capabilities_befor_after.PNG -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "cranPackages": [ 3 | { 4 | "name": "scales", 5 | "displayName": "scales: Scale Functions for Visualization", 6 | "url": "https://cran.r-project.org/web/packages/scales/index.html" 7 | }, 8 | { 9 | "name": "reshape", 10 | "displayName": "reshape: lets you flexibly restructure and aggregate data", 11 | "url": "https://cran.r-project.org/web/packages/reshape/index.html" 12 | }, 13 | { 14 | "name": "ggplot2", 15 | "displayName": "ggplot2: Create Elegant Data Visualisations Using the Grammar of Graphics", 16 | "url": "https://cran.r-project.org/web/packages/ggplot2/index.html" 17 | }, 18 | { 19 | "name": "htmlwidgets", 20 | "displayName": "htmlwidgets: HTML Widgets for R", 21 | "url": "https://cran.r-project.org/web/packages/htmlwidgets/index.html" 22 | }, 23 | { 24 | "name": "XML", 25 | "displayName": "XML: Tools for Parsing and Generating XML Within R and S-Plus", 26 | "url": "https://cran.r-project.org/web/packages/XML/index.html" 27 | }, 28 | { 29 | "name": "plotly", 30 | "displayName": "plotly: Create Interactive Web Graphics via plotly", 31 | "url": "https://cran.r-project.org/web/packages/plotly/index.html" 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/dependencies_old.json: -------------------------------------------------------------------------------- 1 | { 2 | "cranPackages": [ 3 | { 4 | "name": "ggplot2", 5 | "displayName": "GG Plot 2", 6 | "url": "https://cran.r-project.org/web/packages/ggplot2/index.html" 7 | }, 8 | { 9 | "name": "scales", 10 | "displayName": "scales: Scale Functions for Visualization", 11 | "url": "https://cran.r-project.org/web/packages/scales/index.html" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/dist/funnelRHTMLvisual.pbiviz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PowerBi-Projects/PowerBI-visuals/e8f409c928d28770210697e548887a56bb94ab87/RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/dist/funnelRHTMLvisual.pbiviz -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visual", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "powerbi-visuals-utils-dataviewutils": { 7 | "version": "1.2.0", 8 | "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-dataviewutils/-/powerbi-visuals-utils-dataviewutils-1.2.0.tgz", 9 | "integrity": "sha1-WaHJgzVclYoj2ZAYlPZfFXUZMhM=", 10 | "dev": true 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visual", 3 | "devDependencies": { 4 | "powerbi-visuals-utils-dataviewutils": "1.2.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/pbiviz.json: -------------------------------------------------------------------------------- 1 | { 2 | "visual": { 3 | "name": "funnelRHTMLvisual", 4 | "displayName": "funnelRHTMLvisual", 5 | "guid": "funnelRHTMLvisualCCC546068BF74D4A82CF250911B09EF1", 6 | "visualClassName": "Visual", 7 | "version": "1.0.0", 8 | "description": "", 9 | "supportUrl": "", 10 | "gitHubUrl": "" 11 | }, 12 | "apiVersion": "1.10.0", 13 | "author": { 14 | "name": "", 15 | "email": "" 16 | }, 17 | "assets": { 18 | "icon": "assets/icon.png" 19 | }, 20 | "externalJS": [ 21 | "node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js" 22 | ], 23 | "style": "style/visual.less", 24 | "capabilities": "capabilities.json", 25 | "dependencies": "dependencies.json", 26 | "stringResources": [] 27 | } 28 | -------------------------------------------------------------------------------- /RVisualTutorial/TutorialFunnelPlot/chapter4_RHTMLCustomVisual/funnelRHTMLvisual_v01/r_files/flatten_HTML.r: -------------------------------------------------------------------------------- 1 | ############### Utility functions ############### 2 | libraryRequireInstall = function(packageName, ...) 3 | { 4 | if(!require(packageName, character.only = TRUE)) 5 | warning(paste("*** The package: '", packageName, "' was not installed ***", sep="")) 6 | } 7 | 8 | libraryRequireInstall("XML") 9 | libraryRequireInstall("htmlwidgets") 10 | 11 | internalSaveWidget <- function(widget, fname) 12 | { 13 | tempFname = paste(fname, ".tmp", sep="") 14 | htmlwidgets::saveWidget(widget, file = tempFname, selfcontained = FALSE) 15 | FlattenHTML(tempFname, fname) 16 | } 17 | 18 | FlattenHTML <- function(fnameIn, fnameOut) 19 | { 20 | # Read and parse HTML file 21 | # Embed all js and css files into one unified file 22 | 23 | if(!file.exists(fnameIn)) 24 | return(FALSE) 25 | 26 | dir = dirname(fnameIn) 27 | html = htmlTreeParse(fnameIn, useInternal = TRUE) 28 | top = xmlRoot(html) 29 | 30 | # extract all