pptb-standard-sample-tool 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/app.js +161 -0
- package/dist/index.html +17 -2
- package/npm-shrinkwrap.json +6 -6
- package/package.json +17 -2
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ This sample demonstrates:
|
|
|
18
18
|
|
|
19
19
|
- ✅ **Dataverse API Usage**
|
|
20
20
|
- FetchXML queries
|
|
21
|
+
- Multi-connection queries (primary and secondary)
|
|
21
22
|
- CRUD operations (Create, Read, Update, Delete)
|
|
22
23
|
- Entity metadata retrieval
|
|
23
24
|
- Error handling
|
|
@@ -102,6 +103,7 @@ html-sample/
|
|
|
102
103
|
- FetchXML query to retrieve top 10 accounts
|
|
103
104
|
- Display results with formatting
|
|
104
105
|
- If a FetchXML is saved in Tool Settings, the Query button will use that instead of the default
|
|
106
|
+
- This sample supports multi-connection: try the "Secondary" buttons to run the same queries against the secondary connection
|
|
105
107
|
|
|
106
108
|
**CRUD Operations:**
|
|
107
109
|
- Create new account records
|
|
@@ -230,6 +232,22 @@ const result = await dataverse.fetchXmlQuery(`
|
|
|
230
232
|
</fetch>
|
|
231
233
|
`);
|
|
232
234
|
|
|
235
|
+
// Query with FetchXML targeting the secondary connection
|
|
236
|
+
const secondaryResult = await dataverse.fetchXmlQuery(`
|
|
237
|
+
<fetch top="5">
|
|
238
|
+
<entity name="account">
|
|
239
|
+
<attribute name="name" />
|
|
240
|
+
<order attribute="name" />
|
|
241
|
+
</entity>
|
|
242
|
+
</fetch>
|
|
243
|
+
`, 'secondary');
|
|
244
|
+
|
|
245
|
+
// Query via OData (secondary)
|
|
246
|
+
const odataResult = await (dataverse as any).queryData(
|
|
247
|
+
'$select=name,accountid&$filter=statecode eq 0&$orderby=name&$top=5',
|
|
248
|
+
'secondary'
|
|
249
|
+
);
|
|
250
|
+
|
|
233
251
|
// Create record
|
|
234
252
|
const account = await dataverse.create('account', {
|
|
235
253
|
name: 'Contoso Ltd',
|
|
@@ -246,6 +264,9 @@ await dataverse.delete('account', accountId);
|
|
|
246
264
|
|
|
247
265
|
// Get metadata
|
|
248
266
|
const metadata = await dataverse.getEntityMetadata('account');
|
|
267
|
+
|
|
268
|
+
// Get metadata on secondary
|
|
269
|
+
const metadataSecondary = await dataverse.getEntityMetadata('account', true, ['LogicalName'], 'secondary');
|
|
249
270
|
```
|
|
250
271
|
|
|
251
272
|
## Troubleshooting
|
package/dist/app.js
CHANGED
|
@@ -15,6 +15,7 @@ const toolbox = window.toolboxAPI;
|
|
|
15
15
|
const dataverse = window.dataverseAPI;
|
|
16
16
|
// Application state
|
|
17
17
|
let currentConnection = null;
|
|
18
|
+
let secondaryConnection = null;
|
|
18
19
|
let currentTerminal = null;
|
|
19
20
|
let createdId = null;
|
|
20
21
|
/**
|
|
@@ -45,6 +46,7 @@ async function initialize() {
|
|
|
45
46
|
async function refreshConnection() {
|
|
46
47
|
try {
|
|
47
48
|
currentConnection = await toolbox.connections.getActiveConnection();
|
|
49
|
+
secondaryConnection = await toolbox.connections.getSecondaryConnection();
|
|
48
50
|
const connectionInfo = document.getElementById('connection-info');
|
|
49
51
|
if (!connectionInfo)
|
|
50
52
|
return;
|
|
@@ -78,6 +80,42 @@ async function refreshConnection() {
|
|
|
78
80
|
connectionInfo.innerHTML = '<p><strong>⚠️ No active connection</strong><br>Please connect to a Dataverse environment to use this tool.</p>';
|
|
79
81
|
log('No active connection found', 'warning');
|
|
80
82
|
}
|
|
83
|
+
if (secondaryConnection) {
|
|
84
|
+
const secondaryInfo = document.getElementById('secondary-connection-info');
|
|
85
|
+
if (!secondaryInfo)
|
|
86
|
+
return;
|
|
87
|
+
const envClass = secondaryConnection.environment.toLowerCase();
|
|
88
|
+
secondaryInfo.className = 'info-box success';
|
|
89
|
+
secondaryInfo.innerHTML = `
|
|
90
|
+
<div class="connection-details">
|
|
91
|
+
<div class="connection-item">
|
|
92
|
+
<strong>Name:</strong>
|
|
93
|
+
<span>${secondaryConnection.name}</span>
|
|
94
|
+
</div>
|
|
95
|
+
<div class="connection-item">
|
|
96
|
+
<strong>URL:</strong>
|
|
97
|
+
<span>${secondaryConnection.url}</span>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="connection-item">
|
|
100
|
+
<strong>Environment:</strong>
|
|
101
|
+
<span class="env-badge ${envClass}">${secondaryConnection.environment}</span>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="connection-item">
|
|
104
|
+
<strong>ID:</strong>
|
|
105
|
+
<span>${secondaryConnection.id}</span>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
`;
|
|
109
|
+
log(`Secondary connection: ${secondaryConnection.name}`, 'success');
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const secondaryInfo = document.getElementById('secondary-connection-info');
|
|
113
|
+
if (!secondaryInfo)
|
|
114
|
+
return;
|
|
115
|
+
secondaryInfo.className = 'info-box warning';
|
|
116
|
+
secondaryInfo.innerHTML = '<p><strong>⚠️ No secondary connection</strong><br>Please connect to a secondary Dataverse environment to use this tool.</p>';
|
|
117
|
+
log('No secondary connection found', 'warning');
|
|
118
|
+
}
|
|
81
119
|
}
|
|
82
120
|
catch (error) {
|
|
83
121
|
log(`Error refreshing connection: ${error.message}`, 'error');
|
|
@@ -129,6 +167,9 @@ function setupEventHandlers() {
|
|
|
129
167
|
document.getElementById('close-terminal-btn')?.addEventListener('click', closeTerminal);
|
|
130
168
|
// Dataverse query button
|
|
131
169
|
document.getElementById('query-accounts-btn')?.addEventListener('click', queryAccounts);
|
|
170
|
+
document.getElementById('query-odata-btn')?.addEventListener('click', queryODataAccounts);
|
|
171
|
+
document.getElementById('query-accounts-secondary-btn')?.addEventListener('click', queryAccountsSecondary);
|
|
172
|
+
document.getElementById('query-odata-secondary-btn')?.addEventListener('click', queryODataSecondary);
|
|
132
173
|
// CRUD buttons
|
|
133
174
|
document.getElementById('create-contact-btn')?.addEventListener('click', createContact);
|
|
134
175
|
document.getElementById('update-contact-btn')?.addEventListener('click', updateContact);
|
|
@@ -358,6 +399,126 @@ async function queryAccounts() {
|
|
|
358
399
|
log(`Error querying accounts: ${error.message}`, 'error');
|
|
359
400
|
}
|
|
360
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* Query accounts from Dataverse using OData
|
|
404
|
+
*/
|
|
405
|
+
async function queryODataAccounts() {
|
|
406
|
+
if (!currentConnection) {
|
|
407
|
+
await showNotification('No Connection', 'Please connect to a Dataverse environment', 'warning');
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
try {
|
|
411
|
+
const output = document.getElementById('query-odata-output');
|
|
412
|
+
if (output)
|
|
413
|
+
output.textContent = 'Querying accounts via OData...\n';
|
|
414
|
+
// Example OData query: top 5 active accounts with basic fields
|
|
415
|
+
const odata = `$select=name,accountid,emailaddress1,telephone1&$filter=statecode eq 0&$orderby=name&$top=5`;
|
|
416
|
+
const result = await dataverse.queryData(odata);
|
|
417
|
+
if (output) {
|
|
418
|
+
output.textContent = `Found ${result.value.length} active account(s) (OData):\n\n`;
|
|
419
|
+
result.value.forEach((account, index) => {
|
|
420
|
+
output.textContent += `${index + 1}. ${account.name}\n`;
|
|
421
|
+
output.textContent += ` ID: ${account.accountid}\n`;
|
|
422
|
+
if (account.emailaddress1)
|
|
423
|
+
output.textContent += ` Email: ${account.emailaddress1}\n`;
|
|
424
|
+
if (account.telephone1)
|
|
425
|
+
output.textContent += ` Phone: ${account.telephone1}\n`;
|
|
426
|
+
output.textContent += '\n';
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
log(`Queried ${result.value.length} accounts via OData`, 'success');
|
|
430
|
+
}
|
|
431
|
+
catch (error) {
|
|
432
|
+
const output = document.getElementById('query-odata-output');
|
|
433
|
+
if (output)
|
|
434
|
+
output.textContent = `Error (OData): ${error.message}`;
|
|
435
|
+
log(`Error OData querying accounts: ${error.message}`, 'error');
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Query accounts from Dataverse using the secondary connection (FetchXML)
|
|
440
|
+
*/
|
|
441
|
+
async function queryAccountsSecondary() {
|
|
442
|
+
if (!secondaryConnection) {
|
|
443
|
+
await showNotification('No Secondary Connection', 'Please configure a secondary Dataverse connection', 'warning');
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
try {
|
|
447
|
+
const output = document.getElementById('query-output-secondary');
|
|
448
|
+
if (output)
|
|
449
|
+
output.textContent = 'Querying accounts using secondary connection...\n';
|
|
450
|
+
// Use saved FetchXML if present, otherwise default
|
|
451
|
+
const saved = await getSetting('demo.fetchxml');
|
|
452
|
+
const fetchXml = (saved && saved.trim().length > 0) ? saved : `
|
|
453
|
+
<fetch top="10">
|
|
454
|
+
<entity name="account">
|
|
455
|
+
<attribute name="name" />
|
|
456
|
+
<attribute name="accountid" />
|
|
457
|
+
<attribute name="emailaddress1" />
|
|
458
|
+
<attribute name="telephone1" />
|
|
459
|
+
<order attribute="name" />
|
|
460
|
+
</entity>
|
|
461
|
+
</fetch>
|
|
462
|
+
`.trim();
|
|
463
|
+
// Pass 'secondary' to target the secondary connection
|
|
464
|
+
const result = await dataverse.fetchXmlQuery(fetchXml, 'secondary');
|
|
465
|
+
if (output) {
|
|
466
|
+
output.textContent = `Found ${result.value.length} account(s) on secondary:\n\n`;
|
|
467
|
+
result.value.forEach((account, index) => {
|
|
468
|
+
output.textContent += `${index + 1}. ${account.name}\n`;
|
|
469
|
+
output.textContent += ` ID: ${account.accountid}\n`;
|
|
470
|
+
if (account.emailaddress1)
|
|
471
|
+
output.textContent += ` Email: ${account.emailaddress1}\n`;
|
|
472
|
+
if (account.telephone1)
|
|
473
|
+
output.textContent += ` Phone: ${account.telephone1}\n`;
|
|
474
|
+
output.textContent += '\n';
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
log(`Queried ${result.value.length} accounts on secondary`, 'success');
|
|
478
|
+
}
|
|
479
|
+
catch (error) {
|
|
480
|
+
const output = document.getElementById('query-output-secondary');
|
|
481
|
+
if (output)
|
|
482
|
+
output.textContent = `Error (secondary): ${error.message}`;
|
|
483
|
+
log(`Error querying accounts (secondary): ${error.message}`, 'error');
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Query accounts from Dataverse using OData against the secondary connection
|
|
488
|
+
*/
|
|
489
|
+
async function queryODataSecondary() {
|
|
490
|
+
if (!secondaryConnection) {
|
|
491
|
+
await showNotification('No Secondary Connection', 'Please configure a secondary Dataverse connection', 'warning');
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
try {
|
|
495
|
+
const output = document.getElementById('query-odata-secondary-output');
|
|
496
|
+
if (output)
|
|
497
|
+
output.textContent = 'Querying accounts via OData on secondary...\n';
|
|
498
|
+
// Example OData query: top 5 active accounts with basic fields
|
|
499
|
+
const odata = `$select=name,accountid,emailaddress1,telephone1&$filter=statecode eq 0&$orderby=name&$top=5`;
|
|
500
|
+
const result = await dataverse.queryData(odata, 'secondary');
|
|
501
|
+
if (output) {
|
|
502
|
+
output.textContent = `Found ${result.value.length} active account(s) on secondary (OData):\n\n`;
|
|
503
|
+
result.value.forEach((account, index) => {
|
|
504
|
+
output.textContent += `${index + 1}. ${account.name}\n`;
|
|
505
|
+
output.textContent += ` ID: ${account.accountid}\n`;
|
|
506
|
+
if (account.emailaddress1)
|
|
507
|
+
output.textContent += ` Email: ${account.emailaddress1}\n`;
|
|
508
|
+
if (account.telephone1)
|
|
509
|
+
output.textContent += ` Phone: ${account.telephone1}\n`;
|
|
510
|
+
output.textContent += '\n';
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
log(`Queried ${result.value.length} accounts via OData on secondary`, 'success');
|
|
514
|
+
}
|
|
515
|
+
catch (error) {
|
|
516
|
+
const output = document.getElementById('query-odata-secondary-output');
|
|
517
|
+
if (output)
|
|
518
|
+
output.textContent = `Error (OData secondary): ${error.message}`;
|
|
519
|
+
log(`Error OData querying accounts (secondary): ${error.message}`, 'error');
|
|
520
|
+
}
|
|
521
|
+
}
|
|
361
522
|
/**
|
|
362
523
|
* Create a new account
|
|
363
524
|
*/
|
package/dist/index.html
CHANGED
|
@@ -15,12 +15,19 @@
|
|
|
15
15
|
|
|
16
16
|
<!-- Connection Status -->
|
|
17
17
|
<section class="card">
|
|
18
|
-
<h2>🔗 Connection Status</h2>
|
|
18
|
+
<h2>🔗 Primary Connection Status</h2>
|
|
19
19
|
<div id="connection-info" class="info-box">
|
|
20
20
|
<div class="loading">Checking connection...</div>
|
|
21
21
|
</div>
|
|
22
22
|
</section>
|
|
23
23
|
|
|
24
|
+
<section class="card">
|
|
25
|
+
<h2>🔗 Secondary Connection Status</h2>
|
|
26
|
+
<div id="secondary-connection-info" class="info-box">
|
|
27
|
+
<div class="loading">Checking connection...</div>
|
|
28
|
+
</div>
|
|
29
|
+
</section>
|
|
30
|
+
|
|
24
31
|
<!-- ToolBox API Examples -->
|
|
25
32
|
<section class="card">
|
|
26
33
|
<h2>🛠️ ToolBox API Examples</h2>
|
|
@@ -85,8 +92,16 @@
|
|
|
85
92
|
|
|
86
93
|
<div class="example-group">
|
|
87
94
|
<h3>Query Records</h3>
|
|
88
|
-
<
|
|
95
|
+
<div class="button-group">
|
|
96
|
+
<button id="query-accounts-btn" class="btn btn-primary">Query Top 10 Accounts (Primary)</button>
|
|
97
|
+
<button id="query-odata-btn" class="btn btn-primary">Query Active Accounts via OData (Primary)</button>
|
|
98
|
+
<button id="query-accounts-secondary-btn" class="btn">Query Top 10 Accounts (Secondary)</button>
|
|
99
|
+
<button id="query-odata-secondary-btn" class="btn">Query Active Accounts via OData (Secondary)</button>
|
|
100
|
+
</div>
|
|
89
101
|
<div id="query-output" class="output"></div>
|
|
102
|
+
<div id="query-odata-output" class="output"></div>
|
|
103
|
+
<div id="query-output-secondary" class="output"></div>
|
|
104
|
+
<div id="query-odata-secondary-output" class="output"></div>
|
|
90
105
|
</div>
|
|
91
106
|
|
|
92
107
|
<div class="example-group">
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pptb-standard-sample-tool",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pptb-standard-sample-tool",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.8",
|
|
10
10
|
"license": "GPL-3.0",
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@pptb/types": "^1.0.
|
|
12
|
+
"@pptb/types": "^1.0.11",
|
|
13
13
|
"shx": "^0.4.0",
|
|
14
14
|
"typescript": "^5.0.0"
|
|
15
15
|
},
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
"node_modules/@pptb/types": {
|
|
59
|
-
"version": "1.0.
|
|
60
|
-
"resolved": "https://registry.npmjs.org/@pptb/types/-/types-1.0.
|
|
61
|
-
"integrity": "sha512-
|
|
59
|
+
"version": "1.0.11",
|
|
60
|
+
"resolved": "https://registry.npmjs.org/@pptb/types/-/types-1.0.11.tgz",
|
|
61
|
+
"integrity": "sha512-Sgzl4az106T7GmDuobZUy35NccGTXXOGY250AI2rSEz6soYTXdO7azxzdfKyVUwEhoprlfhfdAdhpjU0ruo8rg==",
|
|
62
62
|
"dev": true,
|
|
63
63
|
"license": "GPL-3.0"
|
|
64
64
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pptb-standard-sample-tool",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"displayName": "HTML Sample Tool",
|
|
5
5
|
"description": "A sample Power Platform Tool Box tool built with HTML, CSS, and TypeScript",
|
|
6
6
|
"main": "index.html",
|
|
@@ -14,6 +14,21 @@
|
|
|
14
14
|
"html"
|
|
15
15
|
],
|
|
16
16
|
"license": "GPL-3.0",
|
|
17
|
+
"contributors": [
|
|
18
|
+
{
|
|
19
|
+
"name": "Power Platform Tool Box",
|
|
20
|
+
"url": "https://github.com/PowerPlatform-ToolBox"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"configurations": {
|
|
24
|
+
"repository": "https://github.com/PowerPlatform-ToolBox/html-sample",
|
|
25
|
+
"website": "https://powerplatformtoolbox.com",
|
|
26
|
+
"iconUrl": "https://raw.githubusercontent.com/PowerPlatformToolBox/sample-tools/refs/heads/main/new/html-sample/icon/sample-icon.png",
|
|
27
|
+
"readmeUrl": "https://raw.githubusercontent.com/PowerPlatformToolBox/sample-tools/refs/heads/main/new/html-sample/README.md"
|
|
28
|
+
},
|
|
29
|
+
"features": {
|
|
30
|
+
"multi-connection": true
|
|
31
|
+
},
|
|
17
32
|
"repository": {
|
|
18
33
|
"type": "git",
|
|
19
34
|
"url": "https://github.com/PowerPlatform-ToolBox/desktop-app.git",
|
|
@@ -30,7 +45,7 @@
|
|
|
30
45
|
"watch": "tsc --watch"
|
|
31
46
|
},
|
|
32
47
|
"devDependencies": {
|
|
33
|
-
"@pptb/types": "^1.0.
|
|
48
|
+
"@pptb/types": "^1.0.11",
|
|
34
49
|
"typescript": "^5.0.0",
|
|
35
50
|
"shx": "^0.4.0"
|
|
36
51
|
},
|