├── assets
├── icon.png
├── screen.png
├── thumb.png
├── icon_old.png
├── screen_old.png
└── spline_custom_RV_HTML-based.pbix
├── dist
└── PowerBI-visuals-spline.pbiviz
├── .travis.yml
├── .gitignore
├── style
└── visual.less
├── tsconfig.json
├── package.json
├── README.md
├── dependencies.json
├── pbiviz.json
├── src
├── htmlInjectionUtility.ts
├── objectEnumerationUtility.ts
└── visual.ts
├── tslint.json
├── r_files
└── flatten_HTML.r
├── capabilities.json
└── script.r
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-visuals-spline/HEAD/assets/icon.png
--------------------------------------------------------------------------------
/assets/screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-visuals-spline/HEAD/assets/screen.png
--------------------------------------------------------------------------------
/assets/thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-visuals-spline/HEAD/assets/thumb.png
--------------------------------------------------------------------------------
/assets/icon_old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-visuals-spline/HEAD/assets/icon_old.png
--------------------------------------------------------------------------------
/assets/screen_old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-visuals-spline/HEAD/assets/screen_old.png
--------------------------------------------------------------------------------
/dist/PowerBI-visuals-spline.pbiviz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-visuals-spline/HEAD/dist/PowerBI-visuals-spline.pbiviz
--------------------------------------------------------------------------------
/assets/spline_custom_RV_HTML-based.pbix:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-visuals-spline/HEAD/assets/spline_custom_RV_HTML-based.pbix
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | os:
2 | - linux
3 | sudo: required
4 | dist: trusty
5 | language: node_js
6 | node_js:
7 | - "7"
8 | install:
9 | - npm install
10 | script:
11 | - npm run lint
12 | - npm run package
13 | notifications:
14 | email: false
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | try.txt
3 | .tmp
4 | .api
5 | .Rhistory
6 | .RData
7 | out.html_files
8 | out.html_files/*
9 | dist
10 | dist/*
11 | dist/PowerBI-visuals-spline.pbiviz
12 | out.html.tmp
13 | out.html_files
14 | out.html_files/*
15 | out_files
16 | out_files/*
17 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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.7.0/PowerBI-visuals.d.ts",
12 | "src/htmlInjectionUtility.ts",
13 | "src/objectEnumerationUtility.ts",
14 | "src/visual.ts"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "visual",
3 | "scripts": {
4 | "postinstall": "pbiviz update 1.7.0",
5 | "pbiviz": "pbiviz",
6 | "package": "pbiviz package",
7 | "lint": "tslint -r \"node_modules/tslint-microsoft-contrib\" \"+(src)/**/*.ts\"",
8 | "start": "pbiviz start"
9 | },
10 | "devDependencies": {
11 | "tslint": "^4.4.2",
12 | "tslint-microsoft-contrib": "^4.0.0",
13 | "powerbi-visuals-tools": "1.7.1"
14 | }
15 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PowerBI-visuals-spline
2 | R-powered custom visual implements spline smoothing
3 |
4 | 
5 | # Overview
6 | Imagine that you have a scatter (XY) plot. It is not always easy to see the trends and to tell the story behind the data.
7 |
8 | Smoothing spline helps you to visualize and understand noisy scatterplot data.
9 |
10 | Here is how it works:
11 | * Define the fields for horizontal and vertical axes of the scatterplot
12 | * Controll the smoothness of the smoothing spline
13 | * Control the confidence levels or the spline curve (or even turn them off)
14 | * Define the colors and the rest of graphical attributes to meet your specific needs
15 |
16 | R package dependencies(auto-installed): graphics, scales, reshape
17 |
18 | Supports R versions: R 3.3.1, R 3.3.0, MRO 3.3.1, MRO 3.3.0, MRO 3.2.2
19 |
20 | See also [Spline chart at Microsoft Office store](https://store.office.com/en-us/app.aspx?assetid=WA104380860&sourcecorrid=cf75337d-2a42-4e88-913f-aa2158340d82&searchapppos=0&ui=en-US&rs=en-US&ad=US&appredirect=false)
--------------------------------------------------------------------------------
/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": "mgcv",
15 | "displayName": "mgvc: Mixed GAM Computation ",
16 | "url": "https://cran.r-project.org/web/packages/mgcv/index.html"
17 | },
18 | {
19 | "name": "ggplot2",
20 | "displayName": "GG Plot 2",
21 | "url": "https://cran.r-project.org/web/packages/ggplot2/index.html"
22 | },
23 | {
24 | "name": "plotly",
25 | "displayName": "Plotly",
26 | "url": "https://cran.r-project.org/web/packages/plotly/index.html"
27 | },
28 | {
29 | "name": "htmlwidgets",
30 | "displayName": "HTML Widgets",
31 | "url": "https://cran.r-project.org/web/packages/htmlwidgets/index.html"
32 | },
33 | {
34 | "name": "XML",
35 | "displayName": "XML",
36 | "url": "https://cran.r-project.org/web/packages/XML/index.html"
37 | }
38 | ]
39 | }
--------------------------------------------------------------------------------
/pbiviz.json:
--------------------------------------------------------------------------------
1 | {
2 | "visual": {
3 | "name": "PowerBI-visuals-spline",
4 | "displayName": "Spline",
5 | "guid": "PBI_CV_9D783E0D_2610_4C22_9576_88AD092AB59E",
6 | "visualClassName": "Visual",
7 | "version": "1.0.3",
8 | "description": "Smoothing spline helps you visualize and understand noisy data. Control the colors and the rest of attributes to meet your specific needs.
Service prerequisites: R-powered custom visual is used in service seamlessly
Desktop prerequisites: To run R scripts in Power BI Desktop, you must separately install R on your local computer.
You can download and install R for free from the Revolution Open download page or the CRAN Repository
R package dependencies(auto-installed): graphics, scales, reshape, ggplot2, mgcv, htmlWidgets, XML, plotly
Supports R versions: R 3.3.1, R 3.3.0, MRO 3.3.1, MRO 3.3.0, MRO 3.2.2
",
9 | "supportUrl": "http://community.powerbi.com/",
10 | "gitHubUrl": "https://github.com/microsoft/PowerBI-visuals-spline"
11 | },
12 | "apiVersion": "1.7.0",
13 | "author": {
14 | "name": "Microsoft",
15 | "email": "pbicvsupport@microsoft.com"
16 | },
17 | "assets": {
18 | "icon": "assets/icon.png"
19 | },
20 | "externalJS": [],
21 | "style": "style/visual.less",
22 | "capabilities": "capabilities.json",
23 | "dependencies": "dependencies.json"
24 | }
25 |
--------------------------------------------------------------------------------
/src/htmlInjectionUtility.ts:
--------------------------------------------------------------------------------
1 | module powerbi.extensibility.visual {
2 | let injectorCounter: number = 0;
3 |
4 | export function ResetInjector() : void {
5 | injectorCounter = 0;
6 | }
7 |
8 | export function injectorReady() : boolean {
9 | return injectorCounter === 0;
10 | }
11 |
12 | export function ParseElement(el: HTMLElement , target: HTMLElement) : Node[]
13 | {
14 | let arr: Node[] = [];
15 | if (!el || !el.hasChildNodes())
16 | return
17 |
18 | let nodes = el.children;
19 | for (var i=0; inodes.item(i).cloneNode(true);
28 | }
29 | target.appendChild(tempNode);
30 | arr.push(tempNode);
31 | }
32 | return arr;
33 | }
34 |
35 | function createScriptNode(refNode: Element): HTMLElement{
36 | let script = document.createElement('script');
37 | let attr = refNode.attributes;
38 | for (var i=0; i {
57 | if (injectorReady()) {
58 | window.clearInterval(intervalVar);
59 | if (window.hasOwnProperty('HTMLWidgets') && window['HTMLWidgets'].staticRender) {
60 | window['HTMLWidgets'].staticRender();
61 | }
62 | }
63 | }, 100);
64 | }
65 | }
--------------------------------------------------------------------------------
/src/objectEnumerationUtility.ts:
--------------------------------------------------------------------------------
1 | module powerbi.extensibility.visual {
2 | /**
3 | * Gets property value for a particular object.
4 | *
5 | * @function
6 | * @param {DataViewObjects} objects - Map of defined objects.
7 | * @param {string} objectName - Name of desired object.
8 | * @param {string} propertyName - Name of desired property.
9 | * @param {T} defaultValue - Default value of desired property.
10 | */
11 | export function getValue(objects: DataViewObjects, objectName: string, propertyName: string, defaultValue: T): T {
12 | if (objects) {
13 | let object = objects[objectName];
14 | if (object) {
15 | let property: T = object[propertyName];
16 | if (property !== undefined) {
17 | return property;
18 | }
19 | }
20 | }
21 | return defaultValue;
22 | }
23 |
24 | /**
25 | * Gets property value for a particular object in a category.
26 | *
27 | * @function
28 | * @param {DataViewCategoryColumn} category - List of category objects.
29 | * @param {number} index - Index of category object.
30 | * @param {string} objectName - Name of desired object.
31 | * @param {string} propertyName - Name of desired property.
32 | * @param {T} defaultValue - Default value of desired property.
33 | */
34 | export function getCategoricalObjectValue(category: DataViewCategoryColumn, index: number, objectName: string, propertyName: string, defaultValue: T): T {
35 | let categoryObjects = category.objects;
36 |
37 | if (categoryObjects) {
38 | let categoryObject: DataViewObject = categoryObjects[index];
39 | if (categoryObject) {
40 | let object = categoryObject[objectName];
41 | if (object) {
42 | let property: T = object[propertyName];
43 | if (property !== undefined) {
44 | return property;
45 | }
46 | }
47 | }
48 | }
49 | return defaultValue;
50 | }
51 |
52 | // returns value in range
53 | export function inMinMax(a: number, mi: number, ma: number)
54 | {
55 | if(ama)
58 | return ma;
59 | return a;
60 | }
61 |
62 |
63 | }
--------------------------------------------------------------------------------
/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": [
67 | true,
68 | "http://www.example.com/?.*",
69 | "http://www.examples.com/?.*"
70 | ],
71 | "no-inner-html": true,
72 | "no-octal-literal": true,
73 | "no-reserved-keywords": true,
74 | "no-string-based-set-immediate": true,
75 | "no-string-based-set-interval": true,
76 | "no-string-based-set-timeout": true,
77 | "non-literal-require": true,
78 | "possible-timing-attack": true,
79 | "react-anchor-blank-noopener": true,
80 | "react-iframe-missing-sandbox": true,
81 | "react-no-dangerous-html": true
82 | }
83 | }
--------------------------------------------------------------------------------
/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