Skip to content

Commit 76e0176

Browse files
committedAug 12, 2019
All changes to complete the visual for part 1 of the tutorial.
1 parent f360b99 commit 76e0176

15 files changed

+2226
-1
lines changed
 

‎.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,6 @@ typings/
5959

6060
# next.js build output
6161
.next
62+
63+
.tmp
64+
webpack.statistics.dev.html

‎.vscode/launch.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
}

‎.vscode/settings.json

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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.6.0/schema.pbiviz.json"
23+
},
24+
{
25+
"fileMatch": [
26+
"/capabilities.json"
27+
],
28+
"url": "./.api/v1.6.0/schema.capabilities.json"
29+
},
30+
{
31+
"fileMatch": [
32+
"/dependencies.json"
33+
],
34+
"url": "./.api/v1.6.0/schema.dependencies.json"
35+
}
36+
]
37+
}

‎README.md

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,24 @@
11
# powerbi-visuals-example-simple-line-chart
2-
Very simple demonstration of migrating a regular d3.js line chart into the Power BI Custom Visuals SDK
2+
3+
This is a very simple demonstration of migrating a regular d3.js line chart into the Power BI Custom Visuals SDK, and is documented in these online posts:
4+
5+
* [Lifting and Shifting a Simple d3.js Line Chart into A Power BI Custom Visual (Part 1)](https://coacervo.co/examples/d3-line-chart-1)
6+
* Lifting and Shifting a Simple d3.js Line Chart into A Power BI Custom Visual (Part 2) - TBC
7+
8+
Please refer to these articles for further details.
9+
10+
To work with this repository, you will need the Power BI Custom Visuals SDK installed. [Refer here for instructions on setting up your developer environment](https://docs.microsoft.com/en-us/power-bi/developer/custom-visual-develop-tutorial#setting-up-the-developer-environment).
11+
12+
Once checked out, and the pre-requisites set up, you just need to run:
13+
14+
```
15+
npm i
16+
```
17+
18+
From the root of the checkout, and then:
19+
20+
```
21+
pbiviz start
22+
```
23+
24+
To run the visual server. You can then test in the Power BI service.

‎Simple Line Chart Custom Visual.pbix

54.9 KB
Binary file not shown.

‎assets/icon.png

1.5 KB
Loading

‎capabilities.json

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"dataRoles": [
3+
{
4+
"displayName": "Category Data",
5+
"name": "category",
6+
"kind": "Grouping"
7+
},
8+
{
9+
"displayName": "Measure Data",
10+
"name": "measure",
11+
"kind": "Measure"
12+
}
13+
],
14+
"objects": {},
15+
"dataViewMappings": [
16+
{
17+
"conditions": [
18+
{
19+
"category": {
20+
"max": 1
21+
},
22+
"measure": {
23+
"max": 1
24+
}
25+
}
26+
],
27+
"categorical": {
28+
"categories": {
29+
"for": {
30+
"in": "category"
31+
},
32+
"dataReductionAlgorithm": {
33+
"top": {
34+
"count": 2000
35+
}
36+
}
37+
},
38+
"values": {
39+
"select": [
40+
{
41+
"bind": {
42+
"to": "measure"
43+
}
44+
}
45+
]
46+
}
47+
}
48+
}
49+
]
50+
}

‎package-lock.json

+1,830
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "visual",
3+
"scripts": {
4+
"pbiviz": "pbiviz",
5+
"start": "pbiviz start",
6+
"package": "pbiviz package",
7+
"lint": "tslint -r \"node_modules/tslint-microsoft-contrib\" \"+(src|test)/**/*.ts\""
8+
},
9+
"dependencies": {
10+
"@babel/runtime": "^7.4.5",
11+
"@babel/runtime-corejs2": "^7.4.5",
12+
"@types/d3": "5.5.0",
13+
"d3": "5.5.0",
14+
"powerbi-visuals-utils-dataviewutils": "^2.2.0",
15+
"powerbi-visuals-api": "~2.6.0",
16+
"core-js": "3.1.3"
17+
},
18+
"devDependencies": {
19+
"ts-loader": "5.2.2",
20+
"typescript": "3.0.1"
21+
}
22+
}

‎pbiviz.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"visual":{"name":"d3LineChartExample","displayName":"d3LineChartExample","guid":"d3LineChartExample313DC31569204B798A9C88D7363C4760","visualClassName":"Visual","version":"1.0.0","description":"","supportUrl":"","gitHubUrl":""},"apiVersion":"2.6.0","author":{"name":"","email":""},"assets":{"icon":"assets/icon.png"},"externalJS":null,"style":"style/visual.less","capabilities":"capabilities.json","dependencies":null,"stringResources":[]}

