@esri/solutions-components 0.5.7 → 0.5.8

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.
@@ -43,6 +43,25 @@ interface IAttributeTypes {
43
43
  [attributeName: string]: string;
44
44
  }
45
45
 
46
+ interface ILayerRelationshipQuery {
47
+ layer: __esri.FeatureLayer;
48
+ relatedQuery: IRelatedFeaturesQuery;
49
+ }
50
+
51
+ interface ILayerRelationshipQueryHash {
52
+ [relationshipId: string]: ILayerRelationshipQuery;
53
+ }
54
+
55
+ // Class RelationshipQuery doesn't appear to work, and so since
56
+ // https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#queryRelatedFeatures
57
+ // says that the relationshipQuery argument is autocast, we'll set up a variant for the class
58
+ interface IRelatedFeaturesQuery {
59
+ outFields: string[];
60
+ relationshipId: string;
61
+ returnGeometry: boolean;
62
+ objectIds?: number;
63
+ }
64
+
46
65
  const lineSeparatorChar = "|";
47
66
 
48
67
  //#endregion
@@ -278,6 +297,44 @@ export function _createFilename(
278
297
  return title;
279
298
  }
280
299
 
300
+ /**
301
+ * Creates relationship queries for each relationship flag in a popup.
302
+ * @param layer Layer whose popup is to be examined
303
+ * @return Hash of relationships by their id, or null if there are no relationship flags in the
304
+ * popup; each relationship has the properties layer and relatedQuery for the related layer
305
+ * and the query for that layer
306
+ */
307
+ export function _createRelationshipQueries(
308
+ layer: __esri.FeatureLayer,
309
+ ): ILayerRelationshipQueryHash {
310
+
311
+ const relationships: ILayerRelationshipQueryHash = {};
312
+ const relationshipFieldPattern = /\{relationships\/\d+\//gm;
313
+ const relationshipIdPattern = /\d+/;
314
+
315
+ // Test if this popup has any relationship references
316
+ const matches = layer.popupTemplate.content[0].text.match(relationshipFieldPattern);
317
+ if (matches) {
318
+ matches.forEach(match => {
319
+ // Add a query to a found relationship if we don't already have one
320
+ const id = match.match(relationshipIdPattern)[0];
321
+ if (!relationships.hasOwnProperty(id)) {
322
+ const relatedQuery: IRelatedFeaturesQuery = {
323
+ outFields: ['*'],
324
+ relationshipId: id,
325
+ returnGeometry: false
326
+ };
327
+ relationships[id] = {
328
+ layer,
329
+ relatedQuery
330
+ } as ILayerRelationshipQuery;
331
+ }
332
+ });
333
+ }
334
+
335
+ return relationships;
336
+ }
337
+
281
338
  /**
282
339
  * Prepares an attribute's value by applying domain and type information.
283
340
  *
@@ -369,6 +426,7 @@ async function _prepareLabels(
369
426
 
370
427
  // Get the label formatting, if any
371
428
  let labelFormat: string;
429
+ let relationshipQueries: ILayerRelationshipQueryHash = {};
372
430
  let arcadeExecutors: IArcadeExecutors = {};
373
431
  if (layer.popupEnabled) {
374
432
  layer.popupTemplate.fieldInfos.forEach(
@@ -401,6 +459,9 @@ async function _prepareLabels(
401
459
  } else if (formatUsingLayerPopup && layer.popupTemplate?.content[0]?.type === "text") {
402
460
  labelFormat = _convertPopupTextToLabelSpec(layer.popupTemplate.content[0].text);
403
461
 
462
+ // Do we need any relationship queries?
463
+ relationshipQueries = _createRelationshipQueries(layer);
464
+
404
465
  // Do we need any Arcade executors?
405
466
  arcadeExecutors = await _createArcadeExecutors(labelFormat, layer);
406
467
  }
@@ -410,41 +471,100 @@ async function _prepareLabels(
410
471
  let labels: string[][];
411
472
  // eslint-disable-next-line unicorn/prefer-ternary
412
473
  if (labelFormat) {
474
+ console.log("labelFormat", labelFormat);//???
413
475
  const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
414
476
  const attributeRegExp = /\{\w+\}/g;
415
477
 
416
478
  // Find the label fields that we need to replace with values
417
- const arcadeExpressionMatches = labelFormat.match(arcadeExpressionRegExp);
418
- const attributeMatches = labelFormat.match(attributeRegExp);
479
+ const arcadeExpressionMatches = labelFormat.match(arcadeExpressionRegExp) ?? [];
480
+ const attributeMatches = labelFormat.match(attributeRegExp) ?? [];
419
481
 
420
482
  // Convert feature attributes into an array of labels
421
- labels = featureSet.features.map(
422
- feature => {
483
+ const relationshipKeys = Object.keys(relationshipQueries);
484
+ labels = await Promise.all(featureSet.features.map(
485
+ async feature => {
423
486
  let labelPrep = labelFormat;
424
487
 
425
- // Replace Arcade expressions
426
- if (arcadeExpressionMatches) {
427
- arcadeExpressionMatches.forEach(
428
- (match: string) => {
429
- const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
430
- const value = arcadeExecutors[expressionName].execute({"$feature": feature});
431
- labelPrep = labelPrep.replace(match, value);
432
- }
433
- )
434
- }
488
+ // Replace Arcade expressions in this feature
489
+ arcadeExpressionMatches.forEach(
490
+ (match: string) => {
491
+ const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
492
+ const value = arcadeExecutors[expressionName].execute({"$feature": feature});
493
+ labelPrep = labelPrep.replace(match, value);
494
+ }
495
+ )
496
+
497
+ // Replace relationship expressions in this feature
498
+ const relatedFeatureQueries = [] as Promise<__esri.FeatureSet>[];
499
+ const relationshipIds = [] as string[];
500
+ relationshipKeys.forEach(
501
+ (relationshipId) => {
502
+ const relationship = relationshipQueries[relationshipId];
503
+ const objectId = feature.attributes[relationship.layer.objectIdField];
504
+ const relatedQuery = {
505
+ ...relationship.relatedQuery,
506
+ objectIds: [objectId]
507
+ };
508
+ relatedFeatureQueries.push(relationship.layer.queryRelatedFeatures(relatedQuery as any));
509
+ relationshipIds.push(relationshipId);
510
+ }
511
+ );
435
512
 
436
- // Replace non-Arcade fields
437
- if (attributeMatches) {
438
- attributeMatches.forEach(
439
- (match: string) => {
440
- const attributeName = match.substring(1, match.length - 1);
441
- const value = _prepareAttributeValue(feature.attributes[attributeName],
442
- attributeTypes[attributeName], attributeDomains[attributeName],
443
- attributeFormats[attributeName], intl);
444
- labelPrep = labelPrep.replace(match, value);
445
- }
446
- )
447
- }
513
+ // Wait for all of the queries for related records for this label
514
+ const relatedFeatureQueryResults = await Promise.all(relatedFeatureQueries);
515
+ console.log("relatedFeatureQueryResults", relatedFeatureQueryResults);//???
516
+ relatedFeatureQueryResults.forEach(
517
+ (relatedFeatureQueryResult, i) => {
518
+ // We have an object with FeatureSets grouped by source layer or table objectIds
519
+ const relationshipId = relationshipIds[i];
520
+ console.log("relationshipId", relationshipId);//???
521
+ console.log("relatedFeatureQueryResult", relatedFeatureQueryResult);//???
522
+
523
+ // Run through the source layer or table objectIds
524
+ Object.keys(relatedFeatureQueryResult).forEach(
525
+ relatedFeatureSetId => {
526
+ console.log("relatedFeatureSetId", relatedFeatureSetId);//???
527
+ // We have a feature set
528
+ const relatedFeatures = relatedFeatureQueryResult[relatedFeatureSetId].features;
529
+ console.log("relatedFeatures", relatedFeatures);//???
530
+
531
+ // Get the values from each feature and replace them in the label
532
+ relatedFeatures.forEach(
533
+ feature => {
534
+ // Merge the base and related feature attributes and create the label
535
+ // Prefix related feature's attributes with "relationships/<id>/" to match popup
536
+ const rePrefix = "\{relationships/" + relationshipId + "/";
537
+ const reSuffix = "\}";
538
+ console.log("/rePrefix + attributeName + reSuffix/g", rePrefix + "attributeName" + reSuffix);//???
539
+
540
+ const attributes = feature.attributes;
541
+ Object.keys(attributes).forEach(
542
+ attributeName => {
543
+ console.log("/rePrefix + attributeName + reSuffix/g", rePrefix + attributeName + reSuffix);//???
544
+ // Replace the value using the attribute name as a relationship
545
+ const attributeRelationshipRegExp = new RegExp(rePrefix + attributeName + reSuffix, "g");
546
+ labelPrep = labelPrep.replaceAll(attributeRelationshipRegExp, attributes[attributeName]);
547
+ }
548
+ );
549
+ }
550
+ );
551
+ }
552
+ );
553
+ }
554
+ );
555
+
556
+ // Replace non-Arcade fields in this feature
557
+ attributeMatches.forEach(
558
+ (match: string) => {
559
+ const attributeName = match.substring(1, match.length - 1);
560
+
561
+ const value = _prepareAttributeValue(feature.attributes[attributeName],
562
+ attributeTypes[attributeName], attributeDomains[attributeName],
563
+ attributeFormats[attributeName], intl);
564
+ labelPrep = labelPrep.replace(match, value);
565
+
566
+ }
567
+ )
448
568
 
449
569
  // Split label into lines
450
570
  let label = labelPrep.split(lineSeparatorChar);
@@ -454,7 +574,7 @@ async function _prepareLabels(
454
574
 
455
575
  return label;
456
576
  }
457
- );
577
+ ));
458
578
 
459
579
  } else {
460
580
  // Export all attributes
@@ -2425,6 +2425,38 @@ function _createFilename(selectionSetNames) {
2425
2425
  const title = selectionSetNames.length > 0 ? selectionSetNames.join(", ") : "download";
2426
2426
  return title;
2427
2427
  }
2428
+ /**
2429
+ * Creates relationship queries for each relationship flag in a popup.
2430
+ * @param layer Layer whose popup is to be examined
2431
+ * @return Hash of relationships by their id, or null if there are no relationship flags in the
2432
+ * popup; each relationship has the properties layer and relatedQuery for the related layer
2433
+ * and the query for that layer
2434
+ */
2435
+ function _createRelationshipQueries(layer) {
2436
+ const relationships = {};
2437
+ const relationshipFieldPattern = /\{relationships\/\d+\//gm;
2438
+ const relationshipIdPattern = /\d+/;
2439
+ // Test if this popup has any relationship references
2440
+ const matches = layer.popupTemplate.content[0].text.match(relationshipFieldPattern);
2441
+ if (matches) {
2442
+ matches.forEach(match => {
2443
+ // Add a query to a found relationship if we don't already have one
2444
+ const id = match.match(relationshipIdPattern)[0];
2445
+ if (!relationships.hasOwnProperty(id)) {
2446
+ const relatedQuery = {
2447
+ outFields: ['*'],
2448
+ relationshipId: id,
2449
+ returnGeometry: false
2450
+ };
2451
+ relationships[id] = {
2452
+ layer,
2453
+ relatedQuery
2454
+ };
2455
+ }
2456
+ });
2457
+ }
2458
+ return relationships;
2459
+ }
2428
2460
  /**
2429
2461
  * Prepares an attribute's value by applying domain and type information.
2430
2462
  *
@@ -2485,7 +2517,7 @@ function _prepareAttributeValue(attributeValue, attributeType, attributeDomain,
2485
2517
  * @returns Promise resolving when function is done
2486
2518
  */
2487
2519
  async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLayerPopup = true, includeHeaderNames = false) {
2488
- var _a, _b, _c, _d;
2520
+ var _a, _b, _c, _d, _e, _f;
2489
2521
  const [intl] = await loadModules(["esri/intl"]);
2490
2522
  // Get the features to export
2491
2523
  const featureSet = await queryFeaturesByID(ids, layer);
@@ -2499,6 +2531,7 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
2499
2531
  const attributeFormats = {};
2500
2532
  // Get the label formatting, if any
2501
2533
  let labelFormat;
2534
+ let relationshipQueries = {};
2502
2535
  let arcadeExecutors = {};
2503
2536
  if (layer.popupEnabled) {
2504
2537
  layer.popupTemplate.fieldInfos.forEach(
@@ -2527,6 +2560,8 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
2527
2560
  }
2528
2561
  else if (formatUsingLayerPopup && ((_d = (_c = layer.popupTemplate) === null || _c === void 0 ? void 0 : _c.content[0]) === null || _d === void 0 ? void 0 : _d.type) === "text") {
2529
2562
  labelFormat = _convertPopupTextToLabelSpec(layer.popupTemplate.content[0].text);
2563
+ // Do we need any relationship queries?
2564
+ relationshipQueries = _createRelationshipQueries(layer);
2530
2565
  // Do we need any Arcade executors?
2531
2566
  arcadeExecutors = await _createArcadeExecutors(labelFormat, layer);
2532
2567
  }
@@ -2535,36 +2570,75 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
2535
2570
  let labels;
2536
2571
  // eslint-disable-next-line unicorn/prefer-ternary
2537
2572
  if (labelFormat) {
2573
+ console.log("labelFormat", labelFormat); //???
2538
2574
  const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
2539
2575
  const attributeRegExp = /\{\w+\}/g;
2540
2576
  // Find the label fields that we need to replace with values
2541
- const arcadeExpressionMatches = labelFormat.match(arcadeExpressionRegExp);
2542
- const attributeMatches = labelFormat.match(attributeRegExp);
2577
+ const arcadeExpressionMatches = (_e = labelFormat.match(arcadeExpressionRegExp)) !== null && _e !== void 0 ? _e : [];
2578
+ const attributeMatches = (_f = labelFormat.match(attributeRegExp)) !== null && _f !== void 0 ? _f : [];
2543
2579
  // Convert feature attributes into an array of labels
2544
- labels = featureSet.features.map(feature => {
2580
+ const relationshipKeys = Object.keys(relationshipQueries);
2581
+ labels = await Promise.all(featureSet.features.map(async (feature) => {
2545
2582
  let labelPrep = labelFormat;
2546
- // Replace Arcade expressions
2547
- if (arcadeExpressionMatches) {
2548
- arcadeExpressionMatches.forEach((match) => {
2549
- const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
2550
- const value = arcadeExecutors[expressionName].execute({ "$feature": feature });
2551
- labelPrep = labelPrep.replace(match, value);
2552
- });
2553
- }
2554
- // Replace non-Arcade fields
2555
- if (attributeMatches) {
2556
- attributeMatches.forEach((match) => {
2557
- const attributeName = match.substring(1, match.length - 1);
2558
- const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], attributeFormats[attributeName], intl);
2559
- labelPrep = labelPrep.replace(match, value);
2583
+ // Replace Arcade expressions in this feature
2584
+ arcadeExpressionMatches.forEach((match) => {
2585
+ const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
2586
+ const value = arcadeExecutors[expressionName].execute({ "$feature": feature });
2587
+ labelPrep = labelPrep.replace(match, value);
2588
+ });
2589
+ // Replace relationship expressions in this feature
2590
+ const relatedFeatureQueries = [];
2591
+ const relationshipIds = [];
2592
+ relationshipKeys.forEach((relationshipId) => {
2593
+ const relationship = relationshipQueries[relationshipId];
2594
+ const objectId = feature.attributes[relationship.layer.objectIdField];
2595
+ const relatedQuery = Object.assign(Object.assign({}, relationship.relatedQuery), { objectIds: [objectId] });
2596
+ relatedFeatureQueries.push(relationship.layer.queryRelatedFeatures(relatedQuery));
2597
+ relationshipIds.push(relationshipId);
2598
+ });
2599
+ // Wait for all of the queries for related records for this label
2600
+ const relatedFeatureQueryResults = await Promise.all(relatedFeatureQueries);
2601
+ console.log("relatedFeatureQueryResults", relatedFeatureQueryResults); //???
2602
+ relatedFeatureQueryResults.forEach((relatedFeatureQueryResult, i) => {
2603
+ // We have an object with FeatureSets grouped by source layer or table objectIds
2604
+ const relationshipId = relationshipIds[i];
2605
+ console.log("relationshipId", relationshipId); //???
2606
+ console.log("relatedFeatureQueryResult", relatedFeatureQueryResult); //???
2607
+ // Run through the source layer or table objectIds
2608
+ Object.keys(relatedFeatureQueryResult).forEach(relatedFeatureSetId => {
2609
+ console.log("relatedFeatureSetId", relatedFeatureSetId); //???
2610
+ // We have a feature set
2611
+ const relatedFeatures = relatedFeatureQueryResult[relatedFeatureSetId].features;
2612
+ console.log("relatedFeatures", relatedFeatures); //???
2613
+ // Get the values from each feature and replace them in the label
2614
+ relatedFeatures.forEach(feature => {
2615
+ // Merge the base and related feature attributes and create the label
2616
+ // Prefix related feature's attributes with "relationships/<id>/" to match popup
2617
+ const rePrefix = "\{relationships/" + relationshipId + "/";
2618
+ const reSuffix = "\}";
2619
+ console.log("/rePrefix + attributeName + reSuffix/g", rePrefix + "attributeName" + reSuffix); //???
2620
+ const attributes = feature.attributes;
2621
+ Object.keys(attributes).forEach(attributeName => {
2622
+ console.log("/rePrefix + attributeName + reSuffix/g", rePrefix + attributeName + reSuffix); //???
2623
+ // Replace the value using the attribute name as a relationship
2624
+ const attributeRelationshipRegExp = new RegExp(rePrefix + attributeName + reSuffix, "g");
2625
+ labelPrep = labelPrep.replaceAll(attributeRelationshipRegExp, attributes[attributeName]);
2626
+ });
2627
+ });
2560
2628
  });
2561
- }
2629
+ });
2630
+ // Replace non-Arcade fields in this feature
2631
+ attributeMatches.forEach((match) => {
2632
+ const attributeName = match.substring(1, match.length - 1);
2633
+ const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], attributeFormats[attributeName], intl);
2634
+ labelPrep = labelPrep.replace(match, value);
2635
+ });
2562
2636
  // Split label into lines
2563
2637
  let label = labelPrep.split(lineSeparatorChar);
2564
2638
  // Trim lines
2565
2639
  label = label.map(line => line.trim());
2566
2640
  return label;
2567
- });
2641
+ }));
2568
2642
  }
2569
2643
  else {
2570
2644
  // Export all attributes
@@ -20,7 +20,7 @@ import { g as goToSelection, h as highlightFeatures, q as queryObjectIds, a as g
20
20
  import { c as EWorkflowType, e as ESelectionMode, f as EDrawMode } from './interfaces-523c6558.js';
21
21
  import { s as state } from './publicNotificationStore-c36d95bf.js';
22
22
  import { a as getComponentClosestLanguage, g as getLocaleComponentStrings } from './locale-54cac39a.js';
23
- import { d as downloadCSV, a as downloadPDF } from './downloadUtils-046ce0aa.js';
23
+ import { d as downloadCSV, a as downloadPDF } from './downloadUtils-b9785635.js';
24
24
  import './guid-2069664e.js';
25
25
  import './key-218d8d4d.js';
26
26
  import './index-4c4a4f3d.js';
@@ -1505,7 +1505,7 @@ function(t){var e=function(t){for(var e=t.length,r=new Uint8Array(e),n=0;n<e;n++
1505
1505
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1506
1506
  * ====================================================================
1507
1507
  */
1508
- function(t){function e(){return (n.canvg?Promise.resolve(n.canvg):import('./index.es-3fd0e8f6.js')).catch((function(t){return Promise.reject(new Error("Could not load canvg: "+t))})).then((function(t){return t.default?t.default:t}))}E.API.addSvgAsImage=function(t,r,n,i,o,s,c,u){if(isNaN(r)||isNaN(n))throw a.error("jsPDF.addSvgAsImage: Invalid coordinates",arguments),new Error("Invalid coordinates passed to jsPDF.addSvgAsImage");if(isNaN(i)||isNaN(o))throw a.error("jsPDF.addSvgAsImage: Invalid measurements",arguments),new Error("Invalid measurements (width and/or height) passed to jsPDF.addSvgAsImage");var h=document.createElement("canvas");h.width=i,h.height=o;var l=h.getContext("2d");l.fillStyle="#fff",l.fillRect(0,0,h.width,h.height);var f={ignoreMouse:!0,ignoreAnimation:!0,ignoreDimensions:!0},d=this;return e().then((function(e){return e.fromString(l,t,f)}),(function(){return Promise.reject(new Error("Could not load canvg."))})).then((function(t){return t.render(f)})).then((function(){d.addImage(h.toDataURL("image/jpeg",1),r,n,i,o,c,u);}))};}(),E.API.putTotalPages=function(t){var e,r=0;parseInt(this.internal.getFont().id.substr(1),10)<15?(e=new RegExp(t,"g"),r=this.internal.getNumberOfPages()):(e=new RegExp(this.pdfEscape16(t,this.internal.getFont()),"g"),r=this.pdfEscape16(this.internal.getNumberOfPages()+"",this.internal.getFont()));for(var n=1;n<=this.internal.getNumberOfPages();n++)for(var i=0;i<this.internal.pages[n].length;i++)this.internal.pages[n][i]=this.internal.pages[n][i].replace(e,r);return this},E.API.viewerPreferences=function(e,r){var n;e=e||{},r=r||!1;var i,a,o,s={HideToolbar:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},HideMenubar:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},HideWindowUI:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},FitWindow:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},CenterWindow:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},DisplayDocTitle:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.4},NonFullScreenPageMode:{defaultValue:"UseNone",value:"UseNone",type:"name",explicitSet:!1,valueSet:["UseNone","UseOutlines","UseThumbs","UseOC"],pdfVersion:1.3},Direction:{defaultValue:"L2R",value:"L2R",type:"name",explicitSet:!1,valueSet:["L2R","R2L"],pdfVersion:1.3},ViewArea:{defaultValue:"CropBox",value:"CropBox",type:"name",explicitSet:!1,valueSet:["MediaBox","CropBox","TrimBox","BleedBox","ArtBox"],pdfVersion:1.4},ViewClip:{defaultValue:"CropBox",value:"CropBox",type:"name",explicitSet:!1,valueSet:["MediaBox","CropBox","TrimBox","BleedBox","ArtBox"],pdfVersion:1.4},PrintArea:{defaultValue:"CropBox",value:"CropBox",type:"name",explicitSet:!1,valueSet:["MediaBox","CropBox","TrimBox","BleedBox","ArtBox"],pdfVersion:1.4},PrintClip:{defaultValue:"CropBox",value:"CropBox",type:"name",explicitSet:!1,valueSet:["MediaBox","CropBox","TrimBox","BleedBox","ArtBox"],pdfVersion:1.4},PrintScaling:{defaultValue:"AppDefault",value:"AppDefault",type:"name",explicitSet:!1,valueSet:["AppDefault","None"],pdfVersion:1.6},Duplex:{defaultValue:"",value:"none",type:"name",explicitSet:!1,valueSet:["Simplex","DuplexFlipShortEdge","DuplexFlipLongEdge","none"],pdfVersion:1.7},PickTrayByPDFSize:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.7},PrintPageRange:{defaultValue:"",value:"",type:"array",explicitSet:!1,valueSet:null,pdfVersion:1.7},NumCopies:{defaultValue:1,value:1,type:"integer",explicitSet:!1,valueSet:null,pdfVersion:1.7}},c=Object.keys(s),u=[],h=0,l=0,f=0;function d(t,e){var r,n=!1;for(r=0;r<t.length;r+=1)t[r]===e&&(n=!0);return n}if(void 0===this.internal.viewerpreferences&&(this.internal.viewerpreferences={},this.internal.viewerpreferences.configuration=JSON.parse(JSON.stringify(s)),this.internal.viewerpreferences.isSubscribed=!1),n=this.internal.viewerpreferences.configuration,"reset"===e||!0===r){var p=c.length;for(f=0;f<p;f+=1)n[c[f]].value=n[c[f]].defaultValue,n[c[f]].explicitSet=!1;}if("object"===t(e))for(a in e)if(o=e[a],d(c,a)&&void 0!==o){if("boolean"===n[a].type&&"boolean"==typeof o)n[a].value=o;else if("name"===n[a].type&&d(n[a].valueSet,o))n[a].value=o;else if("integer"===n[a].type&&Number.isInteger(o))n[a].value=o;else if("array"===n[a].type){for(h=0;h<o.length;h+=1)if(i=!0,1===o[h].length&&"number"==typeof o[h][0])u.push(String(o[h]-1));else if(o[h].length>1){for(l=0;l<o[h].length;l+=1)"number"!=typeof o[h][l]&&(i=!1);!0===i&&u.push([o[h][0]-1,o[h][1]-1].join(" "));}n[a].value="["+u.join(" ")+"]";}else n[a].value=n[a].defaultValue;n[a].explicitSet=!0;}return !1===this.internal.viewerpreferences.isSubscribed&&(this.internal.events.subscribe("putCatalog",(function(){var t,e=[];for(t in n)!0===n[t].explicitSet&&("name"===n[t].type?e.push("/"+t+" /"+n[t].value):e.push("/"+t+" "+n[t].value));0!==e.length&&this.internal.write("/ViewerPreferences\n<<\n"+e.join("\n")+"\n>>");})),this.internal.viewerpreferences.isSubscribed=!0),this.internal.viewerpreferences.configuration=n,this},
1508
+ function(t){function e(){return (n.canvg?Promise.resolve(n.canvg):import('./index.es-70994c40.js')).catch((function(t){return Promise.reject(new Error("Could not load canvg: "+t))})).then((function(t){return t.default?t.default:t}))}E.API.addSvgAsImage=function(t,r,n,i,o,s,c,u){if(isNaN(r)||isNaN(n))throw a.error("jsPDF.addSvgAsImage: Invalid coordinates",arguments),new Error("Invalid coordinates passed to jsPDF.addSvgAsImage");if(isNaN(i)||isNaN(o))throw a.error("jsPDF.addSvgAsImage: Invalid measurements",arguments),new Error("Invalid measurements (width and/or height) passed to jsPDF.addSvgAsImage");var h=document.createElement("canvas");h.width=i,h.height=o;var l=h.getContext("2d");l.fillStyle="#fff",l.fillRect(0,0,h.width,h.height);var f={ignoreMouse:!0,ignoreAnimation:!0,ignoreDimensions:!0},d=this;return e().then((function(e){return e.fromString(l,t,f)}),(function(){return Promise.reject(new Error("Could not load canvg."))})).then((function(t){return t.render(f)})).then((function(){d.addImage(h.toDataURL("image/jpeg",1),r,n,i,o,c,u);}))};}(),E.API.putTotalPages=function(t){var e,r=0;parseInt(this.internal.getFont().id.substr(1),10)<15?(e=new RegExp(t,"g"),r=this.internal.getNumberOfPages()):(e=new RegExp(this.pdfEscape16(t,this.internal.getFont()),"g"),r=this.pdfEscape16(this.internal.getNumberOfPages()+"",this.internal.getFont()));for(var n=1;n<=this.internal.getNumberOfPages();n++)for(var i=0;i<this.internal.pages[n].length;i++)this.internal.pages[n][i]=this.internal.pages[n][i].replace(e,r);return this},E.API.viewerPreferences=function(e,r){var n;e=e||{},r=r||!1;var i,a,o,s={HideToolbar:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},HideMenubar:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},HideWindowUI:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},FitWindow:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},CenterWindow:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.3},DisplayDocTitle:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.4},NonFullScreenPageMode:{defaultValue:"UseNone",value:"UseNone",type:"name",explicitSet:!1,valueSet:["UseNone","UseOutlines","UseThumbs","UseOC"],pdfVersion:1.3},Direction:{defaultValue:"L2R",value:"L2R",type:"name",explicitSet:!1,valueSet:["L2R","R2L"],pdfVersion:1.3},ViewArea:{defaultValue:"CropBox",value:"CropBox",type:"name",explicitSet:!1,valueSet:["MediaBox","CropBox","TrimBox","BleedBox","ArtBox"],pdfVersion:1.4},ViewClip:{defaultValue:"CropBox",value:"CropBox",type:"name",explicitSet:!1,valueSet:["MediaBox","CropBox","TrimBox","BleedBox","ArtBox"],pdfVersion:1.4},PrintArea:{defaultValue:"CropBox",value:"CropBox",type:"name",explicitSet:!1,valueSet:["MediaBox","CropBox","TrimBox","BleedBox","ArtBox"],pdfVersion:1.4},PrintClip:{defaultValue:"CropBox",value:"CropBox",type:"name",explicitSet:!1,valueSet:["MediaBox","CropBox","TrimBox","BleedBox","ArtBox"],pdfVersion:1.4},PrintScaling:{defaultValue:"AppDefault",value:"AppDefault",type:"name",explicitSet:!1,valueSet:["AppDefault","None"],pdfVersion:1.6},Duplex:{defaultValue:"",value:"none",type:"name",explicitSet:!1,valueSet:["Simplex","DuplexFlipShortEdge","DuplexFlipLongEdge","none"],pdfVersion:1.7},PickTrayByPDFSize:{defaultValue:!1,value:!1,type:"boolean",explicitSet:!1,valueSet:[!0,!1],pdfVersion:1.7},PrintPageRange:{defaultValue:"",value:"",type:"array",explicitSet:!1,valueSet:null,pdfVersion:1.7},NumCopies:{defaultValue:1,value:1,type:"integer",explicitSet:!1,valueSet:null,pdfVersion:1.7}},c=Object.keys(s),u=[],h=0,l=0,f=0;function d(t,e){var r,n=!1;for(r=0;r<t.length;r+=1)t[r]===e&&(n=!0);return n}if(void 0===this.internal.viewerpreferences&&(this.internal.viewerpreferences={},this.internal.viewerpreferences.configuration=JSON.parse(JSON.stringify(s)),this.internal.viewerpreferences.isSubscribed=!1),n=this.internal.viewerpreferences.configuration,"reset"===e||!0===r){var p=c.length;for(f=0;f<p;f+=1)n[c[f]].value=n[c[f]].defaultValue,n[c[f]].explicitSet=!1;}if("object"===t(e))for(a in e)if(o=e[a],d(c,a)&&void 0!==o){if("boolean"===n[a].type&&"boolean"==typeof o)n[a].value=o;else if("name"===n[a].type&&d(n[a].valueSet,o))n[a].value=o;else if("integer"===n[a].type&&Number.isInteger(o))n[a].value=o;else if("array"===n[a].type){for(h=0;h<o.length;h+=1)if(i=!0,1===o[h].length&&"number"==typeof o[h][0])u.push(String(o[h]-1));else if(o[h].length>1){for(l=0;l<o[h].length;l+=1)"number"!=typeof o[h][l]&&(i=!1);!0===i&&u.push([o[h][0]-1,o[h][1]-1].join(" "));}n[a].value="["+u.join(" ")+"]";}else n[a].value=n[a].defaultValue;n[a].explicitSet=!0;}return !1===this.internal.viewerpreferences.isSubscribed&&(this.internal.events.subscribe("putCatalog",(function(){var t,e=[];for(t in n)!0===n[t].explicitSet&&("name"===n[t].type?e.push("/"+t+" /"+n[t].value):e.push("/"+t+" "+n[t].value));0!==e.length&&this.internal.write("/ViewerPreferences\n<<\n"+e.join("\n")+"\n>>");})),this.internal.viewerpreferences.isSubscribed=!0),this.internal.viewerpreferences.configuration=n,this},
1509
1509
  /** ====================================================================
1510
1510
  * @license
1511
1511
  * jsPDF XMP metadata plugin
@@ -2425,6 +2425,38 @@ function _createFilename(selectionSetNames) {
2425
2425
  const title = selectionSetNames.length > 0 ? selectionSetNames.join(", ") : "download";
2426
2426
  return title;
2427
2427
  }
2428
+ /**
2429
+ * Creates relationship queries for each relationship flag in a popup.
2430
+ * @param layer Layer whose popup is to be examined
2431
+ * @return Hash of relationships by their id, or null if there are no relationship flags in the
2432
+ * popup; each relationship has the properties layer and relatedQuery for the related layer
2433
+ * and the query for that layer
2434
+ */
2435
+ function _createRelationshipQueries(layer) {
2436
+ const relationships = {};
2437
+ const relationshipFieldPattern = /\{relationships\/\d+\//gm;
2438
+ const relationshipIdPattern = /\d+/;
2439
+ // Test if this popup has any relationship references
2440
+ const matches = layer.popupTemplate.content[0].text.match(relationshipFieldPattern);
2441
+ if (matches) {
2442
+ matches.forEach(match => {
2443
+ // Add a query to a found relationship if we don't already have one
2444
+ const id = match.match(relationshipIdPattern)[0];
2445
+ if (!relationships.hasOwnProperty(id)) {
2446
+ const relatedQuery = {
2447
+ outFields: ['*'],
2448
+ relationshipId: id,
2449
+ returnGeometry: false
2450
+ };
2451
+ relationships[id] = {
2452
+ layer,
2453
+ relatedQuery
2454
+ };
2455
+ }
2456
+ });
2457
+ }
2458
+ return relationships;
2459
+ }
2428
2460
  /**
2429
2461
  * Prepares an attribute's value by applying domain and type information.
2430
2462
  *
@@ -2485,7 +2517,7 @@ function _prepareAttributeValue(attributeValue, attributeType, attributeDomain,
2485
2517
  * @returns Promise resolving when function is done
2486
2518
  */
2487
2519
  async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLayerPopup = true, includeHeaderNames = false) {
2488
- var _a, _b, _c, _d;
2520
+ var _a, _b, _c, _d, _e, _f;
2489
2521
  const [intl] = await loadModules(["esri/intl"]);
2490
2522
  // Get the features to export
2491
2523
  const featureSet = await queryFeaturesByID(ids, layer);
@@ -2499,6 +2531,7 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
2499
2531
  const attributeFormats = {};
2500
2532
  // Get the label formatting, if any
2501
2533
  let labelFormat;
2534
+ let relationshipQueries = {};
2502
2535
  let arcadeExecutors = {};
2503
2536
  if (layer.popupEnabled) {
2504
2537
  layer.popupTemplate.fieldInfos.forEach(
@@ -2527,6 +2560,8 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
2527
2560
  }
2528
2561
  else if (formatUsingLayerPopup && ((_d = (_c = layer.popupTemplate) === null || _c === void 0 ? void 0 : _c.content[0]) === null || _d === void 0 ? void 0 : _d.type) === "text") {
2529
2562
  labelFormat = _convertPopupTextToLabelSpec(layer.popupTemplate.content[0].text);
2563
+ // Do we need any relationship queries?
2564
+ relationshipQueries = _createRelationshipQueries(layer);
2530
2565
  // Do we need any Arcade executors?
2531
2566
  arcadeExecutors = await _createArcadeExecutors(labelFormat, layer);
2532
2567
  }
@@ -2535,36 +2570,75 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
2535
2570
  let labels;
2536
2571
  // eslint-disable-next-line unicorn/prefer-ternary
2537
2572
  if (labelFormat) {
2573
+ console.log("labelFormat", labelFormat); //???
2538
2574
  const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
2539
2575
  const attributeRegExp = /\{\w+\}/g;
2540
2576
  // Find the label fields that we need to replace with values
2541
- const arcadeExpressionMatches = labelFormat.match(arcadeExpressionRegExp);
2542
- const attributeMatches = labelFormat.match(attributeRegExp);
2577
+ const arcadeExpressionMatches = (_e = labelFormat.match(arcadeExpressionRegExp)) !== null && _e !== void 0 ? _e : [];
2578
+ const attributeMatches = (_f = labelFormat.match(attributeRegExp)) !== null && _f !== void 0 ? _f : [];
2543
2579
  // Convert feature attributes into an array of labels
2544
- labels = featureSet.features.map(feature => {
2580
+ const relationshipKeys = Object.keys(relationshipQueries);
2581
+ labels = await Promise.all(featureSet.features.map(async (feature) => {
2545
2582
  let labelPrep = labelFormat;
2546
- // Replace Arcade expressions
2547
- if (arcadeExpressionMatches) {
2548
- arcadeExpressionMatches.forEach((match) => {
2549
- const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
2550
- const value = arcadeExecutors[expressionName].execute({ "$feature": feature });
2551
- labelPrep = labelPrep.replace(match, value);
2552
- });
2553
- }
2554
- // Replace non-Arcade fields
2555
- if (attributeMatches) {
2556
- attributeMatches.forEach((match) => {
2557
- const attributeName = match.substring(1, match.length - 1);
2558
- const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], attributeFormats[attributeName], intl);
2559
- labelPrep = labelPrep.replace(match, value);
2583
+ // Replace Arcade expressions in this feature
2584
+ arcadeExpressionMatches.forEach((match) => {
2585
+ const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
2586
+ const value = arcadeExecutors[expressionName].execute({ "$feature": feature });
2587
+ labelPrep = labelPrep.replace(match, value);
2588
+ });
2589
+ // Replace relationship expressions in this feature
2590
+ const relatedFeatureQueries = [];
2591
+ const relationshipIds = [];
2592
+ relationshipKeys.forEach((relationshipId) => {
2593
+ const relationship = relationshipQueries[relationshipId];
2594
+ const objectId = feature.attributes[relationship.layer.objectIdField];
2595
+ const relatedQuery = Object.assign(Object.assign({}, relationship.relatedQuery), { objectIds: [objectId] });
2596
+ relatedFeatureQueries.push(relationship.layer.queryRelatedFeatures(relatedQuery));
2597
+ relationshipIds.push(relationshipId);
2598
+ });
2599
+ // Wait for all of the queries for related records for this label
2600
+ const relatedFeatureQueryResults = await Promise.all(relatedFeatureQueries);
2601
+ console.log("relatedFeatureQueryResults", relatedFeatureQueryResults); //???
2602
+ relatedFeatureQueryResults.forEach((relatedFeatureQueryResult, i) => {
2603
+ // We have an object with FeatureSets grouped by source layer or table objectIds
2604
+ const relationshipId = relationshipIds[i];
2605
+ console.log("relationshipId", relationshipId); //???
2606
+ console.log("relatedFeatureQueryResult", relatedFeatureQueryResult); //???
2607
+ // Run through the source layer or table objectIds
2608
+ Object.keys(relatedFeatureQueryResult).forEach(relatedFeatureSetId => {
2609
+ console.log("relatedFeatureSetId", relatedFeatureSetId); //???
2610
+ // We have a feature set
2611
+ const relatedFeatures = relatedFeatureQueryResult[relatedFeatureSetId].features;
2612
+ console.log("relatedFeatures", relatedFeatures); //???
2613
+ // Get the values from each feature and replace them in the label
2614
+ relatedFeatures.forEach(feature => {
2615
+ // Merge the base and related feature attributes and create the label
2616
+ // Prefix related feature's attributes with "relationships/<id>/" to match popup
2617
+ const rePrefix = "\{relationships/" + relationshipId + "/";
2618
+ const reSuffix = "\}";
2619
+ console.log("/rePrefix + attributeName + reSuffix/g", rePrefix + "attributeName" + reSuffix); //???
2620
+ const attributes = feature.attributes;
2621
+ Object.keys(attributes).forEach(attributeName => {
2622
+ console.log("/rePrefix + attributeName + reSuffix/g", rePrefix + attributeName + reSuffix); //???
2623
+ // Replace the value using the attribute name as a relationship
2624
+ const attributeRelationshipRegExp = new RegExp(rePrefix + attributeName + reSuffix, "g");
2625
+ labelPrep = labelPrep.replaceAll(attributeRelationshipRegExp, attributes[attributeName]);
2626
+ });
2627
+ });
2560
2628
  });
2561
- }
2629
+ });
2630
+ // Replace non-Arcade fields in this feature
2631
+ attributeMatches.forEach((match) => {
2632
+ const attributeName = match.substring(1, match.length - 1);
2633
+ const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], attributeFormats[attributeName], intl);
2634
+ labelPrep = labelPrep.replace(match, value);
2635
+ });
2562
2636
  // Split label into lines
2563
2637
  let label = labelPrep.split(lineSeparatorChar);
2564
2638
  // Trim lines
2565
2639
  label = label.map(line => line.trim());
2566
2640
  return label;
2567
- });
2641
+ }));
2568
2642
  }
