@esri/solutions-components 0.4.0 → 0.4.2

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 (76) hide show
  1. package/dist/assets/t9n/map-select-tools/resources.json +1 -1
  2. package/dist/assets/t9n/map-select-tools/resources_en.json +1 -1
  3. package/dist/assets/t9n/public-notification/resources.json +5 -5
  4. package/dist/assets/t9n/public-notification/resources_en.json +5 -5
  5. package/dist/assets/t9n/refine-selection/resources.json +3 -3
  6. package/dist/assets/t9n/refine-selection/resources_en.json +3 -3
  7. package/dist/cjs/calcite-input-message_5.cjs.entry.js +1344 -18
  8. package/dist/cjs/{calcite-input-message.calcite-notice.map-select-tools.pdf-download.refine-selection-da276a1c.js → downloadUtils-99981c6b.js} +278 -1383
  9. package/dist/cjs/{index.es-176629d8.js → index.es-53f3bc97.js} +3 -13
  10. package/dist/cjs/layer-table.cjs.entry.js +5 -15
  11. package/dist/cjs/loader.cjs.js +1 -1
  12. package/dist/cjs/public-notification.cjs.entry.js +25 -10
  13. package/dist/cjs/solutions-components.cjs.js +1 -1
  14. package/dist/collection/components/layer-table/layer-table.js +4 -16
  15. package/dist/collection/components/map-search/map-search.js +1 -1
  16. package/dist/collection/components/map-select-tools/map-select-tools.js +43 -39
  17. package/dist/collection/components/pdf-download/pdf-download.js +33 -80
  18. package/dist/collection/components/public-notification/public-notification.js +26 -11
  19. package/dist/collection/components/refine-selection/refine-selection.js +1 -1
  20. package/dist/collection/utils/csvUtils.js +4 -0
  21. package/dist/collection/utils/csvUtils.ts +7 -0
  22. package/dist/collection/utils/downloadUtils.js +254 -0
  23. package/dist/collection/utils/downloadUtils.ts +344 -0
  24. package/dist/collection/utils/interfaces.ts +3 -2
  25. package/dist/collection/utils/pdfUtils.js +7 -0
  26. package/dist/collection/utils/pdfUtils.ts +13 -2
  27. package/dist/components/downloadUtils.js +2352 -0
  28. package/dist/components/index.es.js +1 -1
  29. package/dist/components/layer-table.js +5 -16
  30. package/dist/components/map-layer-picker2.js +1 -1
  31. package/dist/components/map-search.js +1 -1
  32. package/dist/components/map-select-tools2.js +45 -41
  33. package/dist/components/pdf-download2.js +14 -2126
  34. package/dist/components/public-notification.js +26 -11
  35. package/dist/components/queryUtils.js +1 -1
  36. package/dist/components/refine-selection-tools2.js +1 -1
  37. package/dist/components/refine-selection2.js +1 -1
  38. package/dist/esm/buffer-tools_6.entry.js +1 -1
  39. package/dist/esm/calcite-combobox_3.entry.js +1 -1
  40. package/dist/esm/calcite-input-message_5.entry.js +1343 -13
  41. package/dist/esm/{calcite-input-message.calcite-notice.map-select-tools.pdf-download.refine-selection-c6f63458.js → downloadUtils-4bb47330.js} +279 -1381
  42. package/dist/esm/{index.es-54a6f3a3.js → index.es-4424d2f7.js} +2 -12
  43. package/dist/esm/layer-table.entry.js +6 -16
  44. package/dist/esm/loader.js +1 -1
  45. package/dist/esm/{mapViewUtils-63e118f8.js → mapViewUtils-02696ab6.js} +1 -1
  46. package/dist/esm/public-notification.entry.js +26 -11
  47. package/dist/esm/solutions-components.js +1 -1
  48. package/dist/solutions-components/p-0aed9b0d.js +437 -0
  49. package/dist/solutions-components/p-0d3b0fa0.entry.js +17 -0
  50. package/dist/solutions-components/{p-cc2e20c8.js → p-1bfd07e3.js} +1 -1
  51. package/dist/solutions-components/{p-117174e8.entry.js → p-335fce8c.entry.js} +1 -1
  52. package/dist/solutions-components/{p-1e459361.js → p-50117f71.js} +3 -3
  53. package/dist/solutions-components/p-5e4dfbe4.entry.js +6 -0
  54. package/dist/solutions-components/{p-8a0c0935.entry.js → p-a3b60bc9.entry.js} +1 -1
  55. package/dist/solutions-components/p-ec7f7804.entry.js +6 -0
  56. package/dist/solutions-components/solutions-components.esm.js +1 -1
  57. package/dist/solutions-components/utils/csvUtils.ts +7 -0
  58. package/dist/solutions-components/utils/downloadUtils.ts +344 -0
  59. package/dist/solutions-components/utils/interfaces.ts +3 -2
  60. package/dist/solutions-components/utils/pdfUtils.ts +13 -2
  61. package/dist/types/components/map-select-tools/map-select-tools.d.ts +12 -6
  62. package/dist/types/components/pdf-download/pdf-download.d.ts +4 -20
  63. package/dist/types/components/public-notification/public-notification.d.ts +9 -1
  64. package/dist/types/components.d.ts +4 -2
  65. package/dist/types/utils/downloadUtils.d.ts +42 -0
  66. package/dist/types/utils/interfaces.d.ts +2 -3
  67. package/dist/types/utils/pdfUtils.d.ts +3 -1
  68. package/package.json +1 -1
  69. package/dist/cjs/csvUtils-3a56c6d8.js +0 -54
  70. package/dist/components/csvUtils.js +0 -52
  71. package/dist/esm/csvUtils-23b5418f.js +0 -52
  72. package/dist/solutions-components/p-3069e3b7.js +0 -21
  73. package/dist/solutions-components/p-6d28f991.entry.js +0 -6
  74. package/dist/solutions-components/p-80f5e33c.js +0 -416
  75. package/dist/solutions-components/p-8927862a.entry.js +0 -6
  76. package/dist/solutions-components/p-e69c58e5.entry.js +0 -6
