@esri/solutions-components 0.4.3 → 0.4.5
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/public-notification/resources.json +5 -5
- package/dist/assets/t9n/public-notification/resources_en.json +5 -5
- package/dist/cjs/calcite-input-message_5.cjs.entry.js +1 -17
- package/dist/cjs/{downloadUtils-ae182e3a.js → downloadUtils-d05b069f.js} +91 -42
- package/dist/cjs/{index.es-b71e9071.js → index.es-e47b660c.js} +1 -1
- package/dist/cjs/layer-table.cjs.entry.js +1 -1
- package/dist/cjs/public-notification.cjs.entry.js +3 -11
- package/dist/collection/components/map-select-tools/map-select-tools.js +0 -16
- package/dist/collection/components/public-notification/public-notification.js +3 -11
- package/dist/collection/utils/downloadUtils.js +90 -41
- package/dist/collection/utils/downloadUtils.ts +123 -52
- package/dist/components/downloadUtils.js +90 -41
- package/dist/components/map-select-tools2.js +0 -16
- package/dist/components/public-notification.js +3 -11
- package/dist/esm/calcite-input-message_5.entry.js +1 -17
- package/dist/esm/{downloadUtils-8d64719e.js → downloadUtils-a9b39194.js} +91 -42
- package/dist/esm/{index.es-1d777745.js → index.es-4904465f.js} +1 -1
- package/dist/esm/layer-table.entry.js +1 -1
- package/dist/esm/public-notification.entry.js +3 -11
- package/dist/solutions-components/p-20c73673.entry.js +6 -0
- package/dist/solutions-components/{p-702e1915.js → p-25eb36dc.js} +1 -1
- package/dist/solutions-components/p-59caff67.entry.js +17 -0
- package/dist/solutions-components/{p-048a4c91.entry.js → p-a606221a.entry.js} +1 -1
- package/dist/solutions-components/{p-01215468.js → p-e7b3a4d9.js} +3 -3
- package/dist/solutions-components/solutions-components.esm.js +1 -1
- package/dist/solutions-components/utils/downloadUtils.ts +123 -52
- package/dist/types/components/json-editor/assets/monaco-editor/monaco.d.ts +8262 -0
- package/package.json +1 -1
- package/dist/solutions-components/p-4bfcd9ea.entry.js +0 -17
- package/dist/solutions-components/p-a99ca396.entry.js +0 -6
@@ -24,6 +24,7 @@ import { exportPDF } from "./pdfUtils";
|
|
24
24
|
import { loadModules } from "./loadModules";
|
25
25
|
import { queryFeaturesByID } from "./queryUtils";
|
26
26
|
export { ILabel } from "./pdfUtils";
|
27
|
+
const lineSeparatorChar = "|";
|
27
28
|
//#endregion
|
28
29
|
//#region Public functions
|
29
30
|
/**
|
@@ -56,7 +57,12 @@ export async function downloadCSV(selectionSetNames, layer, ids, formatUsingLaye
|
|
56
57
|
*/
|
57
58
|
export async function downloadPDF(selectionSetNames, layer, ids, removeDuplicates, labelPageDescription) {
|
58
59
|
console.log("downloadPDF using selectionSetNames " + JSON.stringify(selectionSetNames)); //???
|
59
|
-
|
60
|
+
let labels = await _prepareLabels(layer, ids, removeDuplicates);
|
61
|
+
labels =
|
62
|
+
// Remove empty lines in labels
|
63
|
+
labels.map(labelLines => labelLines.filter(line => line.length > 0))
|
64
|
+
// Remove empty labels
|
65
|
+
.filter(label => label.length > 0);
|
60
66
|
exportPDF(labels, labelPageDescription);
|
61
67
|
return Promise.resolve();
|
62
68
|
}
|
@@ -67,7 +73,7 @@ export async function downloadPDF(selectionSetNames, layer, ids, removeDuplicate
|
|
67
73
|
*
|
68
74
|
* @param fieldInfos Layer's fieldInfos structure
|
69
75
|
* @param bypassFieldVisiblity Indicates if the configured fieldInfo visibility property should be ignored
|
70
|
-
* @return Label spec
|
76
|
+
* @return Label spec with lines separated by `lineSeparatorChar`
|
71
77
|
*/
|
72
78
|
function _convertPopupFieldsToLabelSpec(fieldInfos, bypassFieldVisiblity = false) {
|
73
79
|
const labelSpec = [];
|
@@ -77,7 +83,7 @@ function _convertPopupFieldsToLabelSpec(fieldInfos, bypassFieldVisiblity = false
|
|
77
83
|
labelSpec.push(`{${fieldInfo.fieldName}}`);
|
78
84
|
}
|
79
85
|
});
|
80
|
-
return labelSpec;
|
86
|
+
return labelSpec.join(lineSeparatorChar);
|
81
87
|
}
|
82
88
|
;
|
83
89
|
/**
|
@@ -86,22 +92,19 @@ function _convertPopupFieldsToLabelSpec(fieldInfos, bypassFieldVisiblity = false
|
|
86
92
|
*
|
87
93
|
* @param popupInfo Layer's popupInfo structure containing description, fieldInfos, and expressionInfos, e.g.,
|
88
94
|
* "<div style='text-align: left;'>{NAME}<br />{STREET}<br />{CITY}, {STATE} {ZIP} <br /></div>"
|
89
|
-
* @return Label spec
|
95
|
+
* @return Label spec with lines separated by `lineSeparatorChar`
|
90
96
|
*/
|
91
97
|
function _convertPopupTextToLabelSpec(popupInfo) {
|
92
|
-
// Replace <br>, <br/> with
|
93
|
-
popupInfo = popupInfo.replace(/<br\s*\/?>/gi,
|
94
|
-
// Remove remaining HTML tags, replace 0xA0 that popup uses for spaces, replace some char representations,
|
98
|
+
// Replace <br>, <br/> with the line separator character
|
99
|
+
popupInfo = popupInfo.replace(/<br\s*\/?>/gi, lineSeparatorChar);
|
100
|
+
// Remove remaining HTML tags, replace 0xA0 that popup uses for spaces, and replace some char representations,
|
95
101
|
// and split the label back into individual lines
|
96
|
-
|
102
|
+
const labelSpec = popupInfo
|
97
103
|
.replace(/<[\s.]*[^<>]*\/?>/gi, "")
|
98
104
|
.replace(/\xA0/gi, " ")
|
99
105
|
.replace(/</gi, "<")
|
100
106
|
.replace(/>/gi, ">")
|
101
|
-
.replace(/ /gi, " ")
|
102
|
-
.split("|");
|
103
|
-
// Trim lines and remove empties
|
104
|
-
labelSpec = labelSpec.map(line => line.trim()).filter(line => line.length > 0);
|
107
|
+
.replace(/ /gi, " ");
|
105
108
|
return labelSpec;
|
106
109
|
}
|
107
110
|
;
|
@@ -121,7 +124,7 @@ async function _createArcadeExecutors(labelFormat, layer) {
|
|
121
124
|
}
|
122
125
|
// Are there any Arcade expressions in the label format?
|
123
126
|
const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
|
124
|
-
const arcadeExpressionsMatches = labelFormat.
|
127
|
+
const arcadeExpressionsMatches = labelFormat.match(arcadeExpressionRegExp);
|
125
128
|
if (!arcadeExpressionsMatches) {
|
126
129
|
return Promise.resolve(arcadeExecutors);
|
127
130
|
}
|
@@ -148,6 +151,39 @@ async function _createArcadeExecutors(labelFormat, layer) {
|
|
148
151
|
return arcadeExecutors;
|
149
152
|
});
|
150
153
|
}
|
154
|
+
/**
|
155
|
+
* Prepares an attribute's value by applying domain and type information.
|
156
|
+
*
|
157
|
+
* @param attributeValue Value of attribute
|
158
|
+
* @param attributeType Type of attribute
|
159
|
+
* @param attributeDomain Domain info for attribute, if any
|
160
|
+
* @return Attribute value modified appropriate to domain and type
|
161
|
+
*/
|
162
|
+
function _prepareAttributeValue(attributeValue, attributeType, attributeDomain, intl) {
|
163
|
+
if (attributeDomain && attributeDomain.type === "coded-value") {
|
164
|
+
// "coded-value" domain field
|
165
|
+
const value = attributeDomain.getName(attributeValue);
|
166
|
+
return value;
|
167
|
+
}
|
168
|
+
else {
|
169
|
+
// Non-domain field or unsupported domain type
|
170
|
+
let value = attributeValue;
|
171
|
+
switch (attributeType) {
|
172
|
+
case "date":
|
173
|
+
// Format date produces odd characters for the space between the time and the AM/PM text,
|
174
|
+
// e.g., "12/31/1969, 4:00 PM"
|
175
|
+
value = intl.formatDate(value).replace(/\xe2\x80\xaf/g, "");
|
176
|
+
break;
|
177
|
+
case "double":
|
178
|
+
case "integer":
|
179
|
+
case "long":
|
180
|
+
case "small-integer":
|
181
|
+
value = intl.formatNumber(value);
|
182
|
+
break;
|
183
|
+
}
|
184
|
+
return value;
|
185
|
+
}
|
186
|
+
}
|
151
187
|
/**
|
152
188
|
* Creates labels from items.
|
153
189
|
*
|
@@ -164,6 +200,13 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
|
|
164
200
|
const [intl] = await loadModules(["esri/intl"]);
|
165
201
|
// Get the features to export
|
166
202
|
const featureSet = await queryFeaturesByID(ids, layer);
|
203
|
+
// Get field data types. Do we have any domain-based fields?
|
204
|
+
const attributeTypes = {};
|
205
|
+
const attributeDomains = {};
|
206
|
+
layer.fields.forEach(field => {
|
207
|
+
attributeTypes[field.name] = field.type;
|
208
|
+
attributeDomains[field.name] = field.domain;
|
209
|
+
});
|
167
210
|
// Get the label formatting, if any
|
168
211
|
let labelFormat;
|
169
212
|
let arcadeExecutors = {};
|
@@ -177,7 +220,7 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
|
|
177
220
|
// Can we use the popup title?
|
178
221
|
// eslint-disable-next-line unicorn/prefer-ternary
|
179
222
|
if (typeof layer.popupTemplate.title === "string") {
|
180
|
-
labelFormat =
|
223
|
+
labelFormat = layer.popupTemplate.title;
|
181
224
|
// Otherwise revert to using attributes
|
182
225
|
}
|
183
226
|
else {
|
@@ -196,35 +239,43 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
|
|
196
239
|
// eslint-disable-next-line unicorn/prefer-ternary
|
197
240
|
if (labelFormat) {
|
198
241
|
const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
|
199
|
-
|
242
|
+
const attributeRegExp = /\{\w+\}/g;
|
243
|
+
// Find the label fields that we need to replace with values
|
244
|
+
const arcadeExpressionMatches = labelFormat.match(arcadeExpressionRegExp);
|
245
|
+
const attributeMatches = labelFormat.match(attributeRegExp);
|
246
|
+
// Convert feature attributes into an array of labels
|
200
247
|
labels = featureSet.features.map(feature => {
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
248
|
+
let labelPrep = labelFormat;
|
249
|
+
// Replace Arcade expressions
|
250
|
+
if (arcadeExpressionMatches) {
|
251
|
+
arcadeExpressionMatches.forEach((match) => {
|
252
|
+
const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
|
253
|
+
const value = arcadeExecutors[expressionName].execute({ "$feature": feature });
|
254
|
+
labelPrep = labelPrep.replace(match, value);
|
255
|
+
});
|
256
|
+
}
|
257
|
+
// Replace non-Arcade fields
|
258
|
+
if (attributeMatches) {
|
259
|
+
attributeMatches.forEach((match) => {
|
260
|
+
const attributeName = match.substring(1, match.length - 1);
|
261
|
+
const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], intl);
|
262
|
+
labelPrep = labelPrep.replace(match, value);
|
263
|
+
});
|
264
|
+
}
|
265
|
+
// Split label into lines
|
266
|
+
let label = labelPrep.split(lineSeparatorChar);
|
267
|
+
// Trim lines
|
268
|
+
label = label.map(line => line.trim());
|
219
269
|
return label;
|
220
|
-
})
|
221
|
-
// Remove empty labels
|
222
|
-
.filter(label => label.length > 0);
|
270
|
+
});
|
223
271
|
}
|
224
272
|
else {
|
225
273
|
// Export all attributes
|
226
274
|
labels = featureSet.features.map(feature => {
|
227
|
-
return Object.
|
275
|
+
return Object.keys(feature.attributes).map((attributeName) => {
|
276
|
+
const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], intl);
|
277
|
+
return `${value}`;
|
278
|
+
});
|
228
279
|
});
|
229
280
|
}
|
230
281
|
// Remove duplicates
|
@@ -237,14 +288,12 @@ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLa
|
|
237
288
|
if (includeHeaderNames) {
|
238
289
|
let headerNames = [];
|
239
290
|
if (labelFormat) {
|
240
|
-
headerNames = labelFormat.
|
291
|
+
headerNames = labelFormat.replace(/\{/g, "").replace(/\}/g, "").split(lineSeparatorChar);
|
241
292
|
}
|
242
293
|
else {
|
243
294
|
const featuresAttrs = featureSet.features[0].attributes;
|
244
295
|
Object.keys(featuresAttrs).forEach(k => {
|
245
|
-
|
246
|
-
headerNames.push(k);
|
247
|
-
}
|
296
|
+
headerNames.push(k);
|
248
297
|
});
|
249
298
|
}
|
250
299
|
labels.unshift(headerNames);
|
@@ -31,6 +31,16 @@ interface IArcadeExecutorPromises {
|
|
31
31
|
[expressionName: string]: Promise<__esri.ArcadeExecutor>;
|
32
32
|
}
|
33
33
|
|
34
|
+
interface IAttributeDomains {
|
35
|
+
[attributeName: string]: __esri.CodedValueDomain | __esri.RangeDomain | __esri.InheritedDomain | null;
|
36
|
+
}
|
37
|
+
|
38
|
+
interface IAttributeTypes {
|
39
|
+
[attributeName: string]: string;
|
40
|
+
}
|
41
|
+
|
42
|
+
const lineSeparatorChar = "|";
|
43
|
+
|
34
44
|
//#endregion
|
35
45
|
//#region Public functions
|
36
46
|
|
@@ -80,7 +90,13 @@ export async function downloadPDF(
|
|
80
90
|
labelPageDescription: ILabel
|
81
91
|
): Promise<void> {
|
82
92
|
console.log("downloadPDF using selectionSetNames " + JSON.stringify(selectionSetNames));//???
|
83
|
-
|
93
|
+
let labels = await _prepareLabels(layer, ids, removeDuplicates);
|
94
|
+
|
95
|
+
labels =
|
96
|
+
// Remove empty lines in labels
|
97
|
+
labels.map(labelLines => labelLines.filter(line => line.length > 0))
|
98
|
+
// Remove empty labels
|
99
|
+
.filter(label => label.length > 0);
|
84
100
|
|
85
101
|
exportPDF(labels, labelPageDescription);
|
86
102
|
|
@@ -95,12 +111,12 @@ export async function downloadPDF(
|
|
95
111
|
*
|
96
112
|
* @param fieldInfos Layer's fieldInfos structure
|
97
113
|
* @param bypassFieldVisiblity Indicates if the configured fieldInfo visibility property should be ignored
|
98
|
-
* @return Label spec
|
114
|
+
* @return Label spec with lines separated by `lineSeparatorChar`
|
99
115
|
*/
|
100
116
|
function _convertPopupFieldsToLabelSpec(
|
101
117
|
fieldInfos: __esri.FieldInfo[],
|
102
118
|
bypassFieldVisiblity = false
|
103
|
-
): string
|
119
|
+
): string {
|
104
120
|
const labelSpec: string[] = [];
|
105
121
|
|
106
122
|
// Every visible attribute is used
|
@@ -112,7 +128,7 @@ function _convertPopupFieldsToLabelSpec(
|
|
112
128
|
}
|
113
129
|
);
|
114
130
|
|
115
|
-
return labelSpec;
|
131
|
+
return labelSpec.join(lineSeparatorChar);
|
116
132
|
};
|
117
133
|
|
118
134
|
/**
|
@@ -121,26 +137,22 @@ function _convertPopupFieldsToLabelSpec(
|
|
121
137
|
*
|
122
138
|
* @param popupInfo Layer's popupInfo structure containing description, fieldInfos, and expressionInfos, e.g.,
|
123
139
|
* "<div style='text-align: left;'>{NAME}<br />{STREET}<br />{CITY}, {STATE} {ZIP} <br /></div>"
|
124
|
-
* @return Label spec
|
140
|
+
* @return Label spec with lines separated by `lineSeparatorChar`
|
125
141
|
*/
|
126
142
|
function _convertPopupTextToLabelSpec(
|
127
|
-
popupInfo: string
|
128
|
-
): string
|
129
|
-
// Replace <br>, <br/> with
|
130
|
-
popupInfo = popupInfo.replace(/<br\s*\/?>/gi,
|
143
|
+
popupInfo: string,
|
144
|
+
): string {
|
145
|
+
// Replace <br>, <br/> with the line separator character
|
146
|
+
popupInfo = popupInfo.replace(/<br\s*\/?>/gi, lineSeparatorChar);
|
131
147
|
|
132
|
-
// Remove remaining HTML tags, replace 0xA0 that popup uses for spaces, replace some char representations,
|
148
|
+
// Remove remaining HTML tags, replace 0xA0 that popup uses for spaces, and replace some char representations,
|
133
149
|
// and split the label back into individual lines
|
134
|
-
|
150
|
+
const labelSpec = popupInfo
|
135
151
|
.replace(/<[\s.]*[^<>]*\/?>/gi, "")
|
136
152
|
.replace(/\xA0/gi, " ")
|
137
153
|
.replace(/</gi, "<")
|
138
154
|
.replace(/>/gi, ">")
|
139
|
-
.replace(/ /gi, " ")
|
140
|
-
.split("|");
|
141
|
-
|
142
|
-
// Trim lines and remove empties
|
143
|
-
labelSpec = labelSpec.map(line => line.trim()).filter(line => line.length > 0);
|
155
|
+
.replace(/ /gi, " ");
|
144
156
|
|
145
157
|
return labelSpec;
|
146
158
|
};
|
@@ -154,7 +166,7 @@ function _convertPopupTextToLabelSpec(
|
|
154
166
|
* @return Promise resolving to a set of executors keyed using the expression name
|
155
167
|
*/
|
156
168
|
async function _createArcadeExecutors(
|
157
|
-
labelFormat: string
|
169
|
+
labelFormat: string,
|
158
170
|
layer: __esri.FeatureLayer
|
159
171
|
): Promise<IArcadeExecutors> {
|
160
172
|
const arcadeExecutors: IArcadeExecutors = {};
|
@@ -166,7 +178,7 @@ async function _createArcadeExecutors(
|
|
166
178
|
|
167
179
|
// Are there any Arcade expressions in the label format?
|
168
180
|
const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
|
169
|
-
const arcadeExpressionsMatches = labelFormat.
|
181
|
+
const arcadeExpressionsMatches = labelFormat.match(arcadeExpressionRegExp);
|
170
182
|
if (!arcadeExpressionsMatches) {
|
171
183
|
return Promise.resolve(arcadeExecutors);
|
172
184
|
}
|
@@ -206,6 +218,44 @@ async function _createArcadeExecutors(
|
|
206
218
|
);
|
207
219
|
}
|
208
220
|
|
221
|
+
/**
|
222
|
+
* Prepares an attribute's value by applying domain and type information.
|
223
|
+
*
|
224
|
+
* @param attributeValue Value of attribute
|
225
|
+
* @param attributeType Type of attribute
|
226
|
+
* @param attributeDomain Domain info for attribute, if any
|
227
|
+
* @return Attribute value modified appropriate to domain and type
|
228
|
+
*/
|
229
|
+
function _prepareAttributeValue(
|
230
|
+
attributeValue: any,
|
231
|
+
attributeType: string,
|
232
|
+
attributeDomain: __esri.CodedValueDomain | __esri.RangeDomain | __esri.InheritedDomain | null,
|
233
|
+
intl: any
|
234
|
+
): any {
|
235
|
+
if (attributeDomain && (attributeDomain as __esri.CodedValueDomain).type === "coded-value") {
|
236
|
+
// "coded-value" domain field
|
237
|
+
const value = (attributeDomain as __esri.CodedValueDomain).getName(attributeValue);
|
238
|
+
return value;
|
239
|
+
} else {
|
240
|
+
// Non-domain field or unsupported domain type
|
241
|
+
let value = attributeValue;
|
242
|
+
switch (attributeType) {
|
243
|
+
case "date":
|
244
|
+
// Format date produces odd characters for the space between the time and the AM/PM text,
|
245
|
+
// e.g., "12/31/1969, 4:00 PM"
|
246
|
+
value = intl.formatDate(value).replace(/\xe2\x80\xaf/g, "");
|
247
|
+
break;
|
248
|
+
case "double":
|
249
|
+
case "integer":
|
250
|
+
case "long":
|
251
|
+
case "small-integer":
|
252
|
+
value = intl.formatNumber(value);
|
253
|
+
break;
|
254
|
+
}
|
255
|
+
return value;
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
209
259
|
/**
|
210
260
|
* Creates labels from items.
|
211
261
|
*
|
@@ -229,8 +279,18 @@ async function _prepareLabels(
|
|
229
279
|
// Get the features to export
|
230
280
|
const featureSet = await queryFeaturesByID(ids, layer);
|
231
281
|
|
282
|
+
// Get field data types. Do we have any domain-based fields?
|
283
|
+
const attributeTypes: IAttributeTypes = {};
|
284
|
+
const attributeDomains: IAttributeDomains = {};
|
285
|
+
layer.fields.forEach(
|
286
|
+
field => {
|
287
|
+
attributeTypes[field.name] = field.type;
|
288
|
+
attributeDomains[field.name] = field.domain;
|
289
|
+
}
|
290
|
+
);
|
291
|
+
|
232
292
|
// Get the label formatting, if any
|
233
|
-
let labelFormat: string
|
293
|
+
let labelFormat: string;
|
234
294
|
let arcadeExecutors: IArcadeExecutors = {};
|
235
295
|
if (layer.popupEnabled) {
|
236
296
|
// What data fields are used in the labels?
|
@@ -243,7 +303,7 @@ async function _prepareLabels(
|
|
243
303
|
// Can we use the popup title?
|
244
304
|
// eslint-disable-next-line unicorn/prefer-ternary
|
245
305
|
if (typeof layer.popupTemplate.title === "string") {
|
246
|
-
labelFormat =
|
306
|
+
labelFormat = layer.popupTemplate.title;
|
247
307
|
|
248
308
|
// Otherwise revert to using attributes
|
249
309
|
} else {
|
@@ -264,47 +324,60 @@ async function _prepareLabels(
|
|
264
324
|
// eslint-disable-next-line unicorn/prefer-ternary
|
265
325
|
if (labelFormat) {
|
266
326
|
const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
|
327
|
+
const attributeRegExp = /\{\w+\}/g;
|
328
|
+
|
329
|
+
// Find the label fields that we need to replace with values
|
330
|
+
const arcadeExpressionMatches = labelFormat.match(arcadeExpressionRegExp);
|
331
|
+
const attributeMatches = labelFormat.match(attributeRegExp);
|
267
332
|
|
268
|
-
// Convert attributes into an array of labels
|
333
|
+
// Convert feature attributes into an array of labels
|
269
334
|
labels = featureSet.features.map(
|
270
335
|
feature => {
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
(match: string) => {
|
281
|
-
const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
|
282
|
-
const replacement = arcadeExecutors[expressionName].execute({"$feature": feature});
|
283
|
-
labelLine = labelLine.replace(match, replacement);
|
284
|
-
}
|
285
|
-
)
|
336
|
+
let labelPrep = labelFormat;
|
337
|
+
|
338
|
+
// Replace Arcade expressions
|
339
|
+
if (arcadeExpressionMatches) {
|
340
|
+
arcadeExpressionMatches.forEach(
|
341
|
+
(match: string) => {
|
342
|
+
const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
|
343
|
+
const value = arcadeExecutors[expressionName].execute({"$feature": feature});
|
344
|
+
labelPrep = labelPrep.replace(match, value);
|
286
345
|
}
|
346
|
+
)
|
347
|
+
}
|
287
348
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
349
|
+
// Replace non-Arcade fields
|
350
|
+
if (attributeMatches) {
|
351
|
+
attributeMatches.forEach(
|
352
|
+
(match: string) => {
|
353
|
+
const attributeName = match.substring(1, match.length - 1);
|
354
|
+
const value = _prepareAttributeValue(feature.attributes[attributeName],
|
355
|
+
attributeTypes[attributeName], attributeDomains[attributeName], intl);
|
356
|
+
labelPrep = labelPrep.replace(match, value);
|
293
357
|
}
|
294
|
-
|
295
|
-
|
358
|
+
)
|
359
|
+
}
|
360
|
+
|
361
|
+
// Split label into lines
|
362
|
+
let label = labelPrep.split(lineSeparatorChar);
|
363
|
+
|
364
|
+
// Trim lines
|
365
|
+
label = label.map(line => line.trim());
|
366
|
+
|
296
367
|
return label;
|
297
368
|
}
|
298
|
-
)
|
299
|
-
// Remove empty labels
|
300
|
-
.filter(label => label.length > 0);
|
369
|
+
);
|
301
370
|
|
302
371
|
} else {
|
303
372
|
// Export all attributes
|
304
373
|
labels = featureSet.features.map(
|
305
374
|
feature => {
|
306
|
-
return Object.
|
307
|
-
|
375
|
+
return Object.keys(feature.attributes).map(
|
376
|
+
(attributeName: string) => {
|
377
|
+
const value = _prepareAttributeValue(feature.attributes[attributeName],
|
378
|
+
attributeTypes[attributeName], attributeDomains[attributeName], intl);
|
379
|
+
return `${value}`;
|
380
|
+
}
|
308
381
|
);
|
309
382
|
}
|
310
383
|
);
|
@@ -324,14 +397,12 @@ async function _prepareLabels(
|
|
324
397
|
let headerNames = [];
|
325
398
|
|
326
399
|
if (labelFormat) {
|
327
|
-
headerNames = labelFormat.
|
400
|
+
headerNames = labelFormat.replace(/\{/g, "").replace(/\}/g, "").split(lineSeparatorChar);
|
328
401
|
|
329
402
|
} else {
|
330
403
|
const featuresAttrs = featureSet.features[0].attributes;
|
331
404
|
Object.keys(featuresAttrs).forEach(k => {
|
332
|
-
|
333
|
-
headerNames.push(k);
|
334
|
-
}
|
405
|
+
headerNames.push(k);
|
335
406
|
});
|
336
407
|
}
|
337
408
|
|