@esri/solutions-components 0.5.7 → 0.5.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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