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 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
- <button id="query-accounts-btn" class="btn btn-primary">Query Top 10 Accounts</button>
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">
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "pptb-standard-sample-tool",
3
- "version": "1.0.4",
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.4",
9
+ "version": "1.0.8",
10
10
  "license": "GPL-3.0",
11
11
  "devDependencies": {
12
- "@pptb/types": "^1.0.8",
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.8",
60
- "resolved": "https://registry.npmjs.org/@pptb/types/-/types-1.0.8.tgz",
61
- "integrity": "sha512-qGjif4qCFvGsHFB4Ly0xcvfTMkr+IB9WXh2/Zn0/C//orX6IBpnlSXn2D3xUjj69a9hAiqjVMhNJ1fpJJNqO7g==",
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.7",
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.8",
48
+ "@pptb/types": "^1.0.11",
34
49
  "typescript": "^5.0.0",
35
50
  "shx": "^0.4.0"
36
51
  },