@esri/solutions-components 0.5.6 → 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.
- package/dist/assets/t9n/map-select-tools/resources.json +2 -2
- package/dist/assets/t9n/map-select-tools/resources_en.json +2 -2
- package/dist/assets/t9n/public-notification/resources.json +1 -1
- package/dist/assets/t9n/public-notification/resources_en.json +1 -1
- package/dist/cjs/calcite-input-text_5.cjs.entry.js +4 -4
- package/dist/cjs/calcite-shell-panel_14.cjs.entry.js +1 -1
- package/dist/cjs/{downloadUtils-06876768.js → downloadUtils-8d66f03e.js} +95 -21
- package/dist/cjs/{index.es-d07646b4.js → index.es-4f5dfcc6.js} +1 -1
- package/dist/cjs/layer-table_2.cjs.entry.js +1 -1
- package/dist/cjs/public-notification.cjs.entry.js +12 -1
- package/dist/cjs/solution-configuration.cjs.entry.js +1 -1
- package/dist/cjs/solution-contents_3.cjs.entry.js +1 -1
- package/dist/cjs/{solution-store-70002b57.js → solution-store-ca4639d5.js} +3 -3
- package/dist/collection/components/map-select-tools/map-select-tools.css +7 -2
- package/dist/collection/components/map-select-tools/map-select-tools.js +2 -2
- package/dist/collection/components/public-notification/public-notification.js +12 -1
- package/dist/collection/components/refine-selection/refine-selection.css +85 -85
- package/dist/collection/utils/downloadUtils.js +94 -20
- package/dist/collection/utils/downloadUtils.ts +147 -27
- package/dist/components/downloadUtils.js +94 -20
- package/dist/components/map-select-tools2.js +14 -14
- package/dist/components/public-notification.js +12 -1
- package/dist/components/solution-store.js +3 -3
- package/dist/esm/calcite-input-text_5.entry.js +4 -4
- package/dist/esm/calcite-shell-panel_14.entry.js +1 -1
- package/dist/esm/{downloadUtils-046ce0aa.js → downloadUtils-b9785635.js} +95 -21
- package/dist/esm/{index.es-3fd0e8f6.js → index.es-70994c40.js} +1 -1
- package/dist/esm/layer-table_2.entry.js +1 -1
- package/dist/esm/public-notification.entry.js +12 -1
- package/dist/esm/solution-configuration.entry.js +1 -1
- package/dist/esm/solution-contents_3.entry.js +1 -1
- package/dist/esm/{solution-store-5d068b07.js → solution-store-70f874f8.js} +3 -3
- package/dist/solutions-components/{p-1850a763.entry.js → p-10336554.entry.js} +1 -1
- package/dist/solutions-components/{p-41802f6b.entry.js → p-16dfb254.entry.js} +1 -1
- package/dist/solutions-components/{p-99aec087.js → p-5d5e10d4.js} +1 -1
- package/dist/solutions-components/{p-4769a2a5.entry.js → p-5ed755a2.entry.js} +1 -1
- package/dist/solutions-components/{p-826a814d.js → p-78719506.js} +2 -2
- package/dist/solutions-components/{p-9f620303.entry.js → p-b4b19fd3.entry.js} +1 -1
- package/dist/solutions-components/{p-2e0db581.js → p-be943993.js} +11 -11
- package/dist/solutions-components/{p-7e409786.entry.js → p-c3e3d0bb.entry.js} +3 -3
- package/dist/solutions-components/p-f66a7ea7.entry.js +6 -0
- package/dist/solutions-components/solutions-components.esm.js +1 -1
- package/dist/solutions-components/utils/downloadUtils.ts +147 -27
- package/dist/solutions-components_commit.txt +8 -0
- package/dist/types/utils/downloadUtils.d.ts +21 -0
- package/package.json +1 -1
- package/dist/solutions-components/p-6e87198f.entry.js +0 -6
@@ -196,6 +196,38 @@ export function _createFilename(selectionSetNames) {
|
|
196
196
|
const title = selectionSetNames.length > 0 ? selectionSetNames.join(", ") : "download";
|
197
197
|
return title;
|
198
198
|
}
|
199
|
+
/**
|
200
|
+
* Creates relationship queries for each relationship flag in a popup.
|
201
|
+
* @param layer Layer whose popup is to be examined
|
202
|
+
* @return Hash of relationships by their id, or null if there are no relationship flags in the
|
203
|
+
* popup; each relationship has the properties layer and relatedQuery for the related layer
|
204
|
+
* and the query for that layer
|
205
|
+
*/
|
206
|
+
export function _createRelationshipQueries(layer) {
|
207
|
+
const relationships = {};
|
208
|
+
const relationshipFieldPattern = /\{relationships\/\d+\//gm;
|
209
|
+
const relationshipIdPattern = /\d+/;
|
210
|
+
// Test if this popup has any relationship references
|
211
|
+
const matches = layer.popupTemplate.content[0].text.match(relationshipFieldPattern);
|
212
|
+
if (matches) {
|
213
|
+
matches.forEach(match => {
|
214
|
+
// Add a query to a found relationship if we don't already have one
|
215
|
+
const id = match.match(relationshipIdPattern)[0];
|
216
|
+
if (!relationships.hasOwnProperty(id)) {
|
217
|
+
const relatedQuery = {
|
218
|
+
outFields: ['*'],
|
219
|
+
relationshipId: id,
|
220
|
+
returnGeometry: false
|
221
|
+
};
|
222
|
+
relationships[id] = {
|
223
|
+
layer,
|
224
|
+
relatedQuery
|
225
|
+
};
|
226
|
+
}
|
227
|
+
});
|
228
|
+
}
|
229
|
+
return relationships;
|
230
|
+
}
|
199
231
|
/**
|
200
232
|
* Prepares an attribute's value by applying domain and type information.
|
201
233
|
*
|
@@ -256,7 +288,7 @@ function _prepareAttributeValue(attributeValue, attributeType, attributeDomain,
|
|
256
288
|
* @returns Promise resolving when function is done
|
257
289
|
*/
|
258
290
|
async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLayerPopup = true, includeHeaderNames = false) {
|
259
|
-
var _a, _b, _c, _d;
|
291
|
+
var _a, _b, _c, _d, _e, _f;
|
260
292
|
const [intl] = await loadModules(["esri/intl"]);
|
261
293
|
// Get the features to export
|
262
294
|
const featureSet = await queryFeaturesByID(ids, layer);
|
@@ -270,6 +302,7 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
|
|
270
302
|
const attributeFormats = {};
|
271
303
|
// Get the label formatting, if any
|
272
304
|
let labelFormat;
|
305
|
+
let relationshipQueries = {};
|
273
306
|
let arcadeExecutors = {};
|
274
307
|
if (layer.popupEnabled) {
|
275
308
|
layer.popupTemplate.fieldInfos.forEach(
|
@@ -298,6 +331,8 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
|
|
298
331
|
}
|
299
332
|
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") {
|
300
333
|
labelFormat = _convertPopupTextToLabelSpec(layer.popupTemplate.content[0].text);
|
334
|
+
// Do we need any relationship queries?
|
335
|
+
relationshipQueries = _createRelationshipQueries(layer);
|
301
336
|
// Do we need any Arcade executors?
|
302
337
|
arcadeExecutors = await _createArcadeExecutors(labelFormat, layer);
|
303
338
|
}
|
@@ -306,36 +341,75 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
|
|
306
341
|
let labels;
|
307
342
|
// eslint-disable-next-line unicorn/prefer-ternary
|
308
343
|
if (labelFormat) {
|
344
|
+
console.log("labelFormat", labelFormat); //???
|
309
345
|
const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
|
310
346
|
const attributeRegExp = /\{\w+\}/g;
|
311
347
|
// Find the label fields that we need to replace with values
|
312
|
-
const arcadeExpressionMatches = labelFormat.match(arcadeExpressionRegExp);
|
313
|
-
const attributeMatches = labelFormat.match(attributeRegExp);
|
348
|
+
const arcadeExpressionMatches = (_e = labelFormat.match(arcadeExpressionRegExp)) !== null && _e !== void 0 ? _e : [];
|
349
|
+
const attributeMatches = (_f = labelFormat.match(attributeRegExp)) !== null && _f !== void 0 ? _f : [];
|
314
350
|
// Convert feature attributes into an array of labels
|
315
|
-
|
351
|
+
const relationshipKeys = Object.keys(relationshipQueries);
|
352
|
+
labels = await Promise.all(featureSet.features.map(async (feature) => {
|
316
353
|
let labelPrep = labelFormat;
|
317
|
-
// Replace Arcade expressions
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
354
|
+
// Replace Arcade expressions in this feature
|
355
|
+
arcadeExpressionMatches.forEach((match) => {
|
356
|
+
const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
|
357
|
+
const value = arcadeExecutors[expressionName].execute({ "$feature": feature });
|
358
|
+
labelPrep = labelPrep.replace(match, value);
|
359
|
+
});
|
360
|
+
// Replace relationship expressions in this feature
|
361
|
+
const relatedFeatureQueries = [];
|
362
|
+
const relationshipIds = [];
|
363
|
+
relationshipKeys.forEach((relationshipId) => {
|
364
|
+
const relationship = relationshipQueries[relationshipId];
|
365
|
+
const objectId = feature.attributes[relationship.layer.objectIdField];
|
366
|
+
const relatedQuery = Object.assign(Object.assign({}, relationship.relatedQuery), { objectIds: [objectId] });
|
367
|
+
relatedFeatureQueries.push(relationship.layer.queryRelatedFeatures(relatedQuery));
|
368
|
+
relationshipIds.push(relationshipId);
|
369
|
+
});
|
370
|
+
// Wait for all of the queries for related records for this label
|
371
|
+
const relatedFeatureQueryResults = await Promise.all(relatedFeatureQueries);
|
372
|
+
console.log("relatedFeatureQueryResults", relatedFeatureQueryResults); //???
|
373
|
+
relatedFeatureQueryResults.forEach((relatedFeatureQueryResult, i) => {
|
374
|
+
// We have an object with FeatureSets grouped by source layer or table objectIds
|
375
|
+
const relationshipId = relationshipIds[i];
|
376
|
+
console.log("relationshipId", relationshipId); //???
|
377
|
+
console.log("relatedFeatureQueryResult", relatedFeatureQueryResult); //???
|
378
|
+
// Run through the source layer or table objectIds
|
379
|
+
Object.keys(relatedFeatureQueryResult).forEach(relatedFeatureSetId => {
|
380
|
+
console.log("relatedFeatureSetId", relatedFeatureSetId); //???
|
381
|
+
// We have a feature set
|
382
|
+
const relatedFeatures = relatedFeatureQueryResult[relatedFeatureSetId].features;
|
383
|
+
console.log("relatedFeatures", relatedFeatures); //???
|
384
|
+
// Get the values from each feature and replace them in the label
|
385
|
+
relatedFeatures.forEach(feature => {
|
386
|
+
// Merge the base and related feature attributes and create the label
|
387
|
+
// Prefix related feature's attributes with "relationships/<id>/" to match popup
|
388
|
+
const rePrefix = "\{relationships/" + relationshipId + "/";
|
389
|
+
const reSuffix = "\}";
|
390
|
+
console.log("/rePrefix + attributeName + reSuffix/g", rePrefix + "attributeName" + reSuffix); //???
|
391
|
+
const attributes = feature.attributes;
|
392
|
+
Object.keys(attributes).forEach(attributeName => {
|
393
|
+
console.log("/rePrefix + attributeName + reSuffix/g", rePrefix + attributeName + reSuffix); //???
|
394
|
+
// Replace the value using the attribute name as a relationship
|
395
|
+
const attributeRelationshipRegExp = new RegExp(rePrefix + attributeName + reSuffix, "g");
|
396
|
+
labelPrep = labelPrep.replaceAll(attributeRelationshipRegExp, attributes[attributeName]);
|
397
|
+
});
|
398
|
+
});
|
331
399
|
});
|
332
|
-
}
|
400
|
+
});
|
401
|
+
// Replace non-Arcade fields in this feature
|
402
|
+
attributeMatches.forEach((match) => {
|
403
|
+
const attributeName = match.substring(1, match.length - 1);
|
404
|
+
const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], attributeFormats[attributeName], intl);
|
405
|
+
labelPrep = labelPrep.replace(match, value);
|
406
|
+
});
|
333
407
|
// Split label into lines
|
334
408
|
let label = labelPrep.split(lineSeparatorChar);
|
335
409
|
// Trim lines
|
336
410
|
label = label.map(line => line.trim());
|
337
411
|
return label;
|
338
|
-
});
|
412
|
+
}));
|
339
413
|
}
|
340
414
|
else {
|
341
415
|
// Export all attributes
|
@@ -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
|
-
|
422
|
-
|
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
|
-
|
427
|
-
|
428
|
-
(match
|
429
|
-
|
430
|
-
|
431
|
-
|
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
|
-
//
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
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
|
-
|
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
|
-
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
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
|
@@ -22,14 +22,14 @@ import { d as defineCustomElement$b } from './input-message.js';
|
|
22
22
|
import { d as defineCustomElement$a } from './label.js';
|
23
23
|
import { d as defineCustomElement$9 } from './loader.js';
|
24
24
|
import { d as defineCustomElement$8 } from './option.js';
|
25
|
-
import { d as defineCustomElement$7 } from './
|
26
|
-
import { d as defineCustomElement$6 } from './
|
27
|
-
import { d as defineCustomElement$5 } from './
|
28
|
-
import { d as defineCustomElement$4 } from './
|
29
|
-
import { d as defineCustomElement$3 } from './
|
25
|
+
import { d as defineCustomElement$7 } from './popover.js';
|
26
|
+
import { d as defineCustomElement$6 } from './progress.js';
|
27
|
+
import { d as defineCustomElement$5 } from './select.js';
|
28
|
+
import { d as defineCustomElement$4 } from './slider.js';
|
29
|
+
import { d as defineCustomElement$3 } from './switch.js';
|
30
30
|
import { d as defineCustomElement$2 } from './map-draw-tools2.js';
|
31
31
|
|
32
|
-
const mapSelectToolsCss = ":host{display:block}.div-visible{display:inherit}.div-visible-search{display:flex;height:44px;align-items:center;padding-bottom:0}.div-not-visible{display:none}.padding-bottom-1{padding-bottom:1rem}.padding-top-1{padding-top:1rem}.search-widget{width:100% !important;border:1px solid var(--calcite-ui-border-input)}.w-100{width:100%}.w-50{width:50%}.search-distance-container{padding-top:\"1rem\" !important}.end-border{-webkit-border-end:1px solid var(--calcite-ui-border-2);border-inline-end:1px solid var(--calcite-ui-border-2)}.search-distance{display:flex;padding-top:1rem}.font-bold{font:bold}.border-bottom{border-bottom:1px solid var(--calcite-ui-border-2)}.tooltip-container{
|
32
|
+
const mapSelectToolsCss = ":host{display:block}.div-visible{display:inherit}.div-visible-search{display:flex;height:44px;align-items:center;padding-bottom:0}.div-not-visible{display:none}.padding-bottom-1{padding-bottom:1rem}.padding-top-1{padding-top:1rem}.search-widget{width:100% !important;border:1px solid var(--calcite-ui-border-input)}.w-100{width:100%}.w-50{width:50%}.search-distance-container{padding-top:\"1rem\" !important}.end-border{-webkit-border-end:1px solid var(--calcite-ui-border-2);border-inline-end:1px solid var(--calcite-ui-border-2)}.search-distance{display:flex;padding-top:1rem}.font-bold{font:bold}.border-bottom{border-bottom:1px solid var(--calcite-ui-border-2)}.tooltip-container{display:flex}.padding-start-1-2{-webkit-padding-start:0.5rem;padding-inline-start:0.5rem}.icon{--calcite-ui-icon-color:var(--calcite-ui-brand)}.tooltip-message{padding:5px 8px;font-weight:var(--calcite-font-weight-normal);color:var(--calcite-ui-text-2)}";
|
33
33
|
|
34
34
|
const MapSelectTools = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
35
35
|
constructor() {
|
@@ -200,14 +200,14 @@ const MapSelectTools = /*@__PURE__*/ proxyCustomElement(class extends HTMLElemen
|
|
200
200
|
var _a, _b;
|
201
201
|
const showBufferToolsClass = this._searchDistanceEnabled ? "search-distance" : "div-not-visible";
|
202
202
|
const bufferDistance = typeof ((_a = this.selectionSet) === null || _a === void 0 ? void 0 : _a.distance) === "number" ? this.selectionSet.distance : this.defaultBufferDistance;
|
203
|
-
return (h("div", null, h("div", { class: "padding-top-1 display-flex" }, h("calcite-label", { class: "label-margin-0 w-100", layout: "inline-space-between" }, h("div", { class: "tooltip-container" }, this._translations.searchDistance, h("calcite-icon", { class: "padding-start-1-2 icon", icon: "question", id: "search-distance-icon", scale: "s" }), h("calcite-
|
203
|
+
return (h("div", null, h("div", { class: "padding-top-1 display-flex" }, h("calcite-label", { class: "label-margin-0 w-100", layout: "inline-space-between" }, h("div", { class: "tooltip-container" }, this._translations.searchDistance, h("calcite-icon", { class: "padding-start-1-2 icon", icon: "question", id: "search-distance-icon", scale: "s" }))), h("calcite-popover", { closable: true, label: "", referenceElement: "search-distance-icon" }, h("span", { class: "tooltip-message" }, this._translations.useSearchDistanceTootip)), h("calcite-switch", { checked: this._searchDistanceEnabled, onCalciteSwitchChange: () => this._searchDistanceEnabled = !this._searchDistanceEnabled })), h("div", { class: showBufferToolsClass }, h("buffer-tools", { disabled: !this._searchDistanceEnabled, distance: bufferDistance, geometries: this.geometries, onBufferComplete: (evt) => this._bufferComplete(evt), ref: (el) => this._bufferTools = el, unit: ((_b = this.selectionSet) === null || _b === void 0 ? void 0 : _b.unit) || this.defaultBufferUnit }))));
|
204
204
|
}
|
205
205
|
/**
|
206
206
|
* Renders the map layer picker component.
|
207
207
|
*/
|
208
208
|
_getUseLayerFeaturesOptions() {
|
209
209
|
const useLayerFeaturesClass = this._useLayerFeaturesEnabled ? "div-visible" : "div-not-visible";
|
210
|
-
return (h("div", null, h("div", { class: "padding-top-1 display-flex" }, h("calcite-label", { class: "label-margin-0 w-100", layout: "inline-space-between" }, h("div", { class: "tooltip-container" }, this._translations.useLayerFeatures, h("calcite-icon", { class: "padding-start-1-2 icon", icon: "question", id: "use-layer-features-icon", scale: "s" }), h("calcite-
|
210
|
+
return (h("div", null, h("div", { class: "padding-top-1 display-flex" }, h("calcite-label", { class: "label-margin-0 w-100", layout: "inline-space-between" }, h("div", { class: "tooltip-container" }, this._translations.useLayerFeatures, h("calcite-icon", { class: "padding-start-1-2 icon", icon: "question", id: "use-layer-features-icon", scale: "s" }))), h("calcite-popover", { closable: true, label: "", referenceElement: "use-layer-features-icon" }, h("span", { class: "tooltip-message" }, this._translations.useLayerFeaturesTooltip)), h("calcite-switch", { checked: this._useLayerFeaturesEnabled, onCalciteSwitchChange: () => { this._useLayerFeaturesEnabledChanged(); } })), h("div", { class: useLayerFeaturesClass + " padding-top-1" }, h("map-layer-picker", { enabledLayerIds: this.enabledLayerIds, mapView: this.mapView, onLayerSelectionChange: (evt) => { void this._layerSelectionChange(evt); }, selectedLayerIds: this.layerViews.map(l => l.layer.id), selectionMode: "single" }))));
|
211
211
|
}
|
212
212
|
/**
|
213
213
|
* Renders the number of selected features
|
@@ -809,7 +809,7 @@ function defineCustomElement() {
|
|
809
809
|
if (typeof customElements === "undefined") {
|
810
810
|
return;
|
811
811
|
}
|
812
|
-
const components = ["map-select-tools", "buffer-tools", "calcite-action", "calcite-chip", "calcite-combobox", "calcite-combobox-item", "calcite-graph", "calcite-icon", "calcite-input", "calcite-input-message", "calcite-label", "calcite-loader", "calcite-option", "calcite-
|
812
|
+
const components = ["map-select-tools", "buffer-tools", "calcite-action", "calcite-chip", "calcite-combobox", "calcite-combobox-item", "calcite-graph", "calcite-icon", "calcite-input", "calcite-input-message", "calcite-label", "calcite-loader", "calcite-option", "calcite-popover", "calcite-progress", "calcite-select", "calcite-slider", "calcite-switch", "map-draw-tools", "map-layer-picker"];
|
813
813
|
components.forEach(tagName => { switch (tagName) {
|
814
814
|
case "map-select-tools":
|
815
815
|
if (!customElements.get(tagName)) {
|
@@ -876,27 +876,27 @@ function defineCustomElement() {
|
|
876
876
|
defineCustomElement$8();
|
877
877
|
}
|
878
878
|
break;
|
879
|
-
case "calcite-
|
879
|
+
case "calcite-popover":
|
880
880
|
if (!customElements.get(tagName)) {
|
881
881
|
defineCustomElement$7();
|
882
882
|
}
|
883
883
|
break;
|
884
|
-
case "calcite-
|
884
|
+
case "calcite-progress":
|
885
885
|
if (!customElements.get(tagName)) {
|
886
886
|
defineCustomElement$6();
|
887
887
|
}
|
888
888
|
break;
|
889
|
-
case "calcite-
|
889
|
+
case "calcite-select":
|
890
890
|
if (!customElements.get(tagName)) {
|
891
891
|
defineCustomElement$5();
|
892
892
|
}
|
893
893
|
break;
|
894
|
-
case "calcite-
|
894
|
+
case "calcite-slider":
|
895
895
|
if (!customElements.get(tagName)) {
|
896
896
|
defineCustomElement$4();
|
897
897
|
}
|
898
898
|
break;
|
899
|
-
case "calcite-
|
899
|
+
case "calcite-switch":
|
900
900
|
if (!customElements.get(tagName)) {
|
901
901
|
defineCustomElement$3();
|
902
902
|
}
|