Skip to content

Commit 3724e65

Browse files
authored
Merge pull request #522 from tableau/dev
Merge dev to main for v1.10.0
2 parents 0a58e84 + a87a4a9 commit 3724e65

File tree

112 files changed

+29046
-1374
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+29046
-1374
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest manifest-version="0.1" xmlns="http://www.tableau.com/xml/extension_manifest">
3+
<dashboard-extension id="com.tableau.extensions.samples.annotation" extension-version="0.1.0">
4+
<default-locale>en_US</default-locale>
5+
<name resource-id="name"/>
6+
<description>Annotation Sample</description>
7+
<author name="tableau" email="[email protected]" organization="tableau" website="https://www.tableau.com"/>
8+
<min-api-version>1.10</min-api-version>
9+
<source-location>
10+
<url>http://localhost:8765/Samples-Typescript/Annotation/annotation.html</url>
11+
</source-location>
12+
<icon>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</icon>
13+
</dashboard-extension>
14+
<resources>
15+
<resource id="name">
16+
<text locale="en_US">Annotation Sample</text>
17+
</resource>
18+
</resources>
19+
</manifest>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Annotation Sample</title>
5+
<!-- jQuery -->
6+
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
7+
8+
<!-- Bootstrap -->
9+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
10+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
11+
12+
<!-- Extensions Library -->
13+
<script src="../../lib/tableau.extensions.1.latest.js"></script>
14+
15+
<!-- Our extension's code -->
16+
<script src="../../dist/annotation.js"></script>
17+
</head>
18+
<body>
19+
<div class="container">
20+
<h2>Annotation Sample</h2>
21+
<p>Select marks to generate annotations.</p>
22+
<div>
23+
<p style="display: inline">Worksheet To Annotate:</p>
24+
<!-- Options to select will be populated by the Extension -->
25+
<select id="worksheet-selection" class="form-select" aria-label="Default select example" style="display: inline" disabled></select>
26+
</div>
27+
</div>
28+
</body>
29+
</html>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { MarksSelectedEvent, TableauEvent, Worksheet } from '@tableau/extensions-api-types';
2+
3+
// Wrap everything in an anonymous function to avoid polluting the global namespace
4+
(async () => {
5+
class Annotation {
6+
private worksheets: Worksheet[];
7+
private currentWorksheet: Worksheet;
8+
private self: Annotation;
9+
10+
// Avoid globals.
11+
constructor(private _$: JQueryStatic) {}
12+
13+
/**
14+
* Initializes the extension
15+
*/
16+
public async initialize() {
17+
console.log('Waiting for DOM ready');
18+
await this._$.ready;
19+
console.log('Initializing extension API');
20+
await tableau.extensions.initializeAsync();
21+
22+
this.worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
23+
if (this.worksheets.length === 0) {
24+
return;
25+
}
26+
// populating selection menu with worksheets
27+
this.worksheets.forEach((worksheet, index) => {
28+
const menuOption = this._$('<option>').val(index).text(worksheet.name);
29+
this._$('#worksheet-selection').append(menuOption);
30+
});
31+
// selecting the first worksheet by default
32+
this.currentWorksheet = this.worksheets[0];
33+
this.currentWorksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, this.onMarksSelectedEvent);
34+
// adding functionality to selection menu
35+
this._$('#worksheet-selection').on('click', this.onMenuSelection.bind(this));
36+
this._$('#worksheet-selection').prop('disabled', false);
37+
}
38+
39+
// Upon selecting marks, the worksheet will generate annotations replacing the previous ones
40+
private async onMarksSelectedEvent(event: TableauEvent) {
41+
const markSelectedEvent = event as MarksSelectedEvent;
42+
const worksheet = markSelectedEvent.worksheet;
43+
const marksCollection = await markSelectedEvent.getMarksAsync();
44+
// In most cases the marksCollection will have a single data table
45+
const dataTable = marksCollection.data[0];
46+
const marksInfo = dataTable.marksInfo;
47+
// returning if no marks were selected
48+
if (marksInfo.length === 0) {
49+
return;
50+
}
51+
52+
// clearing the current annotations
53+
const annotations = await worksheet.getAnnotationsAsync();
54+
for (const annotation of annotations) {
55+
await worksheet.removeAnnotationAsync(annotation);
56+
}
57+
58+
// adding annotations for each of the selected marks
59+
marksInfo.forEach(async (markInfo, rowIndex) => {
60+
// getting data values corresponding to each markInfo
61+
const rowData = dataTable.data[rowIndex];
62+
// building annotation text
63+
let annotationText = '';
64+
dataTable.columns.forEach((column, colIndex) => {
65+
annotationText += `${column.fieldName}: ${rowData[colIndex].formattedValue}\n`;
66+
});
67+
await worksheet.annotateMarkAsync(markInfo, annotationText);
68+
});
69+
}
70+
71+
// This function will clear annotations and start listening for marks on the newly selected worksheet.
72+
private async onMenuSelection() {
73+
const selectedWorksheet = this.worksheets[this._$('#worksheet-selection option:selected').val() as number];
74+
if (this.currentWorksheet === selectedWorksheet) {
75+
return;
76+
}
77+
// deactivating current worksheet and clearing annotations
78+
this.currentWorksheet.removeEventListener(
79+
tableau.TableauEventType.MarkSelectionChanged,
80+
this.onMarksSelectedEvent,
81+
);
82+
const annotations = await this.currentWorksheet.getAnnotationsAsync();
83+
for (const annotation of annotations) {
84+
await this.currentWorksheet.removeAnnotationAsync(annotation);
85+
}
86+
// activating selected worksheet
87+
selectedWorksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, this.onMarksSelectedEvent);
88+
this.currentWorksheet = selectedWorksheet;
89+
}
90+
}
91+
92+
console.log('Initializing Annotation extension.');
93+
await new Annotation($).initialize();
94+
})();