2569
2643
  else {
2570
2644
  // Export all attributes
@@ -4,7 +4,7 @@
4
4
  * http://www.apache.org/licenses/LICENSE-2.0
5
5
  */
6
6
  import { a as commonjsGlobal, c as createCommonjsModule, g as getDefaultExportFromCjs } from './_commonjsHelpers-d5f9d613.js';
7
- import { _ as _typeof_1 } from './downloadUtils-046ce0aa.js';
7
+ import { _ as _typeof_1 } from './downloadUtils-b9785635.js';
8
8
  import './index-d298aca9.js';
9
9
  import './loadModules-cd3569de.js';
10
10
  import './locale-54cac39a.js';
@@ -7,7 +7,7 @@ import { r as registerInstance, h, H as Host, g as getElement, c as createEvent
7
7
  import { l as loadModules } from './loadModules-cd3569de.js';
8
8
  import { g as getLocaleComponentStrings } from './locale-54cac39a.js';
9
9
  import { i as getMapLayerIds, b as getMapLayerView, g as goToSelection, j as queryAllFeatures } from './mapViewUtils-ebbd4733.js';
10
- import { d as downloadCSV } from './downloadUtils-046ce0aa.js';
10
+ import { d as downloadCSV } from './downloadUtils-b9785635.js';
11
11
  import { g as EExpandType } from './interfaces-523c6558.js';
12
12
  import './_commonjsHelpers-d5f9d613.js';
13
13