@esri/solutions-components 0.3.9 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/assets/t9n/public-notification/resources.json +0 -2
- package/dist/assets/t9n/public-notification/resources_en.json +0 -2
- package/dist/cjs/buffer-tools_6.cjs.entry.js +5 -2
- package/dist/cjs/calcite-input-message_5.cjs.entry.js +1342 -18
- package/dist/cjs/{calcite-input-message.calcite-notice.map-select-tools.pdf-download.refine-selection-cd8ad61e.js → downloadUtils-27dbd8b9.js} +205 -1337
- package/dist/cjs/{index.es-e89ba2a1.js → index.es-40d341ed.js} +3 -13
- package/dist/cjs/layer-table.cjs.entry.js +5 -15
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/public-notification.cjs.entry.js +23 -2
- package/dist/cjs/solutions-components.cjs.js +1 -1
- package/dist/collection/components/layer-table/layer-table.js +4 -16
- package/dist/collection/components/map-search/map-search.js +1 -1
- package/dist/collection/components/map-select-tools/map-select-tools.js +73 -17
- package/dist/collection/components/pdf-download/pdf-download.js +9 -76
- package/dist/collection/components/public-notification/public-notification.js +45 -3
- package/dist/collection/components/refine-selection/refine-selection.js +1 -1
- package/dist/collection/components/refine-selection-tools/refine-selection-tools.js +13 -5
- package/dist/collection/demos/buffer-tools.html +1 -1
- package/dist/collection/utils/csvUtils.js +4 -0
- package/dist/collection/utils/csvUtils.ts +7 -0
- package/dist/collection/utils/downloadUtils.js +181 -0
- package/dist/collection/utils/downloadUtils.ts +235 -0
- package/dist/collection/utils/interfaces.ts +8 -1
- package/dist/collection/utils/pdfUtils.js +7 -0
- package/dist/collection/utils/pdfUtils.ts +13 -2
- package/dist/components/downloadUtils.js +2279 -0
- package/dist/components/index.es.js +1 -1
- package/dist/components/layer-table.js +5 -16
- package/dist/components/map-layer-picker2.js +1 -1
- package/dist/components/map-search.js +1 -1
- package/dist/components/map-select-tools2.js +69 -19
- package/dist/components/pdf-download2.js +10 -2124
- package/dist/components/public-notification.js +24 -3
- package/dist/components/queryUtils.js +1 -1
- package/dist/components/refine-selection-tools2.js +6 -3
- package/dist/components/refine-selection2.js +1 -1
- package/dist/esm/buffer-tools_6.entry.js +6 -3
- package/dist/esm/calcite-combobox_3.entry.js +1 -1
- package/dist/esm/calcite-input-message_5.entry.js +1341 -13
- package/dist/esm/{calcite-input-message.calcite-notice.map-select-tools.pdf-download.refine-selection-ddd74bd6.js → downloadUtils-76e38a94.js} +206 -1335
- package/dist/esm/{index.es-8edafdb2.js → index.es-489f4f08.js} +2 -12
- package/dist/esm/layer-table.entry.js +6 -16
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{mapViewUtils-63e118f8.js → mapViewUtils-02696ab6.js} +1 -1
- package/dist/esm/public-notification.entry.js +24 -3
- package/dist/esm/solutions-components.js +1 -1
- package/dist/solutions-components/demos/buffer-tools.html +1 -1
- package/dist/solutions-components/{p-cc2e20c8.js → p-1bfd07e3.js} +1 -1
- package/dist/solutions-components/{p-117174e8.entry.js → p-335fce8c.entry.js} +1 -1
- package/dist/solutions-components/p-4ef94c6b.entry.js +6 -0
- package/dist/solutions-components/p-5d27b47d.entry.js +17 -0
- package/dist/solutions-components/p-92cb569a.entry.js +6 -0
- package/dist/solutions-components/{p-2a96314a.entry.js → p-a3b60bc9.entry.js} +2 -2
- package/dist/solutions-components/{p-98884f44.js → p-bff8aa4e.js} +3 -3
- package/dist/solutions-components/p-caa7e7a7.js +437 -0
- package/dist/solutions-components/solutions-components.esm.js +1 -1
- package/dist/solutions-components/utils/csvUtils.ts +7 -0
- package/dist/solutions-components/utils/downloadUtils.ts +235 -0
- package/dist/solutions-components/utils/interfaces.ts +8 -1
- package/dist/solutions-components/utils/pdfUtils.ts +13 -2
- package/dist/types/components/json-editor/assets/monaco-editor/monaco.d.ts +8262 -0
- package/dist/types/components/map-select-tools/map-select-tools.d.ts +19 -1
- package/dist/types/components/pdf-download/pdf-download.d.ts +0 -18
- package/dist/types/components/public-notification/public-notification.d.ts +10 -0
- package/dist/types/components/refine-selection-tools/refine-selection-tools.d.ts +2 -2
- package/dist/types/components.d.ts +6 -2
- package/dist/types/preact.d.ts +2 -1
- package/dist/types/utils/downloadUtils.d.ts +40 -0
- package/dist/types/utils/interfaces.d.ts +6 -2
- package/dist/types/utils/pdfUtils.d.ts +3 -1
- package/package.json +1 -1
- package/dist/cjs/csvUtils-3a56c6d8.js +0 -54
- package/dist/components/csvUtils.js +0 -52
- package/dist/esm/csvUtils-23b5418f.js +0 -52
- package/dist/solutions-components/p-15f9b0a0.entry.js +0 -6
- package/dist/solutions-components/p-238db156.js +0 -416
- package/dist/solutions-components/p-3069e3b7.js +0 -21
- package/dist/solutions-components/p-6d28f991.entry.js +0 -6
- package/dist/solutions-components/p-c5341977.entry.js +0 -6
@@ -19,13 +19,11 @@
|
|
19
19
|
* limitations under the License.
|
20
20
|
*/
|
21
21
|
import "@esri/calcite-components";
|
22
|
-
import * as
|
22
|
+
import * as pdfLabelFormats from "../../assets/data/labelFormats.json";
|
23
|
+
import * as downloadUtils from "../../utils/downloadUtils";
|
23
24
|
import { loadModules } from "../../utils/loadModules";
|
24
25
|
import { Host, h } from "@stencil/core";
|
25
|
-
import { exportCSV } from "../../utils/csvUtils";
|
26
|
-
import { exportPDF } from "../../utils/pdfUtils";
|
27
26
|
import { getLocaleComponentStrings } from "../../utils/locale";
|
28
|
-
import { queryFeaturesByID } from "../../utils/queryUtils";
|
29
27
|
export class PdfDownload {
|
30
28
|
constructor() {
|
31
29
|
this.disabled = false;
|
@@ -51,8 +49,8 @@ export class PdfDownload {
|
|
51
49
|
* @returns Promise resolving when function is done
|
52
50
|
*/
|
53
51
|
async downloadCSV(ids, removeDuplicates, addColumnTitle = true) {
|
54
|
-
|
55
|
-
|
52
|
+
return downloadUtils.downloadCSV(this.layerView.layer, ids, true, // formatUsingLayerPopup
|
53
|
+
removeDuplicates, addColumnTitle);
|
56
54
|
}
|
57
55
|
/**
|
58
56
|
* Downloads pdf of mailing labels for the provided list of ids
|
@@ -62,9 +60,7 @@ export class PdfDownload {
|
|
62
60
|
* @returns Promise resolving when function is done
|
63
61
|
*/
|
64
62
|
async downloadPDF(ids, removeDuplicates) {
|
65
|
-
|
66
|
-
const labelPageDescription = this._labelInfoElement.selectedOption.value;
|
67
|
-
return exportPDF(labels, labelPageDescription);
|
63
|
+
return downloadUtils.downloadPDF(this.layerView.layer, ids, removeDuplicates, this._labelInfoElement.selectedOption.value);
|
68
64
|
}
|
69
65
|
//--------------------------------------------------------------------------
|
70
66
|
//
|
@@ -107,31 +103,6 @@ export class PdfDownload {
|
|
107
103
|
]);
|
108
104
|
this._intl = intl;
|
109
105
|
}
|
110
|
-
/**
|
111
|
-
* Converts the text of a custom popup into a multiline label specification; conversion splits text into
|
112
|
-
* lines on <br>s, and removes HTML tags. It does not handle Arcade and related records.
|
113
|
-
*
|
114
|
-
* @param popupInfo Layer's popupInfo structure containing description, fieldInfos, and expressionInfos, e.g.,
|
115
|
-
* "<div style='text-align: left;'>{NAME}<br />{STREET}<br />{CITY}, {STATE} {ZIP} <br /></div>"
|
116
|
-
* @return Label spec
|
117
|
-
*/
|
118
|
-
_convertPopupToLabelSpec(popupInfo) {
|
119
|
-
// Replace <br>, <br/> with |
|
120
|
-
popupInfo = popupInfo.replace(/<br\s*\/?>/gi, "|");
|
121
|
-
// Remove remaining HTML tags, replace 0xA0 that popup uses for spaces, replace some char representations,
|
122
|
-
// and split the label back into individual lines
|
123
|
-
let labelSpec = popupInfo
|
124
|
-
.replace(/<[\s.]*[^<>]*\/?>/gi, "")
|
125
|
-
.replace(/\xA0/gi, " ")
|
126
|
-
.replace(/</gi, "<")
|
127
|
-
.replace(/>/gi, ">")
|
128
|
-
.replace(/ /gi, " ")
|
129
|
-
.split("|");
|
130
|
-
// Trim lines and remove empties
|
131
|
-
labelSpec = labelSpec.map(line => line.trim()).filter(line => line.length > 0);
|
132
|
-
return labelSpec;
|
133
|
-
}
|
134
|
-
;
|
135
106
|
/**
|
136
107
|
* Gets the formatted pdf export size text
|
137
108
|
*
|
@@ -154,47 +125,6 @@ export class PdfDownload {
|
|
154
125
|
const translations = await getLocaleComponentStrings(this.el);
|
155
126
|
this._translations = translations[0];
|
156
127
|
}
|
157
|
-
/**
|
158
|
-
* Creates labels from items.
|
159
|
-
*
|
160
|
-
* @param ids List of ids to download
|
161
|
-
* @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
|
162
|
-
* @param includeHeaderNames Add the label format at the front of the list of generated labels
|
163
|
-
* @returns Promise resolving when function is done
|
164
|
-
*/
|
165
|
-
async _prepareLabels(ids, removeDuplicates, includeHeaderNames = false) {
|
166
|
-
// Get the attributes of the features to export
|
167
|
-
const featureSet = await queryFeaturesByID(ids, this.layerView.layer);
|
168
|
-
const featuresAttrs = featureSet.features.map(f => f.attributes);
|
169
|
-
// What data fields are used in the labels?
|
170
|
-
// Example labelFormat: ['{NAME}', '{STREET}', '{CITY}, {STATE} {ZIP}']
|
171
|
-
const labelFormat = this._convertPopupToLabelSpec(this.layerView.layer.popupTemplate.content[0].text);
|
172
|
-
// Convert attributes into an array of labels
|
173
|
-
let labels = featuresAttrs.map(featureAttributes => {
|
174
|
-
const label = [];
|
175
|
-
labelFormat.forEach(labelLineTemplate => {
|
176
|
-
const labelLine = this._intl.substitute(labelLineTemplate, featureAttributes).trim();
|
177
|
-
if (labelLine.length > 0) {
|
178
|
-
label.push(labelLine);
|
179
|
-
}
|
180
|
-
});
|
181
|
-
return label;
|
182
|
-
})
|
183
|
-
// Remove empty labels
|
184
|
-
.filter(label => label.length > 0);
|
185
|
-
// Remove duplicates
|
186
|
-
if (removeDuplicates) {
|
187
|
-
const labelsAsStrings = labels.map(label => JSON.stringify(label));
|
188
|
-
const uniqueLabels = new Set(labelsAsStrings);
|
189
|
-
labels = Array.from(uniqueLabels, labelString => JSON.parse(labelString));
|
190
|
-
}
|
191
|
-
// Add header names
|
192
|
-
if (includeHeaderNames) {
|
193
|
-
const headerNames = labelFormat.map(labelFormatLine => labelFormatLine.replace(/\{/g, "").replace(/\}/g, ""));
|
194
|
-
labels.unshift(headerNames);
|
195
|
-
}
|
196
|
-
return Promise.resolve(labels);
|
197
|
-
}
|
198
128
|
/**
|
199
129
|
* Renders the pdf export size options
|
200
130
|
*
|
@@ -203,7 +133,7 @@ export class PdfDownload {
|
|
203
133
|
* @protected
|
204
134
|
*/
|
205
135
|
_renderItems() {
|
206
|
-
const s =
|
136
|
+
const s = pdfLabelFormats;
|
207
137
|
const sortedPdfIndo = (s.default || s).sort((a, b) => {
|
208
138
|
const _a = parseInt(a.descriptionPDF.labelsPerPageDisplay, 10);
|
209
139
|
const _b = parseInt(b.descriptionPDF.labelsPerPageDisplay, 10);
|
@@ -338,6 +268,9 @@ export class PdfDownload {
|
|
338
268
|
"references": {
|
339
269
|
"Promise": {
|
340
270
|
"location": "global"
|
271
|
+
},
|
272
|
+
"downloadUtils": {
|
273
|
+
"location": "global"
|
341
274
|
}
|
342
275
|
},
|
343
276
|
"return": "Promise<void>"
|
@@ -66,6 +66,25 @@ export class PublicNotification {
|
|
66
66
|
this._popupsEnabled = v === null || v === void 0 ? void 0 : v.popup.autoOpenEnabled;
|
67
67
|
}
|
68
68
|
}
|
69
|
+
/**
|
70
|
+
* Called each time the searchConfiguration prop is changed.
|
71
|
+
*
|
72
|
+
* @returns Promise when complete
|
73
|
+
*/
|
74
|
+
async watchSearchConfigurationHandler(newValue, oldValue) {
|
75
|
+
//TODO adding this here to see if its any different than having in map-select-tools
|
76
|
+
// I would have thought that the prop would have made it through on the next render of map-select-tools
|
77
|
+
// however we are still seeing a broken search...need to understand why and don't see a clean way to debug in devext
|
78
|
+
console.log("PN watchSearchConfigurationHandler");
|
79
|
+
console.log("PN newValue");
|
80
|
+
console.log(newValue);
|
81
|
+
console.log("PN oldValue");
|
82
|
+
console.log(oldValue);
|
83
|
+
if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
|
84
|
+
console.log("Emit event from parent");
|
85
|
+
this.searchConfigurationChange.emit(newValue);
|
86
|
+
}
|
87
|
+
}
|
69
88
|
/**
|
70
89
|
* Called each time the selectionSets prop is changed.
|
71
90
|
*/
|
@@ -297,7 +316,7 @@ export class PublicNotification {
|
|
297
316
|
this._selectionWorkflowType === EWorkflowType.SKETCH ? sketchTip : searchTip;
|
298
317
|
const nameLabelClass = this.customLabelEnabled ? "" : "display-none";
|
299
318
|
return (h("calcite-panel", null, this._getLabel(this._translations.stepTwoFull.replace("{{layer}}", (_a = this.addresseeLayer) === null || _a === void 0 ? void 0 : _a.layer.title)), this._getNotice(noticeText), h("div", { class: "padding-top-sides-1" }, h("map-select-tools", { bufferColor: this.bufferColor, bufferOutlineColor: this.bufferOutlineColor, class: "font-bold", defaultBufferDistance: this.defaultBufferDistance, defaultBufferUnit: this.defaultBufferUnit, enabledLayerIds: this.selectionLayerIds, isUpdate: !!this._activeSelection, mapView: this.mapView, onSelectionSetChange: (evt) => this._updateForSelection(evt), onWorkflowTypeChange: (evt) => this._updateForWorkflowType(evt), ref: (el) => { this._selectTools = el; }, searchConfiguration: this.searchConfiguration, selectLayerView: this.addresseeLayer, selectionSet: this._activeSelection, showBufferTools: this.showSearchSettings })), h("div", { class: "padding-sides-1 padding-bottom-1", style: { "align-items": "end", "display": "flex" } }, h("calcite-icon", { class: "info-blue padding-end-1-2", icon: "feature-layer", scale: "s" }), h("calcite-input-message", { active: true, class: "info-blue", scale: "m" }, this.noResultText && this._numSelected === 0 ? this.noResultText :
|
300
|
-
this._translations.selectedAddresses.replace("{{n}}", this._numSelected.toString()).replace("{{layer}}", ((_b = this.addresseeLayer) === null || _b === void 0 ? void 0 : _b.layer.title) || ""))), h("div", { class: "padding-sides-1 " + nameLabelClass }, h("calcite-label", { class: "font-bold" }, "
|
319
|
+
this._translations.selectedAddresses.replace("{{n}}", this._numSelected.toString()).replace("{{layer}}", ((_b = this.addresseeLayer) === null || _b === void 0 ? void 0 : _b.layer.title) || ""))), h("div", { class: "padding-sides-1 " + nameLabelClass }, h("calcite-label", { class: "font-bold" }, "List name", h("calcite-input", { onInput: () => {
|
301
320
|
this.labelChange.emit(this._labelName.value);
|
302
321
|
}, placeholder: "Insert label here...", ref: (el) => { this._labelName = el; }, value: this._customLabel || "" }))), this._getPageNavButtons(this._translations.done, this._numSelected === 0, () => { void this._saveSelection(); }, this._translations.cancel, false, () => { void this._home(); })));
|
303
322
|
}
|
@@ -339,7 +358,7 @@ export class PublicNotification {
|
|
339
358
|
*/
|
340
359
|
_getDownloadPage(type) {
|
341
360
|
const isPdf = type === EExportType.PDF;
|
342
|
-
return (h("calcite-panel", null, h("div", null, h("div", { class: "padding-top-sides-1" }, h("calcite-label", { class: "font-bold" }, isPdf ? this._translations.
|
361
|
+
return (h("calcite-panel", null, h("div", null, h("div", { class: "padding-top-sides-1" }, h("calcite-label", { class: "font-bold" }, isPdf ? this._translations.downloadPDF : this._translations.downloadCSV), h("calcite-label", null, this._translations.notifications)), this._getSelectionLists(), h("div", { class: "margin-side-1 padding-top-1 border-bottom" }), h("div", { class: "padding-top-sides-1" }, h("calcite-label", { layout: "inline" }, h("calcite-checkbox", { disabled: !this._downloadActive, ref: (el) => { this._removeDuplicates = el; } }), this._translations.removeDuplicate)), h("div", { class: isPdf ? "" : "display-none" }, this._getLabel(this._translations.selectPDFLabelOption, false), h("div", { class: "padding-sides-1" }, h("pdf-download", { disabled: !this._downloadActive, layerView: this.addresseeLayer, ref: (el) => { this._downloadTools = el; } }))), h("div", { class: "padding-1 display-flex" }, h("calcite-button", { disabled: !this._downloadActive, onClick: isPdf ? () => this._downloadPDF() : () => this._downloadCSV(), width: "full" }, isPdf ? this._translations.downloadPDF : this._translations.downloadCSV)))));
|
343
362
|
}
|
344
363
|
/**
|
345
364
|
* Create the stacked navigation buttons for a page
|
@@ -878,7 +897,7 @@ export class PublicNotification {
|
|
878
897
|
},
|
879
898
|
"searchConfiguration": {
|
880
899
|
"type": "unknown",
|
881
|
-
"mutable":
|
900
|
+
"mutable": true,
|
882
901
|
"complexType": {
|
883
902
|
"original": "ISearchConfiguration",
|
884
903
|
"resolved": "ISearchConfiguration",
|
@@ -980,6 +999,26 @@ export class PublicNotification {
|
|
980
999
|
"resolved": "string",
|
981
1000
|
"references": {}
|
982
1001
|
}
|
1002
|
+
}, {
|
1003
|
+
"method": "searchConfigurationChange",
|
1004
|
+
"name": "searchConfigurationChange",
|
1005
|
+
"bubbles": true,
|
1006
|
+
"cancelable": true,
|
1007
|
+
"composed": true,
|
1008
|
+
"docs": {
|
1009
|
+
"tags": [],
|
1010
|
+
"text": "Emitted on demand when searchConfiguration gets a new value"
|
1011
|
+
},
|
1012
|
+
"complexType": {
|
1013
|
+
"original": "ISearchConfiguration",
|
1014
|
+
"resolved": "ISearchConfiguration",
|
1015
|
+
"references": {
|
1016
|
+
"ISearchConfiguration": {
|
1017
|
+
"location": "import",
|
1018
|
+
"path": "../../utils/interfaces"
|
1019
|
+
}
|
1020
|
+
}
|
1021
|
+
}
|
983
1022
|
}];
|
984
1023
|
}
|
985
1024
|
static get elementRef() { return "el"; }
|
@@ -987,6 +1026,9 @@ export class PublicNotification {
|
|
987
1026
|
return [{
|
988
1027
|
"propName": "mapView",
|
989
1028
|
"methodName": "mapViewWatchHandler"
|
1029
|
+
}, {
|
1030
|
+
"propName": "searchConfiguration",
|
1031
|
+
"methodName": "watchSearchConfigurationHandler"
|
990
1032
|
}, {
|
991
1033
|
"propName": "_selectionSets",
|
992
1034
|
"methodName": "selectionSetsWatchHandler"
|
@@ -118,7 +118,7 @@ export class RefineSelection {
|
|
118
118
|
const refineSet = this._getRefineSelectionSet(this.selectionSets);
|
119
119
|
const numAdded = (refineSet === null || refineSet === void 0 ? void 0 : refineSet.refineIds.addIds.length) || 0;
|
120
120
|
const numRemoved = (refineSet === null || refineSet === void 0 ? void 0 : refineSet.refineIds.removeIds.length) || 0;
|
121
|
-
return [(h("calcite-list-item", { label: this._translations.featuresAdded.replace("{{n}}", numAdded.toString()) })), (h("calcite-list-item", { label: this._translations.featuresRemoved.replace("{{n}}", numRemoved.toString()) })), (h("calcite-list-item", { label: this._translations.totalSelected.replace("{{n}}", total.toString()) }))];
|
121
|
+
return [(h("calcite-list-item", { label: this._translations.featuresAdded.replace("{{n}}", numAdded.toString()), "non-interactive": true })), (h("calcite-list-item", { label: this._translations.featuresRemoved.replace("{{n}}", numRemoved.toString()), "non-interactive": true })), (h("calcite-list-item", { label: this._translations.totalSelected.replace("{{n}}", total.toString()), "non-interactive": true }))];
|
122
122
|
}
|
123
123
|
/**
|
124
124
|
* Fetch the refine selection set
|
@@ -238,7 +238,7 @@ export class RefineSelectionTools {
|
|
238
238
|
return prev;
|
239
239
|
}, []);
|
240
240
|
}
|
241
|
-
this.refineSelectionGraphicsChange.emit(graphics);
|
241
|
+
this.refineSelectionGraphicsChange.emit({ graphics, useOIDs: false });
|
242
242
|
this._clear();
|
243
243
|
});
|
244
244
|
});
|
@@ -312,7 +312,10 @@ export class RefineSelectionTools {
|
|
312
312
|
});
|
313
313
|
});
|
314
314
|
if (this.refineMode === ERefineMode.SUBSET) {
|
315
|
-
this.refineSelectionGraphicsChange.emit(
|
315
|
+
this.refineSelectionGraphicsChange.emit({
|
316
|
+
graphics,
|
317
|
+
useOIDs: this.layerViews[0].layer.title === this.layerView.layer.title
|
318
|
+
});
|
316
319
|
}
|
317
320
|
else {
|
318
321
|
const oids = Array.isArray(graphics) ? graphics.map(g => { var _a; return g.attributes[(_a = g === null || g === void 0 ? void 0 : g.layer) === null || _a === void 0 ? void 0 : _a.objectIdField]; }) : [];
|
@@ -667,9 +670,14 @@ export class RefineSelectionTools {
|
|
667
670
|
"text": "Emitted on demand when selection graphics change."
|
668
671
|
},
|
669
672
|
"complexType": {
|
670
|
-
"original": "
|
671
|
-
"resolved": "
|
672
|
-
"references": {
|
673
|
+
"original": "IRefineSelectionEvent",
|
674
|
+
"resolved": "IRefineSelectionEvent",
|
675
|
+
"references": {
|
676
|
+
"IRefineSelectionEvent": {
|
677
|
+
"location": "import",
|
678
|
+
"path": "../../utils/interfaces"
|
679
|
+
}
|
680
|
+
}
|
673
681
|
}
|
674
682
|
}, {
|
675
683
|
"method": "refineSelectionIdsChange",
|
@@ -18,6 +18,7 @@
|
|
18
18
|
* See the License for the specific language governing permissions and
|
19
19
|
* limitations under the License.
|
20
20
|
*/
|
21
|
+
//#region Public functions
|
21
22
|
/**
|
22
23
|
* Export a csv of the attributes from the features that match the provided ids
|
23
24
|
*
|
@@ -29,6 +30,8 @@ export function exportCSV(labels) {
|
|
29
30
|
const outputLines = labels.map(label => Object.values(label).map(v => `"${v}"`).join(",") + "\r\n");
|
30
31
|
_downloadCSVFile(outputLines, `notify-${Date.now().toString()}`);
|
31
32
|
}
|
33
|
+
//#endregion
|
34
|
+
//#region Private functions
|
32
35
|
/**
|
33
36
|
* Download the CSV file
|
34
37
|
*
|
@@ -48,3 +51,4 @@ function _downloadCSVFile(outputLines, fileTitle) {
|
|
48
51
|
document.body.removeChild(link);
|
49
52
|
}
|
50
53
|
}
|
54
|
+
//#endregion
|
@@ -14,6 +14,8 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
+
//#region Public functions
|
18
|
+
|
17
19
|
/**
|
18
20
|
* Export a csv of the attributes from the features that match the provided ids
|
19
21
|
*
|
@@ -29,6 +31,9 @@ export function exportCSV(
|
|
29
31
|
_downloadCSVFile(outputLines, `notify-${Date.now().toString()}`);
|
30
32
|
}
|
31
33
|
|
34
|
+
//#endregion
|
35
|
+
//#region Private functions
|
36
|
+
|
32
37
|
/**
|
33
38
|
* Download the CSV file
|
34
39
|
*
|
@@ -51,3 +56,5 @@ function _downloadCSVFile(
|
|
51
56
|
document.body.removeChild(link);
|
52
57
|
}
|
53
58
|
}
|
59
|
+
|
60
|
+
//#endregion
|
@@ -0,0 +1,181 @@
|
|
1
|
+
/*!
|
2
|
+
* Copyright 2022 Esri
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
4
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
5
|
+
*/
|
6
|
+
/** @license
|
7
|
+
* Copyright 2022 Esri
|
8
|
+
*
|
9
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
10
|
+
* you may not use this file except in compliance with the License.
|
11
|
+
* You may obtain a copy of the License at
|
12
|
+
*
|
13
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
14
|
+
*
|
15
|
+
* Unless required by applicable law or agreed to in writing, software
|
16
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
17
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
18
|
+
* See the License for the specific language governing permissions and
|
19
|
+
* limitations under the License.
|
20
|
+
*/
|
21
|
+
//#region Declarations
|
22
|
+
import { exportCSV } from "./csvUtils";
|
23
|
+
import { exportPDF } from "./pdfUtils";
|
24
|
+
import { loadModules } from "./loadModules";
|
25
|
+
import { queryFeaturesByID } from "./queryUtils";
|
26
|
+
export { ILabel } from "./pdfUtils";
|
27
|
+
//#endregion
|
28
|
+
//#region Public functions
|
29
|
+
/**
|
30
|
+
* Downloads csv of mailing labels for the provided list of ids
|
31
|
+
*
|
32
|
+
* @param layer Layer providing features and attributes for download
|
33
|
+
* @param ids List of ids to download
|
34
|
+
* @param formatUsingLayerPopup When true, the layer's popup is used to choose attributes for each column; when false,
|
35
|
+
* all attributes are exported
|
36
|
+
* @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
|
37
|
+
* @param addColumnTitle Indicates if column headings should be included in output
|
38
|
+
* @returns Promise resolving when function is done
|
39
|
+
*/
|
40
|
+
export async function downloadCSV(layer, ids, formatUsingLayerPopup, removeDuplicates = false, addColumnTitle = false) {
|
41
|
+
const labels = await _prepareLabels(layer, ids, removeDuplicates, formatUsingLayerPopup, addColumnTitle);
|
42
|
+
exportCSV(labels);
|
43
|
+
return Promise.resolve();
|
44
|
+
}
|
45
|
+
/**
|
46
|
+
* Downloads csv of mailing labels for the provided list of ids
|
47
|
+
*
|
48
|
+
* @param layer Layer providing features and attributes for download
|
49
|
+
* @param ids List of ids to download
|
50
|
+
* @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
|
51
|
+
* @param labelPageDescription Provides PDF page layout info
|
52
|
+
* @returns Promise resolving when function is done
|
53
|
+
*/
|
54
|
+
export async function downloadPDF(layer, ids, removeDuplicates, labelPageDescription) {
|
55
|
+
const labels = await _prepareLabels(layer, ids, removeDuplicates);
|
56
|
+
exportPDF(labels, labelPageDescription);
|
57
|
+
return Promise.resolve();
|
58
|
+
}
|
59
|
+
//#endregion
|
60
|
+
//#region Private functions
|
61
|
+
/**
|
62
|
+
* Converts a set of fieldInfos into template lines.
|
63
|
+
*
|
64
|
+
* @param fieldInfos Layer's fieldInfos structure
|
65
|
+
* @return Label spec
|
66
|
+
*/
|
67
|
+
function _convertPopupFieldsToLabelSpec(fieldInfos) {
|
68
|
+
const labelSpec = [];
|
69
|
+
// Every visible attribute is used
|
70
|
+
fieldInfos.forEach(fieldInfo => {
|
71
|
+
if (fieldInfo.visible) {
|
72
|
+
labelSpec.push(`{${fieldInfo.fieldName}}`);
|
73
|
+
}
|
74
|
+
});
|
75
|
+
return labelSpec;
|
76
|
+
}
|
77
|
+
;
|
78
|
+
/**
|
79
|
+
* Converts the text of a custom popup into a multiline label specification; conversion splits text into
|
80
|
+
* lines on <br>s, and removes HTML tags. It does not handle Arcade and related records.
|
81
|
+
*
|
82
|
+
* @param popupInfo Layer's popupInfo structure containing description, fieldInfos, and expressionInfos, e.g.,
|
83
|
+
* "<div style='text-align: left;'>{NAME}<br />{STREET}<br />{CITY}, {STATE} {ZIP} <br /></div>"
|
84
|
+
* @return Label spec
|
85
|
+
*/
|
86
|
+
function _convertPopupTextToLabelSpec(popupInfo) {
|
87
|
+
// Replace <br>, <br/> with |
|
88
|
+
popupInfo = popupInfo.replace(/<br\s*\/?>/gi, "|");
|
89
|
+
// Remove remaining HTML tags, replace 0xA0 that popup uses for spaces, replace some char representations,
|
90
|
+
// and split the label back into individual lines
|
91
|
+
let labelSpec = popupInfo
|
92
|
+
.replace(/<[\s.]*[^<>]*\/?>/gi, "")
|
93
|
+
.replace(/\xA0/gi, " ")
|
94
|
+
.replace(/</gi, "<")
|
95
|
+
.replace(/>/gi, ">")
|
96
|
+
.replace(/ /gi, " ")
|
97
|
+
.split("|");
|
98
|
+
// Trim lines and remove empties
|
99
|
+
labelSpec = labelSpec.map(line => line.trim()).filter(line => line.length > 0);
|
100
|
+
return labelSpec;
|
101
|
+
}
|
102
|
+
;
|
103
|
+
/**
|
104
|
+
* Creates labels from items.
|
105
|
+
*
|
106
|
+
* @param layer Layer from which to fetch features
|
107
|
+
* @param ids List of ids to download
|
108
|
+
* @param removeDuplicates When true a single label is generated when multiple featues have a shared address value
|
109
|
+
* @param formatUsingLayerPopup When true, the layer's popup is used to choose attributes for each column; when false,
|
110
|
+
* all attributes are exported
|
111
|
+
* @param includeHeaderNames Add the label format at the front of the list of generated labels
|
112
|
+
* @returns Promise resolving when function is done
|
113
|
+
*/
|
114
|
+
async function _prepareLabels(layer, ids, removeDuplicates = true, formatUsingLayerPopup = true, includeHeaderNames = false) {
|
115
|
+
var _a, _b, _c, _d;
|
116
|
+
const [intl] = await loadModules([
|
117
|
+
"esri/intl"
|
118
|
+
]);
|
119
|
+
// Get the attributes of the features to export
|
120
|
+
const featureSet = await queryFeaturesByID(ids, layer);
|
121
|
+
const featuresAttrs = featureSet.features.map(f => f.attributes);
|
122
|
+
// Get the label formatting, if any
|
123
|
+
let labelFormat;
|
124
|
+
if (layer.popupEnabled) {
|
125
|
+
// What data fields are used in the labels?
|
126
|
+
// Example labelFormat: ['{NAME}', '{STREET}', '{CITY}, {STATE} {ZIP}']
|
127
|
+
if (formatUsingLayerPopup && ((_b = (_a = layer.popupTemplate) === null || _a === void 0 ? void 0 : _a.content[0]) === null || _b === void 0 ? void 0 : _b.type) === "fields") {
|
128
|
+
labelFormat = _convertPopupFieldsToLabelSpec(layer.popupTemplate.fieldInfos);
|
129
|
+
}
|
130
|
+
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") {
|
131
|
+
labelFormat = _convertPopupTextToLabelSpec(layer.popupTemplate.content[0].text);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
// Apply the label format
|
135
|
+
let labels;
|
136
|
+
// eslint-disable-next-line unicorn/prefer-ternary
|
137
|
+
if (labelFormat) {
|
138
|
+
// Convert attributes into an array of labels
|
139
|
+
labels = featuresAttrs.map(featureAttributes => {
|
140
|
+
const label = [];
|
141
|
+
labelFormat.forEach(labelLineTemplate => {
|
142
|
+
const labelLine = intl.substitute(labelLineTemplate, featureAttributes).trim();
|
143
|
+
if (labelLine.length > 0) {
|
144
|
+
label.push(labelLine);
|
145
|
+
}
|
146
|
+
});
|
147
|
+
return label;
|
148
|
+
})
|
149
|
+
// Remove empty labels
|
150
|
+
.filter(label => label.length > 0);
|
151
|
+
}
|
152
|
+
else {
|
153
|
+
// Export all attributes
|
154
|
+
labels = featuresAttrs.map(featureAttributes => {
|
155
|
+
return Object.values(featureAttributes).map(attribute => `${attribute}`);
|
156
|
+
});
|
157
|
+
}
|
158
|
+
// Remove duplicates
|
159
|
+
if (removeDuplicates) {
|
160
|
+
const labelsAsStrings = labels.map(label => JSON.stringify(label));
|
161
|
+
const uniqueLabels = new Set(labelsAsStrings);
|
162
|
+
labels = Array.from(uniqueLabels, labelString => JSON.parse(labelString));
|
163
|
+
}
|
164
|
+
// Add header names
|
165
|
+
if (includeHeaderNames) {
|
166
|
+
let headerNames = [];
|
167
|
+
if (labelFormat) {
|
168
|
+
headerNames = labelFormat.map(labelFormatLine => labelFormatLine.replace(/\{/g, "").replace(/\}/g, ""));
|
169
|
+
}
|
170
|
+
else {
|
171
|
+
Object.keys(featuresAttrs[0]).forEach(k => {
|
172
|
+
if (featuresAttrs[0].hasOwnProperty(k)) {
|
173
|
+
headerNames.push(k);
|
174
|
+
}
|
175
|
+
});
|
176
|
+
}
|
177
|
+
labels.unshift(headerNames);
|
178
|
+
}
|
179
|
+
return Promise.resolve(labels);
|
180
|
+
}
|
181
|
+
//#endregion
|