@@ -0,0 +1,344 @@
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
+
17
+ //#region Declarations
18
+
19
+ import { exportCSV } from "./csvUtils";
20
+ import { ILabel, exportPDF } from "./pdfUtils";
21
+ import { loadModules } from "./loadModules";
22
+ import { queryFeaturesByID } from "./queryUtils";
23
+
24
+ export { ILabel } from "./pdfUtils";
25
+
26
+ interface IArcadeExecutors {
27
+ [expressionName: string]: __esri.ArcadeExecutor;
28
+ }
29
+
30
+ interface IArcadeExecutorPromises {
31
+ [expressionName: string]: Promise<__esri.ArcadeExecutor>;
32
+ }
33
+
34
+ //#endregion
35
+ //#region Public functions
36
+
37
+ /**
38
+ * Downloads csv of mailing labels for the provided list of ids
39
+ *
40
+ * @param selectionSetNames Names of the selection sets used to provide ids
41
+ * @param layer Layer providing features and attributes for download
42
+ * @param ids List of ids to download
43
+ * @param formatUsingLayerPopup When true, the layer's popup is used to choose attributes for each column; when false,
44
+ * all attributes are exported
45
+ * @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
46
+ * @param addColumnTitle Indicates if column headings should be included in output
47
+ * @returns Promise resolving when function is done
48
+ */
49
+ export async function downloadCSV(
50
+ selectionSetNames: string[],
51
+ layer: __esri.FeatureLayer,
52
+ ids: number[],
53
+ formatUsingLayerPopup: boolean,
54
+ removeDuplicates = false,
55
+ addColumnTitle = false
56
+ ): Promise<void> {
57
+ console.log("downloadCSV using selectionSetNames " + JSON.stringify(selectionSetNames));//???
58
+ const labels = await _prepareLabels(layer, ids, removeDuplicates, formatUsingLayerPopup, addColumnTitle);
59
+
60
+ exportCSV(labels);
61
+
62
+ return Promise.resolve();
63
+ }
64
+
65
+ /**
66
+ * Downloads csv of mailing labels for the provided list of ids
67
+ *
68
+ * @param selectionSetNames Names of the selection sets used to provide ids
69
+ * @param layer Layer providing features and attributes for download
70
+ * @param ids List of ids to download
71
+ * @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
72
+ * @param labelPageDescription Provides PDF page layout info
73
+ * @returns Promise resolving when function is done
74
+ */
75
+ export async function downloadPDF(
76
+ selectionSetNames: string[],
77
+ layer: __esri.FeatureLayer,
78
+ ids: number[],
79
+ removeDuplicates: boolean,
80
+ labelPageDescription: ILabel
81
+ ): Promise<void> {
82
+ console.log("downloadPDF using selectionSetNames " + JSON.stringify(selectionSetNames));//???
83
+ const labels = await _prepareLabels(layer, ids, removeDuplicates);
84
+
85
+ exportPDF(labels, labelPageDescription);
86
+
87
+ return Promise.resolve();
88
+ }
89
+
90
+ //#endregion
91
+ //#region Private functions
92
+
93
+ /**
94
+ * Converts a set of fieldInfos into template lines.
95
+ *
96
+ * @param fieldInfos Layer's fieldInfos structure
97
+ * @param bypassFieldVisiblity Indicates if the configured fieldInfo visibility property should be ignored
98
+ * @return Label spec
99
+ */
100
+ function _convertPopupFieldsToLabelSpec(
101
+ fieldInfos: __esri.FieldInfo[],
102
+ bypassFieldVisiblity = false
103
+ ): string[] {
104
+ const labelSpec: string[] = [];
105
+
106
+ // Every visible attribute is used
107
+ fieldInfos.forEach(
108
+ fieldInfo => {
109
+ if (fieldInfo.visible || bypassFieldVisiblity) {
110
+ labelSpec.push(`{${fieldInfo.fieldName}}`);
111
+ }
112
+ }
113
+ );
114
+
115
+ return labelSpec;
116
+ };
117
+
118
+ /**
119
+ * Converts the text of a custom popup into a multiline label specification; conversion splits text into
120
+ * lines on <br>s, and removes HTML tags. It does not handle Arcade and related records.
121
+ *
122
+ * @param popupInfo Layer's popupInfo structure containing description, fieldInfos, and expressionInfos, e.g.,
123
+ * "<div style='text-align: left;'>{NAME}<br />{STREET}<br />{CITY}, {STATE} {ZIP} <br /></div>"
124
+ * @return Label spec
125
+ */
126
+ function _convertPopupTextToLabelSpec(
127
+ popupInfo: string
128
+ ): string[] {
129
+ // Replace <br>, <br/> with |
130
+ popupInfo = popupInfo.replace(/<br\s*\/?>/gi, "|");
131
+
132
+ // Remove remaining HTML tags, replace 0xA0 that popup uses for spaces, replace some char representations,
133
+ // and split the label back into individual lines
134
+ let labelSpec = popupInfo
135
+ .replace(/<[\s.]*[^<>]*\/?>/gi, "")
136
+ .replace(/\xA0/gi, " ")
137
+ .replace(/&lt;/gi, "<")
138
+ .replace(/&gt;/gi, ">")
139
+ .replace(/&nbsp;/gi, " ")
140
+ .split("|");
141
+
142
+ // Trim lines and remove empties
143
+ labelSpec = labelSpec.map(line => line.trim()).filter(line => line.length > 0);
144
+
145
+ return labelSpec;
146
+ };
147
+
148
+ /**
149
+ * Extracts Arcade expressions from the lines of a label format and creates an Arcade executor for each
150
+ * referenced expression name.
151
+ *
152
+ * @param labelFormat Label to examine
153
+ * @param layer Layer from which to fetch features
154
+ * @return Promise resolving to a set of executors keyed using the expression name
155
+ */
156
+ async function _createArcadeExecutors(
157
+ labelFormat: string[],
158
+ layer: __esri.FeatureLayer
159
+ ): Promise<IArcadeExecutors> {
160
+ const arcadeExecutors: IArcadeExecutors = {};
161
+
162
+ // Are any Arcade expressions in the layer?
163
+ if (!Array.isArray(layer.popupTemplate.expressionInfos) || layer.popupTemplate.expressionInfos.length === 0) {
164
+ return Promise.resolve(arcadeExecutors);
165
+ }
166
+
167
+ // Are there any Arcade expressions in the label format?
168
+ const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
169
+ const arcadeExpressionsMatches = labelFormat.join("|").match(arcadeExpressionRegExp);
170
+ if (!arcadeExpressionsMatches) {
171
+ return Promise.resolve(arcadeExecutors);
172
+ }
173
+
174
+ // Generate an Arcade executor for each match
175
+ const [arcade] = await loadModules(["esri/arcade"]);
176
+ const labelingProfile: __esri.Profile = arcade.createArcadeProfile("popup");
177
+
178
+ const createArcadeExecutorPromises: IArcadeExecutorPromises = {};
179
+ arcadeExpressionsMatches.forEach(
180
+ (match: string) => {
181
+ const expressionName = match.substring(match.indexOf("/") + 1, match.length - 1);
182
+
183
+ (layer.popupTemplate.expressionInfos || []).forEach(
184
+ expressionInfo => {
185
+ if (expressionInfo.name === expressionName) {
186
+ createArcadeExecutorPromises[expressionName] =
187
+ arcade.createArcadeExecutor(expressionInfo.expression, labelingProfile);
188
+ }
189
+ }
190
+ );
191
+ }
192
+ );
193
+
194
+ const promises = Object.values(createArcadeExecutorPromises);
195
+ return Promise.all(promises)
196
+ .then(
197
+ executors => {
198
+ const expressionNames = Object.keys(createArcadeExecutorPromises);
199
+
200
+ for (let i = 0; i < expressionNames.length; ++i) {
201
+ arcadeExecutors[expressionNames[i]] = executors[i].valueOf() as __esri.ArcadeExecutor;
202
+ }
203
+
204
+ return arcadeExecutors;
205
+ }
206
+ );
207
+ }
208
+
209
+ /**
210
+ * Creates labels from items.
211
+ *
212
+ * @param layer Layer from which to fetch features
213
+ * @param ids List of ids to download
214
+ * @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
215
+ * @param formatUsingLayerPopup When true, the layer's popup is used to choose attributes for each column; when false,
216
+ * all attributes are exported
217
+ * @param includeHeaderNames Add the label format at the front of the list of generated labels
218
+ * @returns Promise resolving when function is done
219
+ */
220
+ async function _prepareLabels(
221
+ layer: __esri.FeatureLayer,
222
+ ids: number[],
223
+ removeDuplicates = true,
224
+ formatUsingLayerPopup = true,
225
+ includeHeaderNames = false
226
+ ): Promise<string[][]> {
227
+ const [intl] = await loadModules(["esri/intl"]);
228
+
229
+ // Get the features to export
230
+ const featureSet = await queryFeaturesByID(ids, layer);
231
+
232
+ // Get the label formatting, if any
233
+ let labelFormat: string[];
234
+ let arcadeExecutors: IArcadeExecutors = {};
235
+ if (layer.popupEnabled) {
236
+ // What data fields are used in the labels?
237
+ // Example labelFormat: ['{NAME}', '{STREET}', '{CITY}, {STATE} {ZIP}']
238
+ if (formatUsingLayerPopup && layer.popupTemplate?.content[0]?.type === "fields") {
239
+ labelFormat = _convertPopupFieldsToLabelSpec(layer.popupTemplate.fieldInfos);
240
+
241
+ // If popup is configured with "no attribute information", then no fields will visible
242
+ if (labelFormat.length === 0) {
243
+ // Can we use the popup title?
244
+ // eslint-disable-next-line unicorn/prefer-ternary
245
+ if (typeof layer.popupTemplate.title === "string") {
246
+ labelFormat = [layer.popupTemplate.title];
247
+
248
+ // Otherwise revert to using attributes
249
+ } else {
250
+ labelFormat = _convertPopupFieldsToLabelSpec(layer.popupTemplate.fieldInfos, true);
251
+ }
252
+ }
253
+
254
+ } else if (formatUsingLayerPopup && layer.popupTemplate?.content[0]?.type === "text") {
255
+ labelFormat = _convertPopupTextToLabelSpec(layer.popupTemplate.content[0].text);
256
+
257
+ // Do we need any Arcade executors?
258
+ arcadeExecutors = await _createArcadeExecutors(labelFormat, layer);
259
+ }
260
+ }
261
+
262
+ // Apply the label format
263
+ let labels: string[][];
264
+ // eslint-disable-next-line unicorn/prefer-ternary
265
+ if (labelFormat) {
266
+ const arcadeExpressionRegExp = /\{expression\/\w+\}/g;
267
+
268
+ // Convert attributes into an array of labels
269
+ labels = featureSet.features.map(
270
+ feature => {
271
+ const label: string[] = [];
272
+ labelFormat.forEach(
273
+ labelLineTemplate => {
274
+ let labelLine = labelLineTemplate;
275
+
276
+ // Replace Arcade expressions
277
+ const arcadeExpressionsMatches = labelLine.match(arcadeExpressionRegExp);
278
+ if (arcadeExpressionsMatches) {
279
+ arcadeExpressionsMatches.forEach(
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
+ )
286
+ }
287
+
288
+ // Replace fields; must be done after Arcade check because `substitute` will discard Arcade expressions!
289
+ labelLine = intl.substitute(labelLine, feature.attributes).trim();
290
+
291
+ if (labelLine.length > 0) {
292
+ label.push(labelLine);
293
+ }
294
+ }
295
+ )
296
+ return label;
297
+ }
298
+ )
299
+ // Remove empty labels
300
+ .filter(label => label.length > 0);
301
+
302
+ } else {
303
+ // Export all attributes
304
+ labels = featureSet.features.map(
305
+ feature => {
306
+ return Object.values(feature.attributes).map(
307
+ attribute => `${attribute}`
308
+ );
309
+ }
310
+ );
311
+ }
312
+
313
+ // Remove duplicates
314
+ if (removeDuplicates) {
315
+ const labelsAsStrings: string[] = labels.map(label => JSON.stringify(label));
316
+ const uniqueLabels = new Set(labelsAsStrings);
317
+ labels = Array.from(uniqueLabels,
318
+ labelString => JSON.parse(labelString)
319
+ );
320
+ }
321
+
322
+ // Add header names
323
+ if (includeHeaderNames) {
324
+ let headerNames = [];
325
+
326
+ if (labelFormat) {
327
+ headerNames = labelFormat.map(labelFormatLine => labelFormatLine.replace(/\{/g, "").replace(/\}/g, ""));
328
+
329
+ } else {
330
+ const featuresAttrs = featureSet.features[0].attributes;
331
+ Object.keys(featuresAttrs).forEach(k => {
332
+ if (featuresAttrs[0].hasOwnProperty(k)) {
333
+ headerNames.push(k);
334
+ }
335
+ });
336
+ }
337
+
338
+ labels.unshift(headerNames);
339
+ }
340
+
341
+ return Promise.resolve(labels);
342
+ }
343
+
344
+ //#endregion
@@ -108,7 +108,7 @@ export interface ISearchConfiguration {
108
108
  sources: Array<ILocatorSourceConfigItem | ILayerSourceConfigItem>;
109
109
  }
