@esri/solutions-components 0.5.3 → 0.5.4

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.
Files changed (116) hide show
  1. package/dist/cjs/calcite-input-text_5.cjs.entry.js +36 -36
  2. package/dist/cjs/calcite-shell-panel_14.cjs.entry.js +1 -1
  3. package/dist/cjs/solution-configuration.cjs.entry.js +1 -1
  4. package/dist/cjs/solution-contents_3.cjs.entry.js +1 -1
  5. package/dist/cjs/{solution-store-70002b57.js → solution-store-ca4639d5.js} +3 -3
  6. package/dist/collection/components/add-record-modal/test/add-record-modal.e2e.js +24 -0
  7. package/dist/collection/components/add-record-modal/test/add-record-modal.spec.js +32 -0
  8. package/dist/collection/components/buffer-tools/test/buffer-tools.e2e.js +24 -0
  9. package/dist/collection/components/buffer-tools/test/buffer-tools.spec.js +157 -0
  10. package/dist/collection/components/card-manager/test/card-manager.e2e.js +24 -0
  11. package/dist/collection/components/card-manager/test/card-manager.spec.js +32 -0
  12. package/dist/collection/components/comment-card/test/comment-card.e2e.js +24 -0
  13. package/dist/collection/components/comment-card/test/comment-card.spec.js +32 -0
  14. package/dist/collection/components/crowdsource-manager/test/crowdsource-manager.e2e.js +24 -0
  15. package/dist/collection/components/crowdsource-manager/test/crowdsource-manager.spec.js +32 -0
  16. package/dist/collection/components/crowdsource-reporter/test/crowdsource-reporter.e2e.js +24 -0
  17. package/dist/collection/components/crowdsource-reporter/test/crowdsource-reporter.spec.js +32 -0
  18. package/dist/collection/components/deduct-calculator/test/deduct-calculator.e2e.js +24 -0
  19. package/dist/collection/components/deduct-calculator/test/deduct-calculator.spec.js +32 -0
  20. package/dist/collection/components/edit-record-modal/test/edit-record-modal.e2e.js +24 -0
  21. package/dist/collection/components/edit-record-modal/test/edit-record-modal.spec.js +32 -0
  22. package/dist/collection/components/info-card/test/info-card.e2e.js +24 -0
  23. package/dist/collection/components/info-card/test/info-card.spec.js +32 -0
  24. package/dist/collection/components/json-editor/test/json-editor.e2e.js +31 -0
  25. package/dist/collection/components/json-editor/test/json-editor.spec.js +60 -0
  26. package/dist/collection/components/layer-table/test/layer-table.e2e.js +24 -0
  27. package/dist/collection/components/layer-table/test/layer-table.spec.js +32 -0
  28. package/dist/collection/components/list-item/test/list-item.e2e.js +24 -0
  29. package/dist/collection/components/list-item/test/list-item.spec.js +32 -0
  30. package/dist/collection/components/map-card/test/map-card.e2e.js +24 -0
  31. package/dist/collection/components/map-card/test/map-card.spec.js +32 -0
  32. package/dist/collection/components/map-draw-tools/test/map-draw-tools.e2e.js +24 -0
  33. package/dist/collection/components/map-draw-tools/test/map-draw-tools.spec.js +32 -0
  34. package/dist/collection/components/map-layer-picker/test/map-layer-picker.e2e.js +24 -0
  35. package/dist/collection/components/map-layer-picker/test/map-layer-picker.spec.js +109 -0
  36. package/dist/collection/components/map-search/test/map-search.e2e.js +24 -0
  37. package/dist/collection/components/map-search/test/map-search.spec.js +53 -0
  38. package/dist/collection/components/map-select-tools/map-select-tools.js +36 -36
  39. package/dist/collection/components/map-select-tools/test/map-select-tools.e2e.js +24 -0
  40. package/dist/collection/components/map-select-tools/test/map-select-tools.spec.js +349 -0
  41. package/dist/collection/components/media-card/test/media-card.e2e.js +24 -0
  42. package/dist/collection/components/media-card/test/media-card.spec.js +32 -0
  43. package/dist/collection/components/pci-calculator/test/pci-calculator.e2e.js +24 -0
  44. package/dist/collection/components/pci-calculator/test/pci-calculator.spec.js +32 -0
  45. package/dist/collection/components/pdf-download/test/pdf-download.e2e.js +71 -0
  46. package/dist/collection/components/pdf-download/test/pdf-download.spec.js +104 -0
  47. package/dist/collection/components/public-notification/test/public-notification.e2e.js +95 -0
  48. package/dist/collection/components/public-notification/test/public-notification.spec.js +149 -0
  49. package/dist/collection/components/refine-selection/refine-selection.css +85 -85
  50. package/dist/collection/components/solution-configuration/test/solution-configuration.e2e.js +31 -0
  51. package/dist/collection/components/solution-configuration/test/solution-configuration.spec.js +114 -0
  52. package/dist/collection/components/solution-contents/test/solution-contents.e2e.js +89 -0
  53. package/dist/collection/components/solution-contents/test/solution-contents.spec.js +138 -0
  54. package/dist/collection/components/solution-item/test/solution-item.e2e.js +31 -0
  55. package/dist/collection/components/solution-item/test/solution-item.spec.js +72 -0
  56. package/dist/collection/components/solution-item-details/test/solution-item-details.e2e.js +31 -0
  57. package/dist/collection/components/solution-item-details/test/solution-item-details.spec.js +137 -0
  58. package/dist/collection/components/solution-item-icon/test/solution-item-icon.e2e.js +24 -0
  59. package/dist/collection/components/solution-item-icon/test/solution-item-icon.spec.js +34 -0
  60. package/dist/collection/components/solution-item-sharing/test/solution-item-sharing.e2e.js +31 -0
  61. package/dist/collection/components/solution-item-sharing/test/solution-item-sharing.spec.js +49 -0
  62. package/dist/collection/components/solution-organization-variables/test/solution-organization-variables.e2e.js +31 -0
  63. package/dist/collection/components/solution-organization-variables/test/solution-organization-variables.spec.js +60 -0
  64. package/dist/collection/components/solution-resource-item/test/solution-resource-item.e2e.js +31 -0
  65. package/dist/collection/components/solution-resource-item/test/solution-resource-item.spec.js +50 -0
  66. package/dist/collection/components/solution-spatial-ref/test/solution-spatial-ref.e2e.js +31 -0
  67. package/dist/collection/components/solution-spatial-ref/test/solution-spatial-ref.spec.js +170 -0
  68. package/dist/collection/components/solution-template-data/test/solution-template-data.e2e.js +31 -0
  69. package/dist/collection/components/solution-template-data/test/solution-template-data.spec.js +55 -0
  70. package/dist/collection/components/solution-variables/test/solution-variables.e2e.js +31 -0
  71. package/dist/collection/components/solution-variables/test/solution-variables.spec.js +126 -0
  72. package/dist/collection/utils/publicNotificationUtils.js +45 -0
  73. package/dist/collection/utils/templates.e2e.js +25 -0
  74. package/dist/collection/utils/test/csvUtils.spec.js +46 -0
  75. package/dist/collection/utils/test/downloadUtils.spec.js +102 -0
  76. package/dist/collection/utils/test/pciUtils.spec.js +297 -0
  77. package/dist/collection/utils/test/solution-store.spec.js +439 -0
  78. package/dist/components/map-select-tools2.js +36 -36
  79. package/dist/components/solution-store.js +3 -3
  80. package/dist/esm/calcite-input-text_5.entry.js +36 -36
  81. package/dist/esm/calcite-shell-panel_14.entry.js +1 -1
  82. package/dist/esm/solution-configuration.entry.js +1 -1
  83. package/dist/esm/solution-contents_3.entry.js +1 -1
  84. package/dist/esm/{solution-store-5d068b07.js → solution-store-70f874f8.js} +3 -3
  85. package/dist/solutions-components/{p-41802f6b.entry.js → p-16dfb254.entry.js} +1 -1
  86. package/dist/solutions-components/{p-4769a2a5.entry.js → p-5ed755a2.entry.js} +1 -1
  87. package/dist/solutions-components/{p-826a814d.js → p-78719506.js} +2 -2
  88. package/dist/solutions-components/{p-9f620303.entry.js → p-b4b19fd3.entry.js} +1 -1
  89. package/dist/solutions-components/{p-24fe6e1c.entry.js → p-d5d5942d.entry.js} +1 -1
  90. package/dist/solutions-components/solutions-components.esm.js +1 -1
  91. package/dist/solutions-components/utils/common.js +291 -0
  92. package/dist/solutions-components/utils/csvDownload.js +36 -0
  93. package/dist/solutions-components/utils/csvUtils.js +32 -0
  94. package/dist/solutions-components/utils/downloadUtils.js +386 -0
  95. package/dist/solutions-components/utils/interfaces.js +56 -0
  96. package/dist/solutions-components/utils/languageUtil.js +85 -0
  97. package/dist/solutions-components/utils/loadModules.js +20 -0
  98. package/dist/solutions-components/utils/locale.js +56 -0
  99. package/dist/solutions-components/utils/mapViewUtils.js +140 -0
  100. package/dist/solutions-components/utils/pciUtils.js +837 -0
  101. package/dist/solutions-components/utils/pdfUtils.js +62 -0
  102. package/dist/solutions-components/utils/publicNotificationStore.js +38 -0
  103. package/dist/solutions-components/utils/publicNotificationUtils.js +45 -0
  104. package/dist/solutions-components/utils/queryUtils.js +148 -0
  105. package/dist/solutions-components/utils/solution-store.js +579 -0
  106. package/dist/solutions-components/utils/templates.e2e.js +25 -0
  107. package/dist/solutions-components/utils/templates.js +341 -0
  108. package/dist/solutions-components/utils/test/csvUtils.spec.js +46 -0
  109. package/dist/solutions-components/utils/test/downloadUtils.spec.js +102 -0
  110. package/dist/solutions-components/utils/test/mocks/jsApi.js +74 -0
  111. package/dist/solutions-components/utils/test/pciUtils.spec.js +297 -0
  112. package/dist/solutions-components/utils/test/solution-store.spec.js +439 -0
  113. package/dist/solutions-components/utils/test/testUtils.js +135 -0
  114. package/dist/solutions-components/utils/types.js +14 -0
  115. package/dist/solutions-components_commit.txt +7 -0
  116. package/package.json +7 -7