Samples/Annotation/Annotation.trex

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest manifest-version="0.1" xmlns="http://www.tableau.com/xml/extension_manifest">
3+
<dashboard-extension id="com.tableau.extensions.samples.annotation" extension-version="0.1.0">
4+
<default-locale>en_US</default-locale>
5+
<name resource-id="name"/>
6+
<description>Annotation Sample</description>
7+
<author name="tableau" email="[email protected]" organization="tableau" website="https://www.tableau.com"/>
8+
<min-api-version>1.10</min-api-version>
9+
<source-location>
10+
<url>http://localhost:8765/Samples/Annotation/annotation.html</url>
11+
</source-location>
12+
<icon>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</icon>
13+
</dashboard-extension>
14+
<resources>
15+
<resource id="name">
16+
<text locale="en_US">Annotation Sample</text>
17+
</resource>
18+
</resources>
19+
</manifest>

Samples/Annotation/annotation.html

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Annotation Sample</title>
5+
<!-- jQuery -->
6+
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
7+
8+
<!-- Bootstrap -->
9+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
10+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
11+
12+
<!-- Extensions Library -->
13+
<script src="../../lib/tableau.extensions.1.latest.js"></script>
14+
15+
<!-- Our extension's code -->
16+
<script src="./annotation.js"></script>
17+
</head>
18+
<body>
19+
<div class="container">
20+
<h2>Annotation Sample</h2>
21+
<p>Select marks to generate annotations.</p>
22+
<div>
23+
<p style="display: inline">Worksheet To Annotate:</p>
24+
<!-- Options to select will be populated by the Extension -->
25+
<select id="worksheet-selection" class="form-select" aria-label="Default select example" style="display: inline" disabled></select>
26+
</div>
27+
</div>
28+
</body>
29+
</html>

Samples/Annotation/annotation.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use strict';
2+
3+
// Wrap everything in an anonymous function to avoid polluting the global namespace
4+
(function () {
5+
let worksheets = [];
6+
let currentWorksheet;
7+
8+
$(document).ready(function () {
9+
tableau.extensions.initializeAsync().then(function () {
10+
worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
11+
if (worksheets.length === 0) {
12+
return;
13+
}
14+
// populating selection menu with worksheets
15+
worksheets.forEach((worksheet, index) => {
16+
const menuOption = $('<option>').val(index).text(worksheet.name);
17+
$('#worksheet-selection').append(menuOption);
18+
});
19+
// selecting the first worksheet by default
20+
currentWorksheet = worksheets[0];
21+
currentWorksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, onMarksSelectedEvent);
22+
// adding functionality to selection menu
23+
$('#worksheet-selection').on('click', onMenuSelection);
24+
$('#worksheet-selection').prop('disabled', false);
25+
});
26+
});
27+
28+
// Upon selecting marks, the worksheet will generate annotations replacing the previous ones
29+
async function onMarksSelectedEvent (event) {
30+
const worksheet = event.worksheet;
31+
const marksCollection = await event.getMarksAsync();
32+
// In most cases the marksCollection will have a single data table
33+
const dataTable = marksCollection.data[0];
34+
const marksInfo = dataTable.marksInfo;
35+
// returning if no marks were selected
36+
if (marksInfo.length === 0) {
37+
return;
38+
}
39+
40+
// clearing the current annotations
41+
const annotations = await worksheet.getAnnotationsAsync();
42+
for (const annotation of annotations) {
43+
await worksheet.removeAnnotationAsync(annotation);
44+
}
45+
46+
// adding annotations for each of the selected marks
47+
marksInfo.forEach(async (markInfo, rowIndex) => {
48+
// getting data values corresponding to each markInfo
49+
const rowData = dataTable.data[rowIndex];
50+
// building annotation text
51+
let annotationText = '';
52+
dataTable.columns.forEach((column, colIndex) => {
53+
annotationText += `${column.fieldName}: ${rowData[colIndex].formattedValue}\n`;
54+
});
55+
await worksheet.annotateMarkAsync(markInfo, annotationText);
56+
});
57+
}
58+
59+
// This function will clear annotations and start listening for marks on the newly selected worksheet.
60+
async function onMenuSelection () {
61+
const selectedWorksheet = worksheets[$('#worksheet-selection option:selected').val()];
62+
if (currentWorksheet === selectedWorksheet) {
63+
return;
64+
}
65+
// deactivating current worksheet and clearing annotations
66+
currentWorksheet.removeEventListener(tableau.TableauEventType.MarkSelectionChanged, onMarksSelectedEvent);
67+
const annotations = await currentWorksheet.getAnnotationsAsync();
68+
for (const annotation of annotations) {
69+
await currentWorksheet.removeAnnotationAsync(annotation);
70+
}
71+
// activating selected worksheet
72+
selectedWorksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, onMarksSelectedEvent);
73+
currentWorksheet = selectedWorksheet;
74+
}
75+
})();