110
110
 
111
- interface ISearchSourceConfigItem {
111
+ export interface ISearchSourceConfigItem {
112
112
  maxResults: number;
113
113
  maxSuggestions: number;
114
114
  minSuggestCharacters: number;
@@ -387,7 +387,8 @@ export interface ISelectionSet {
387
387
  refineIds: IRefineIds;
388
388
  redoStack?: IRefineOperation[];
389
389
  undoStack?: IRefineOperation[];
390
- skipGeomQuery?: boolean;
390
+ //skipGeomQuery?: boolean;
391
+ skipGeomOIDs?: number[];
391
392
  }
392
393
 
393
394
  export interface IRefineSelectionEvent {
@@ -18,9 +18,13 @@
18
18
  * See the License for the specific language governing permissions and
19
19
  * limitations under the License.
20
20
  */
21
+ //#region Declarations
21
22
  import * as PDFCreator_jsPDF from "../assets/arcgis-pdf-creator/PDFCreator_jsPDF";
22
23
  import * as PDFLabels from "../assets/arcgis-pdf-creator/PDFLabels";
23
24
  import { getAssetPath } from "@stencil/core";
25
+ export { ILabel } from "../assets/arcgis-pdf-creator/PDFLabels";
26
+ //#endregion
27
+ //#region Public functions
24
28
  /**
25
29
  * Exports a PDF of labels.
26
30
  *
@@ -30,6 +34,8 @@ import { getAssetPath } from "@stencil/core";
30
34
  export function exportPDF(labels, labelPageDescription) {
31
35
  _downloadPDFFile(labels, labelPageDescription, `notify-${Date.now().toString()}`);
32
36
  }
37
+ //#endregion
38
+ //#region Private functions
33
39
  /**
34
40
  * Downloads the PDF file.
35
41
  *
@@ -51,3 +57,4 @@ function _downloadPDFFile(labels, labelPageDescription, fileTitle) {
51
57
  });
52
58
  });
53
59
  }
60
+ //#endregion
@@ -14,9 +14,15 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
+ //#region Declarations
18
+
17
19
  import * as PDFCreator_jsPDF from "../assets/arcgis-pdf-creator/PDFCreator_jsPDF";
18
20
  import * as PDFLabels from "../assets/arcgis-pdf-creator/PDFLabels";
19
21
  import { getAssetPath } from "@stencil/core";
22
+ export { ILabel } from "../assets/arcgis-pdf-creator/PDFLabels";
23
+
24
+ //#endregion
25
+ //#region Public functions
20
26
 
21
27
  /**
22
28
  * Exports a PDF of labels.
@@ -26,11 +32,14 @@ import { getAssetPath } from "@stencil/core";
26
32
  */
27
33
  export function exportPDF(
28
34
  labels: string[][],
29
- labelPageDescription: any
35
+ labelPageDescription: PDFLabels.ILabel
30
36
  ): void {
31
37
  _downloadPDFFile(labels, labelPageDescription, `notify-${Date.now().toString()}`);
32
38
  }
33
39
 
40
+ //#endregion
41
+ //#region Private functions
42
+
34
43
  /**
35
44
  * Downloads the PDF file.
36
45
  *
@@ -40,7 +49,7 @@ export function exportPDF(
40
49
  */
41
50
  function _downloadPDFFile(
42
51
  labels: string[][],
43
- labelPageDescription: any,
52
+ labelPageDescription: PDFLabels.ILabel,
44
53
  fileTitle: string
45
54
  ): void {
46
55
  const pdfLib = new PDFCreator_jsPDF.PDFCreator_jsPDF();
@@ -69,3 +78,5 @@ function _downloadPDFFile(
69
78
  );
70
79
 
71
80
  }
81
+
82
+ //#endregion