@@ -0,0 +1,386 @@
1
+ /** @license
2
+ * Copyright 2022 Esri
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ //#region Declarations
17
+ import { exportCSV } from "./csvUtils";
18
+ import { exportPDF } from "./pdfUtils";
19
+ import { loadModules } from "./loadModules";
20
+ import { queryFeaturesByID } from "./queryUtils";
21
+ export { ILabel } from "./pdfUtils";
22
+ const lineSeparatorChar = "|";
23
+ //#endregion
24
+ //#region Public functions
25
+ /**
26
+ * Downloads csv of mailing labels for the provided list of ids
27
+ *
28
+ * @param selectionSetNames Names of the selection sets used to provide ids
29
+ * @param layer Layer providing features and attributes for download
30
+ * @param ids List of ids to download
31
+ * @param formatUsingLayerPopup When true, the layer's popup is used to choose attributes for each column; when false,
32
+ * all attributes are exported
33
+ * @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
34
+ * @param addColumnTitle Indicates if column headings should be included in output
35
+ * @returns Promise resolving when function is done
36
+ */
37
+ export async function downloadCSV(selectionSetNames, layer, ids, formatUsingLayerPopup, removeDuplicates = false, addColumnTitle = false) {
38
+ const labels = await _prepareLabels(layer, ids, removeDuplicates, formatUsingLayerPopup, addColumnTitle);
39
+ exportCSV(_createFilename(selectionSetNames), labels);
40
+ return Promise.resolve();
41
+ }
42
+ /**
43
+ * Downloads csv of mailing labels for the provided list of ids
44
+ *
45
+ * @param selectionSetNames Names of the selection sets used to provide ids
46
+ * @param layer Layer providing features and attributes for download
47
+ * @param ids List of ids to download
48
+ * @param labelPageDescription Provides PDF page layout info
49
+ * @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
50
+ * @param includeMap When true, the first page of the output is a map showing the selection area
51
+ * @param includeTitle When true, a title is included on every page
52
+ * @param title Title for each page when `includeTitle` is true
53
+ * @returns Promise resolving when function is done
54
+ */
55
+ export async function downloadPDF(selectionSetNames, layer, ids, labelPageDescription, removeDuplicates = false, includeMap = false, includeTitle = false, title = "") {
56
+ let labels = await _prepareLabels(layer, ids, removeDuplicates);
57
+ labels =
58
+ // Remove empty lines in labels
59
+ labels.map(labelLines => labelLines.filter(line => line.length > 0))
60
+ // Remove empty labels
61
+ .filter(label => label.length > 0);
62
+ exportPDF(_createFilename(selectionSetNames), labels, labelPageDescription, includeMap, includeTitle, title);
63
+ return Promise.resolve();
64
+ }
65
+ //#endregion
66
+ //#region Private functions
67
+ /**
68
+ * Converts a set of fieldInfos into template lines.
69
+ *
70
+ * @param fieldInfos Layer's fieldInfos structure
71
+ * @param bypassFieldVisiblity Indicates if the configured fieldInfo visibility property should be ignored
72
+ * @return Label spec with lines separated by `lineSeparatorChar`
73
+ */
74
+ export function _convertPopupFieldsToLabelSpec(fieldInfos, bypassFieldVisiblity = false) {
75
+ const labelSpec = [];
76
+ // Every visible attribute is used
77
+ fieldInfos.forEach(fieldInfo => {
78
+ if (fieldInfo.visible || bypassFieldVisiblity) {
79
+ labelSpec.push(`{${fieldInfo.fieldName}}`);
80
+ }
81
+ });
82
+ return labelSpec.join(lineSeparatorChar);
83
+ }
84
+ ;
85
+ /**
86
+ * Converts the text of a custom popup into a multiline label specification; conversion splits text into
87
+ * lines on <br>s, and removes HTML tags. It does not handle Arcade and related records.
88
+ *
89
+ * @param popupInfo Layer's popupInfo structure containing description, fieldInfos, and expressionInfos, e.g.,
90
+ * "<div style='text-align: left;'>{NAME}<br />{STREET}<br />{CITY}, {STATE} {ZIP} <br /></div>"
91
+ * @return Label spec with lines separated by `lineSeparatorChar`
92
+ */
93
+ export function _convertPopupTextToLabelSpec(popupInfo) {
94
+ // Replace <br> variants with the line separator character
95
+ popupInfo = popupInfo.replace(/<br\s*\/?>/gi, lineSeparatorChar);
96
+ // Replace <p> variants with the line separator character, except in the first position
97
+ popupInfo = popupInfo.replace(/<p[^>]*>/gi, lineSeparatorChar).trim().replace(/^\|/, "");
98
+ // Remove </p>
99
+ popupInfo = popupInfo.replace(/<\/p>/gi, "");
100
+ // Replace \n with the line separator character
101
+ popupInfo = popupInfo.replace(/\n/gi, "|");
102
+ // Remove remaining HTML tags, replace 0xA0 that popup uses for spaces, and replace some char representations
103
+ let labelSpec = popupInfo
104
+ .replace(/<[\s.]*[^<>]*\/?>/gi, "")
105
+ .replace(/\xA0/gi, " ")
106
+ .replace(/&lt;/gi, "<")
107
+ .replace(/&gt;/gi, ">")
108
+ .replace(/&nbsp;/gi, " ");
109
+ // Trim each line
110
+ labelSpec = labelSpec.replace(/\s*\|\s*/g, "|");
111
+ // Remove empty lines
112
+ while (labelSpec.match(/\|\|/)) {
113
+ labelSpec = labelSpec.replace(/\|\|/, "|");
114
+ }
115
+ // Remove leading and trailing line feeds
116
+ labelSpec = labelSpec.replace(/^\|/, "");
117
+ labelSpec = labelSpec.replace(/\|$/, "");
118
+ return labelSpec.trim();
119
+ }
120
+ ;
121
+ /**
122
+ * Extracts Arcade expressions from the lines of a label format and creates an Arcade executor for each
123
+ * referenced expression name.
124
+ *
125
+ * @param labelFormat Label to examine
126
+ * @param layer Layer from which to fetch features
127
+ * @return Promise resolving to a set of executors keyed using the expression name
128
+ */
129
+ async function _createArcadeExecutors(labelFormat, layer) {
130
+ const arcadeExecutors = {};
131
+ // Are any Arcade expressions in the layer?
132
+ if (!Array.isArray(layer.popupTemplate.expressionInfos) || layer.popupTemplate.expressionInfos.length === 0) {
133
+ return Promise.resolve(arcadeExecutors);
134
+ }
135
+ // Are there any Arcade expressions in the label format?
136
+ const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
137
+ const arcadeExpressionsMatches = labelFormat.match(arcadeExpressionRegExp);
138
+ if (!arcadeExpressionsMatches) {
139
+ return Promise.resolve(arcadeExecutors);
140
+ }
141
+ // Generate an Arcade executor for each match
142
+ const [arcade] = await loadModules(["esri/arcade"]);
143
+ const labelingProfile = {
144
+ variables: [
145
+ {
146
+ name: "$feature",
147
+ type: "feature"
148
+ },
149
+ {
150
+ name: "$layer",
151
+ type: "featureSet"
152
+ },
153
+ {
154
+ name: "$datastore",
155
+ type: "featureSetCollection"
156
+ },
157
+ {
158
+ name: "$map",
159
+ type: "featureSetCollection"
160
+ }
161
+ ]
162
+ };
163
+ const createArcadeExecutorPromises = {};
164
+ arcadeExpressionsMatches.forEach((match) => {
165
+ const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
166
+ (layer.popupTemplate.expressionInfos || []).forEach(expressionInfo => {
167
+ if (expressionInfo.name === expressionName) {
168
+ createArcadeExecutorPromises[expressionName] =
169
+ arcade.createArcadeExecutor(expressionInfo.expression, labelingProfile);
170
+ }
171
+ });
172
+ });
173
+ const promises = Object.values(createArcadeExecutorPromises);
174
+ return Promise.all(promises)
175
+ .then(executors => {
176
+ const expressionNames = Object.keys(createArcadeExecutorPromises);
177
+ for (let i = 0; i < expressionNames.length; ++i) {
178
+ arcadeExecutors[expressionNames[i]] = executors[i].valueOf();
179
+ }
180
+ return arcadeExecutors;
181
+ });
182
+ }
183
+ /**
184
+ * Creates a title from a list of selection set names.
185
+ *
186
+ * @param selectionSetNames Names to use in title
187
+ * @return Title composed of the selectionSetNames separated by commas; if there are no
188
+ * selection set names supplied, "download" is returned
189
+ */
190
+ export function _createFilename(selectionSetNames) {
191
+ // Windows doesn't permit the characters \/:*?"<>|
192
+ const title = selectionSetNames.length > 0 ? selectionSetNames.join(", ") : "download";
193
+ return title;
194
+ }
195
+ /**
196
+ * Prepares an attribute's value by applying domain and type information.
197
+ *
198
+ * @param attributeValue Value of attribute
199
+ * @param attributeType Type of attribute
200
+ * @param attributeDomain Domain info for attribute, if any
201
+ * @param attributeFormat Format info for attribute, if any
202
+ * @param intl esri/intl
203
+ * @return Attribute value modified appropriate to domain and type
204
+ */
205
+ function _prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl) {
206
+ if (attributeDomain && attributeDomain.type === "coded-value") {
207
+ // "coded-value" domain field
208
+ const value = attributeDomain.getName(attributeValue);
209
+ return value;
210
+ }
211
+ else {
212
+ // Non-domain field or unsupported domain type
213
+ let value = attributeValue;
214
+ switch (attributeType) {
215
+ case "date":
216
+ if (attributeFormat === null || attributeFormat === void 0 ? void 0 : attributeFormat.dateFormat) {
217
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat);
218
+ value = intl.formatDate(value, dateFormatIntlOptions);
219
+ }
220
+ else {
221
+ value = intl.formatDate(value);
222
+ }
223
+ // Format date produces odd characters for the space between the time and the AM/PM text,
224
+ // e.g., "12/31/1969, 4:00 PM"
225
+ value = value.replace(/\xe2\x80\xaf/g, "");
226
+ break;
227
+ case "double":
228
+ case "integer":
229
+ case "long":
230
+ case "small-integer":
231
+ if (attributeFormat) {
232
+ const numberFormatIntlOptions = intl.convertNumberFormatToIntlOptions(attributeFormat);
233
+ value = intl.formatNumber(value, numberFormatIntlOptions);
234
+ }
235
+ else {
236
+ value = intl.formatNumber(value);
237
+ }
238
+ break;
239
+ }
240
+ return value;
241
+ }
242
+ }
243
+ /**
244
+ * Creates labels from items.
245
+ *
246
+ * @param layer Layer from which to fetch features
247
+ * @param ids List of ids to download
248
+ * @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
249
+ * @param formatUsingLayerPopup When true, the layer's popup is used to choose attributes for each column; when false,
250
+ * all attributes are exported
251
+ * @param includeHeaderNames Add the label format at the front of the list of generated labels
252
+ * @returns Promise resolving when function is done
253
+ */
254
+ async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLayerPopup = true, includeHeaderNames = false) {
255
+ var _a, _b, _c, _d;
256
+ const [intl] = await loadModules(["esri/intl"]);
257
+ // Get the features to export
258
+ const featureSet = await queryFeaturesByID(ids, layer);
259
+ let features = featureSet.features;
260
+ if (!removeDuplicates && ids.length > features.length) {
261
+ const oidField = layer.objectIdField;
262
+ features = featureSet.features.reduce((prev, cur) => {
263
+ const id = cur.attributes[oidField];
264
+ // remove the first instance of the id
265
+ const i = ids.indexOf(id);
266
+ if (i > -1) {
267
+ ids = ids.splice(i, 1);
268
+ }
269
+ // add the first instance of the feature to the new array
270
+ prev.push(cur);
271
+ // test for any duplicates
272
+ if (ids.indexOf(id) > -1) {
273
+ // could be more than once..
274
+ const _ids = ids.filter(_id => _id !== id);
275
+ const num = ids.length - _ids.length;
276
+ for (let _i = 0; _i < num; _i++) {
277
+ prev.push(cur);
278
+ }
279
+ ids = _ids;
280
+ }
281
+ return prev;
282
+ }, []);
283
+ }
284
+ // Get field data types. Do we have any domain-based fields?
285
+ const attributeTypes = {};
286
+ const attributeDomains = {};
287
+ layer.fields.forEach(field => {
288
+ attributeTypes[field.name] = field.type;
289
+ attributeDomains[field.name] = field.domain;
290
+ });
291
+ const attributeFormats = {};
292
+ // Get the label formatting, if any
293
+ let labelFormat;
294
+ let arcadeExecutors = {};
295
+ if (layer.popupEnabled) {
296
+ layer.popupTemplate.fieldInfos.forEach(
297
+ // Extract any format info that we have
298
+ fieldInfo => {
299
+ if (fieldInfo.format) {
300
+ attributeFormats[fieldInfo.fieldName] = fieldInfo.format;
301
+ }
302
+ });
303
+ // What data fields are used in the labels?
304
+ // Example labelFormat: ['{NAME}', '{STREET}', '{CITY}, {STATE} {ZIP}']
305
+ if (formatUsingLayerPopup && ((_b = (_a = layer.popupTemplate) === null || _a === void 0 ? void 0 : _a.content[0]) === null || _b === void 0 ? void 0 : _b.type) === "fields") {
306
+ labelFormat = _convertPopupFieldsToLabelSpec(layer.popupTemplate.fieldInfos);
307
+ // If popup is configured with "no attribute information", then no fields will visible
308
+ if (labelFormat.length === 0) {
309
+ // Can we use the popup title?
310
+ // eslint-disable-next-line unicorn/prefer-ternary
311
+ if (typeof layer.popupTemplate.title === "string") {
312
+ labelFormat = layer.popupTemplate.title;
313
+ // Otherwise revert to using attributes
314
+ }
315
+ else {
316
+ labelFormat = _convertPopupFieldsToLabelSpec(layer.popupTemplate.fieldInfos, true);
317
+ }
318
+ }
319
+ }
320
+ 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") {
321
+ labelFormat = _convertPopupTextToLabelSpec(layer.popupTemplate.content[0].text);
322
+ // Do we need any Arcade executors?
323
+ arcadeExecutors = await _createArcadeExecutors(labelFormat, layer);
324
+ }
325
+ }
326
+ // Apply the label format
327
+ let labels;
328
+ // eslint-disable-next-line unicorn/prefer-ternary
329
+ if (labelFormat) {
330
+ const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
331
+ const attributeRegExp = /\{\w+\}/g;
332
+ // Find the label fields that we need to replace with values
333
+ const arcadeExpressionMatches = labelFormat.match(arcadeExpressionRegExp);
334
+ const attributeMatches = labelFormat.match(attributeRegExp);
335
+ // Convert feature attributes into an array of labels
336
+ labels = features.map(feature => {
337
+ let labelPrep = labelFormat;
338
+ // Replace Arcade expressions
339
+ if (arcadeExpressionMatches) {
340
+ arcadeExpressionMatches.forEach((match) => {
341
+ const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
342
+ const value = arcadeExecutors[expressionName].execute({ "$feature": feature });
343
+ labelPrep = labelPrep.replace(match, value);
344
+ });
345
+ }
346
+ // Replace non-Arcade fields
347
+ if (attributeMatches) {
348
+ attributeMatches.forEach((match) => {
349
+ const attributeName = match.substring(1, match.length - 1);
350
+ const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], attributeFormats[attributeName], intl);
351
+ labelPrep = labelPrep.replace(match, value);
352
+ });
353
+ }
354
+ // Split label into lines
355
+ let label = labelPrep.split(lineSeparatorChar);
356
+ // Trim lines
357
+ label = label.map(line => line.trim());
358
+ return label;
359
+ });
360
+ }
361
+ else {
362
+ // Export all attributes
363
+ labels = features.map(feature => {
364
+ return Object.keys(feature.attributes).map((attributeName) => {
365
+ const value = _prepareAttributeValue(feature.attributes[attributeName], attributeTypes[attributeName], attributeDomains[attributeName], null, intl);
366
+ return `${value}`;
367
+ });
368
+ });
369
+ }
370
+ // Add header names
371
+ if (includeHeaderNames) {
372
+ let headerNames = [];
373
+ if (labelFormat) {
374
+ headerNames = labelFormat.replace(/\{/g, "").replace(/\}/g, "").split(lineSeparatorChar);
375
+ }
376
+ else {
377
+ const featuresAttrs = features[0].attributes;
378
+ Object.keys(featuresAttrs).forEach(k => {
379
+ headerNames.push(k);
380
+ });
381
+ }
382
+ labels.unshift(headerNames);
383
+ }
384
+ return Promise.resolve(labels);
385
+ }
386
+ //#endregion
@@ -0,0 +1,56 @@
1
+ /** @license
2
+ * Copyright 2022 Esri
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export var ELayoutMode;
17
+ (function (ELayoutMode) {
18
+ ELayoutMode["GRID"] = "GRID";
19
+ ELayoutMode["HORIZONTAL"] = "HORIZONTAL";
20
+ ELayoutMode["VERTICAL"] = "VERTICAL";
21
+ })(ELayoutMode || (ELayoutMode = {}));
22
+ /**
23
+ * Resource update types
24
+ */
25
+ export var EUpdateType;
26
+ (function (EUpdateType) {
27
+ EUpdateType[EUpdateType["Add"] = 0] = "Add";
28
+ EUpdateType[EUpdateType["Update"] = 1] = "Update";
29
+ EUpdateType[EUpdateType["Remove"] = 2] = "Remove";
30
+ EUpdateType[EUpdateType["None"] = 3] = "None";
31
+ EUpdateType[EUpdateType["Obsolete"] = 4] = "Obsolete";
32
+ })(EUpdateType || (EUpdateType = {}));
33
+ export var EPageType;
34
+ (function (EPageType) {
35
+ EPageType[EPageType["LIST"] = 0] = "LIST";
36
+ EPageType[EPageType["SELECT"] = 1] = "SELECT";
37
+ EPageType[EPageType["EXPORT"] = 2] = "EXPORT";
38
+ })(EPageType || (EPageType = {}));
39
+ export var ESelectionType;
40
+ (function (ESelectionType) {
41
+ ESelectionType["POINT"] = "POINT";
42
+ ESelectionType["LINE"] = "LINE";
43
+ ESelectionType["POLY"] = "POLY";
44
+ ESelectionType["RECT"] = "RECT";
45
+ })(ESelectionType || (ESelectionType = {}));
46
+ export var EExpandType;
47
+ (function (EExpandType) {
48
+ EExpandType["EXPAND"] = "EXPAND";
49
+ EExpandType["COLLAPSE"] = "COLLAPSE";
50
+ })(EExpandType || (EExpandType = {}));
51
+ export var EWorkflowType;
52
+ (function (EWorkflowType) {
53
+ EWorkflowType["SEARCH"] = "SEARCH";
54
+ EWorkflowType["SELECT"] = "SELECT";
55
+ EWorkflowType["SKETCH"] = "SKETCH";
56
+ })(EWorkflowType || (EWorkflowType = {}));
@@ -0,0 +1,85 @@
1
+ /*
2
+ * Copyright (c) 2022 Esri
3
+ * All rights reserved.
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+ import { loadModules } from "./loadModules";
15
+ export const languageMap = new Map([
16
+ ["ar", "ar"],
17
+ ["bg", "bg"],
18
+ ["bs", "bs"],
19
+ ["ca", "ca"],
20
+ ["cs", "cs"],
21
+ ["da", "da"],
22
+ ["de", "de"],
23
+ ["el", "el"],
24
+ ["en", "en"],
25
+ ["es", "es"],
26
+ ["et", "et"],
27
+ ["fi", "fi"],
28
+ ["fr", "fr"],
29
+ ["he", "he"],
30
+ ["hr", "hr"],
31
+ ["hu", "hu"],
32
+ ["id", "id"],
33
+ ["it", "it"],
34
+ ["ja", "ja"],
35
+ ["ko", "ko"],
36
+ ["lt", "lt"],
37
+ ["lv", "lv"],
38
+ ["nb", "nb"],
39
+ ["nl", "nl"],
40
+ ["pl", "pl"],
41
+ ["pt-br", "pt-BR"],
42
+ ["pt-pt", "pt-PT"],
43
+ ["ro", "ro"],
44
+ ["ru", "ru"],
45
+ ["sk", "sk"],
46
+ ["sl", "sl"],
47
+ ["sr", "sr"],
48
+ ["sv", "sv"],
49
+ ["th", "th"],
50
+ ["tr", "tr"],
51
+ ["uk", "uk"],
52
+ ["vi", "vi"],
53
+ ["zh-cn", "zh-CN"],
54
+ ["zh-hk", "zh-HK"],
55
+ ["zh-tw", "zh-TW"],
56
+ ]);
57
+ // rtl
58
+ export function getElementDir(el) {
59
+ return getElementProp(el, "dir", "ltr");
60
+ }
61
+ function getElementProp(el, prop, value) {
62
+ const closestWithProp = el.closest(`[${prop}]`);
63
+ return closestWithProp ? closestWithProp.getAttribute(prop) : value;
64
+ }
65
+ // css
66
+ export const CSS_UTILITY = {
67
+ rtl: "arcgis--rtl",
68
+ };
69
+ export async function formatNumber(number, options) {
70
+ const { api = 4, type = "decimal", places = 2 } = options || {};
71
+ if (api === 4) {
72
+ const [intl] = await loadModules(["esri/intl"]);
73
+ const numberFormatIntlOptions = intl.convertNumberFormatToIntlOptions({
74
+ places,
75
+ type,
76
+ digitSeparator: true,
77
+ });
78
+ return intl.formatNumber(number, numberFormatIntlOptions);
79
+ }
80
+ const [dojoNumber] = await loadModules(["dojo/number"]);
81
+ return dojoNumber.format(number, {
82
+ type,
83
+ places,
84
+ });
85
+ }
@@ -0,0 +1,20 @@
1
+ /** @license
2
+ * Copyright 2022 Esri
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { loadModules as _loadModules } from "esri-loader";
17
+ export const loadModules = async (moduleNames, options) => {
18
+ const mods = await _loadModules(moduleNames, options);
19
+ return mods.map((mod) => (mod.__esModule && mod.default ? mod.default : mod));
20
+ };
@@ -0,0 +1,56 @@
1
+ /** @license
2
+ * Copyright 2022 Esri
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ // https://medium.com/stencil-tricks/implementing-internationalisation-i18n-with-stencil-5e6559554117
17
+ import { languageMap } from "./languageUtil";
18
+ import { getAssetPath } from "@stencil/core";
19
+ export function getComponentClosestLanguage(element) {
20
+ var _a, _b, _c;
21
+ const closestElement = (_a = (element.closest("[lang]"))) !== null && _a !== void 0 ? _a : (_c = (_b = element.shadowRoot) === null || _b === void 0 ? void 0 : _b.ownerDocument) === null || _c === void 0 ? void 0 : _c.documentElement;
22
+ // language set by the calling application or browser. defaults to english.
23
+ const lang = ((closestElement === null || closestElement === void 0 ? void 0 : closestElement.lang) || (navigator === null || navigator === void 0 ? void 0 : navigator.language) || "en").toLowerCase();
24
+ if (languageMap.has(lang)) {
25
+ return languageMap.get(lang);
26
+ }
27
+ else {
28
+ // "ru-RU" maps to "ru" use case
29
+ return languageMap.has(lang.slice(0, 2)) ? languageMap.get(lang.slice(0, 2)) : "en";
30
+ }
31
+ }
32
+ function fetchLocaleStringsForComponent(componentName, locale) {
33
+ return new Promise((resolve, reject) => {
34
+ fetch(getAssetPath(`../assets/t9n/${componentName}/resources_${locale}.json`)).then(result => {
35
+ if (result.ok) {
36
+ resolve(result.json());
37
+ }
38
+ else {
39
+ reject();
40
+ }
41
+ }, () => reject());
42
+ });
43
+ }
44
+ export async function getLocaleComponentStrings(element) {
45
+ const componentName = element.tagName.toLowerCase();
46
+ const componentLanguage = getComponentClosestLanguage(element);
47
+ let strings;
48
+ try {
49
+ strings = await fetchLocaleStringsForComponent(componentName, componentLanguage);
50
+ }
51
+ catch (e) {
52
+ console.warn(`no locale for ${componentName} (${componentLanguage}) loading default locale en.`);
53
+ strings = await fetchLocaleStringsForComponent(componentName, "en");
54
+ }
55
+ return [strings, componentLanguage];
56
+ }