Samples/UINamespace-sandboxed/uiNamespace.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,27 @@
2929
Configure extension to proceed.
3030
</div>
3131
</p>
32+
<div class="container" style="border:1px solid #cecece">
33+
<h6>Dialog Style</h6>
34+
<div class="form-check">
35+
<input class="form-check-input" type="radio" name="dialogStyleRadio" id="modalStyle" checked>
36+
<label class="form-check-label" for="modalStyle">
37+
Modal
38+
</label>
39+
</div>
40+
<div class="form-check">
41+
<input class="form-check-input" type="radio" name="dialogStyleRadio" id="modelessStyle">
42+
<label class="form-check-label" for="modelessStyle">
43+
Modeless
44+
</label>
45+
</div>
46+
<div class="form-check">
47+
<input class="form-check-input" type="radio" name="dialogStyleRadio" id="windowStyle">
48+
<label class="form-check-label" for="windowStyle">
49+
Window
50+
</label>
51+
</div>
52+
</div>
3253
</div>
3354
</body>
3455
</html>

Samples/UINamespace-sandboxed/uiNamespace.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@
3939
// to be updated if the extension is deployed to a new location.
4040
const popupUrl = 'uiNamespaceDialog.html';
4141

42+
// This checks for the selected dialog style in the radio form.
43+
let dialogStyle;
44+
const dialogStyleOptions = document.getElementsByName('dialogStyleRadio');
45+
if (dialogStyleOptions[0].checked) {
46+
dialogStyle = tableau.DialogStyle.Modal;
47+
} else if (dialogStyleOptions[1].checked) {
48+
dialogStyle = tableau.DialogStyle.Modeless;
49+
} else {
50+
dialogStyle = tableau.DialogStyle.Window;
51+
}
52+
4253
/**
4354
* This is the API call that actually displays the popup extension to the user. The
4455
* popup is always a modal dialog. The only required parameter is the URL of the popup,
@@ -51,7 +62,7 @@
5162
* default interval of refresh.
5263
*/
5364
tableau.extensions.ui
54-
.displayDialogAsync(popupUrl, defaultIntervalInMin, { height: 500, width: 500 })
65+
.displayDialogAsync(popupUrl, defaultIntervalInMin, { height: 500, width: 500, dialogStyle })
5566
.then((closePayload) => {
5667
// The promise is resolved when the dialog has been expectedly closed, meaning that
5768
// the popup extension has called tableau.extensions.ui.closeDialog.

Samples/UINamespace/uiNamespace.html

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
1111

1212
<!-- Bootstrap -->
13-
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
14-
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" ></script>
13+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" >
14+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" ></script>
1515

1616
<!-- Extensions Library (this will be hosted on a CDN eventually) -->
1717
<script src="../../lib/tableau.extensions.1.latest.js"></script>
@@ -29,6 +29,27 @@
2929
Configure extension to proceed.
3030
</div>
3131
</p>
32+
<div class="container" style="border:1px solid #cecece">
33+
<h6>Dialog Style</h6>
34+
<div class="form-check">
35+
<input class="form-check-input" type="radio" name="dialogStyleRadio" id="modalStyle" checked>
36+
<label class="form-check-label" for="modalStyle">
37+
Modal
38+
</label>
39+
</div>
40+
<div class="form-check">
41+
<input class="form-check-input" type="radio" name="dialogStyleRadio" id="modelessStyle">
42+
<label class="form-check-label" for="modelessStyle">
43+
Modeless
44+
</label>
45+
</div>
46+
<div class="form-check">
47+
<input class="form-check-input" type="radio" name="dialogStyleRadio" id="windowStyle">
48+
<label class="form-check-label" for="windowStyle">
49+
Window
50+
</label>
51+
</div>
52+
</div>
3253
</div>
3354
</body>
3455
</html>

0 commit comments

Comments
 (0)