‎src/settings.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Simple d3.js Line Chart
3+
*
4+
* Copyright (c) Daniel Marsh-Patrick
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+
"use strict";
28+
29+
import { dataViewObjectsParser } from "powerbi-visuals-utils-dataviewutils";
30+
import DataViewObjectsParser = dataViewObjectsParser.DataViewObjectsParser;
31+
32+
export class VisualSettings extends DataViewObjectsParser {}

‎src/visual.ts

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Simple d3.js Line Chart
3+
*
4+
* Copyright (c) Daniel Marsh-Patrick
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+
"use strict";
28+
29+
import "core-js/stable";
30+
import "./../style/visual.less";
31+
import powerbi from "powerbi-visuals-api";
32+
import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;
33+
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
34+
import IVisual = powerbi.extensibility.visual.IVisual;
35+
import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;
36+
import VisualObjectInstance = powerbi.VisualObjectInstance;
37+
import DataView = powerbi.DataView;
38+
import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;
39+
import { VisualSettings } from "./settings";
40+
41+
/** This specifices the 'shape' of the data in each row. */
42+
interface ILineChartRow {
43+
date: Date,
44+
value: number
45+
}
46+
47+
export class Visual implements IVisual {
48+
private target: HTMLElement;
49+
private settings: VisualSettings;
50+
51+
constructor(options: VisualConstructorOptions) {
52+
console.log('Visual constructor', options);
53+
this.target = options.element;
54+
}
55+
56+
public update(options: VisualUpdateOptions) {
57+
console.log('Visual update', options);
58+
this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
59+
60+
/** Test 1: Data view has both fields added */
61+
let dataViews = options.dataViews;
62+
console.log('Test 1: Valid data view...');
63+
if (!dataViews
64+
|| !dataViews[0]
65+
|| !dataViews[0].categorical
66+
|| !dataViews[0].categorical.categories
67+
|| !dataViews[0].categorical.values
68+
|| !dataViews[0].metadata
69+
) {
70+
console.log('Test 1 FAILED. No data to draw table.');
71+
return;
72+
}
73+
74+
/** If we get this far, we can trust that we can work with the data! */
75+
let categorical = dataViews[0].categorical;
76+
77+
/** Test 2: Category matches our expected data type (dateTime) */
78+
console.log('Test 2: Category field has correct type (dateTime)...');
79+
if (!categorical.categories[0].source.type.dateTime) {
80+
console.log('Test 2 FAILED. Category is incorrect data type.');
81+
return;
82+
}
83+
84+
/** Map our data into an array that looks like our reference visual.
85+
* We're going to map the `categories[0].values` array in-place and return
86+
* an `ILineChartRow` object for each entry. Because the values array elements
87+
* correspond with their equivalent `categories[0].values` element, we can use
88+
* the current index to get the value as we map.
89+
* note that Power BI sees values as `PrimitiveType`, which means we need to
90+
* cast them as the types we need to match the interface we defined. */
91+
let data: ILineChartRow[] = categorical.categories[0].values.map(
92+
(cat, idx) => (
93+
{
94+
date: <Date>cat,
95+
value: <number>categorical.values[0].values[idx]
96+
}
97+
)
98+
);
99+
100+
/** Parse our mapped data and view the output */
101+
console.log(data);
102+
103+
}
104+
105+
private static parseSettings(dataView: DataView): VisualSettings {
106+
return VisualSettings.parse(dataView) as VisualSettings;
107+
}
108+
109+
/**
110+
* This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
111+
* objects and properties you want to expose to the users in the property pane.
112+
*
113+
*/
114+
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
115+
return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
116+
}
117+
}

‎style/visual.less

Whitespace-only changes.

‎tsconfig.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"compilerOptions": {
3+
"allowJs": false,
4+
"emitDecoratorMetadata": true,
5+
"experimentalDecorators": true,
6+
"target": "es6",
7+
"sourceMap": true,
8+
"outDir": "./.tmp/build/",
9+
"moduleResolution": "node",
10+
"declaration": true,
11+
"lib": [
12+
"es2015",
13+
"dom"
14+
]
15+
},
16+
"files": [
17+
"./src/visual.ts"
18+
]
19+
}

‎tslint.json

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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+
}

0 commit comments

Comments
 (0)
Please sign in to comment.