@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.
- package/dist/cjs/calcite-input-text_5.cjs.entry.js +36 -36
- package/dist/cjs/calcite-shell-panel_14.cjs.entry.js +1 -1
- package/dist/cjs/solution-configuration.cjs.entry.js +1 -1
- package/dist/cjs/solution-contents_3.cjs.entry.js +1 -1
- package/dist/cjs/{solution-store-70002b57.js → solution-store-ca4639d5.js} +3 -3
- package/dist/collection/components/add-record-modal/test/add-record-modal.e2e.js +24 -0
- package/dist/collection/components/add-record-modal/test/add-record-modal.spec.js +32 -0
- package/dist/collection/components/buffer-tools/test/buffer-tools.e2e.js +24 -0
- package/dist/collection/components/buffer-tools/test/buffer-tools.spec.js +157 -0
- package/dist/collection/components/card-manager/test/card-manager.e2e.js +24 -0
- package/dist/collection/components/card-manager/test/card-manager.spec.js +32 -0
- package/dist/collection/components/comment-card/test/comment-card.e2e.js +24 -0
- package/dist/collection/components/comment-card/test/comment-card.spec.js +32 -0
- package/dist/collection/components/crowdsource-manager/test/crowdsource-manager.e2e.js +24 -0
- package/dist/collection/components/crowdsource-manager/test/crowdsource-manager.spec.js +32 -0
- package/dist/collection/components/crowdsource-reporter/test/crowdsource-reporter.e2e.js +24 -0
- package/dist/collection/components/crowdsource-reporter/test/crowdsource-reporter.spec.js +32 -0
- package/dist/collection/components/deduct-calculator/test/deduct-calculator.e2e.js +24 -0
- package/dist/collection/components/deduct-calculator/test/deduct-calculator.spec.js +32 -0
- package/dist/collection/components/edit-record-modal/test/edit-record-modal.e2e.js +24 -0
- package/dist/collection/components/edit-record-modal/test/edit-record-modal.spec.js +32 -0
- package/dist/collection/components/info-card/test/info-card.e2e.js +24 -0
- package/dist/collection/components/info-card/test/info-card.spec.js +32 -0
- package/dist/collection/components/json-editor/test/json-editor.e2e.js +31 -0
- package/dist/collection/components/json-editor/test/json-editor.spec.js +60 -0
- package/dist/collection/components/layer-table/test/layer-table.e2e.js +24 -0
- package/dist/collection/components/layer-table/test/layer-table.spec.js +32 -0
- package/dist/collection/components/list-item/test/list-item.e2e.js +24 -0
- package/dist/collection/components/list-item/test/list-item.spec.js +32 -0
- package/dist/collection/components/map-card/test/map-card.e2e.js +24 -0
- package/dist/collection/components/map-card/test/map-card.spec.js +32 -0
- package/dist/collection/components/map-draw-tools/test/map-draw-tools.e2e.js +24 -0
- package/dist/collection/components/map-draw-tools/test/map-draw-tools.spec.js +32 -0
- package/dist/collection/components/map-layer-picker/test/map-layer-picker.e2e.js +24 -0
- package/dist/collection/components/map-layer-picker/test/map-layer-picker.spec.js +109 -0
- package/dist/collection/components/map-search/test/map-search.e2e.js +24 -0
- package/dist/collection/components/map-search/test/map-search.spec.js +53 -0
- package/dist/collection/components/map-select-tools/map-select-tools.js +36 -36
- package/dist/collection/components/map-select-tools/test/map-select-tools.e2e.js +24 -0
- package/dist/collection/components/map-select-tools/test/map-select-tools.spec.js +349 -0
- package/dist/collection/components/media-card/test/media-card.e2e.js +24 -0
- package/dist/collection/components/media-card/test/media-card.spec.js +32 -0
- package/dist/collection/components/pci-calculator/test/pci-calculator.e2e.js +24 -0
- package/dist/collection/components/pci-calculator/test/pci-calculator.spec.js +32 -0
- package/dist/collection/components/pdf-download/test/pdf-download.e2e.js +71 -0
- package/dist/collection/components/pdf-download/test/pdf-download.spec.js +104 -0
- package/dist/collection/components/public-notification/test/public-notification.e2e.js +95 -0
- package/dist/collection/components/public-notification/test/public-notification.spec.js +149 -0
- package/dist/collection/components/refine-selection/refine-selection.css +85 -85
- package/dist/collection/components/solution-configuration/test/solution-configuration.e2e.js +31 -0
- package/dist/collection/components/solution-configuration/test/solution-configuration.spec.js +114 -0
- package/dist/collection/components/solution-contents/test/solution-contents.e2e.js +89 -0
- package/dist/collection/components/solution-contents/test/solution-contents.spec.js +138 -0
- package/dist/collection/components/solution-item/test/solution-item.e2e.js +31 -0
- package/dist/collection/components/solution-item/test/solution-item.spec.js +72 -0
- package/dist/collection/components/solution-item-details/test/solution-item-details.e2e.js +31 -0
- package/dist/collection/components/solution-item-details/test/solution-item-details.spec.js +137 -0
- package/dist/collection/components/solution-item-icon/test/solution-item-icon.e2e.js +24 -0
- package/dist/collection/components/solution-item-icon/test/solution-item-icon.spec.js +34 -0
- package/dist/collection/components/solution-item-sharing/test/solution-item-sharing.e2e.js +31 -0
- package/dist/collection/components/solution-item-sharing/test/solution-item-sharing.spec.js +49 -0
- package/dist/collection/components/solution-organization-variables/test/solution-organization-variables.e2e.js +31 -0
- package/dist/collection/components/solution-organization-variables/test/solution-organization-variables.spec.js +60 -0
- package/dist/collection/components/solution-resource-item/test/solution-resource-item.e2e.js +31 -0
- package/dist/collection/components/solution-resource-item/test/solution-resource-item.spec.js +50 -0
- package/dist/collection/components/solution-spatial-ref/test/solution-spatial-ref.e2e.js +31 -0
- package/dist/collection/components/solution-spatial-ref/test/solution-spatial-ref.spec.js +170 -0
- package/dist/collection/components/solution-template-data/test/solution-template-data.e2e.js +31 -0
- package/dist/collection/components/solution-template-data/test/solution-template-data.spec.js +55 -0
- package/dist/collection/components/solution-variables/test/solution-variables.e2e.js +31 -0
- package/dist/collection/components/solution-variables/test/solution-variables.spec.js +126 -0
- package/dist/collection/utils/publicNotificationUtils.js +45 -0
- package/dist/collection/utils/templates.e2e.js +25 -0
- package/dist/collection/utils/test/csvUtils.spec.js +46 -0
- package/dist/collection/utils/test/downloadUtils.spec.js +102 -0
- package/dist/collection/utils/test/pciUtils.spec.js +297 -0
- package/dist/collection/utils/test/solution-store.spec.js +439 -0
- package/dist/components/map-select-tools2.js +36 -36
- package/dist/components/solution-store.js +3 -3
- package/dist/esm/calcite-input-text_5.entry.js +36 -36
- package/dist/esm/calcite-shell-panel_14.entry.js +1 -1
- package/dist/esm/solution-configuration.entry.js +1 -1
- package/dist/esm/solution-contents_3.entry.js +1 -1
- package/dist/esm/{solution-store-5d068b07.js → solution-store-70f874f8.js} +3 -3
- package/dist/solutions-components/{p-41802f6b.entry.js → p-16dfb254.entry.js} +1 -1
- package/dist/solutions-components/{p-4769a2a5.entry.js → p-5ed755a2.entry.js} +1 -1
- package/dist/solutions-components/{p-826a814d.js → p-78719506.js} +2 -2
- package/dist/solutions-components/{p-9f620303.entry.js → p-b4b19fd3.entry.js} +1 -1
- package/dist/solutions-components/{p-24fe6e1c.entry.js → p-d5d5942d.entry.js} +1 -1
- package/dist/solutions-components/solutions-components.esm.js +1 -1
- package/dist/solutions-components/utils/common.js +291 -0
- package/dist/solutions-components/utils/csvDownload.js +36 -0
- package/dist/solutions-components/utils/csvUtils.js +32 -0
- package/dist/solutions-components/utils/downloadUtils.js +386 -0
- package/dist/solutions-components/utils/interfaces.js +56 -0
- package/dist/solutions-components/utils/languageUtil.js +85 -0
- package/dist/solutions-components/utils/loadModules.js +20 -0
- package/dist/solutions-components/utils/locale.js +56 -0
- package/dist/solutions-components/utils/mapViewUtils.js +140 -0
- package/dist/solutions-components/utils/pciUtils.js +837 -0
- package/dist/solutions-components/utils/pdfUtils.js +62 -0
- package/dist/solutions-components/utils/publicNotificationStore.js +38 -0
- package/dist/solutions-components/utils/publicNotificationUtils.js +45 -0
- package/dist/solutions-components/utils/queryUtils.js +148 -0
- package/dist/solutions-components/utils/solution-store.js +579 -0
- package/dist/solutions-components/utils/templates.e2e.js +25 -0
- package/dist/solutions-components/utils/templates.js +341 -0
- package/dist/solutions-components/utils/test/csvUtils.spec.js +46 -0
- package/dist/solutions-components/utils/test/downloadUtils.spec.js +102 -0
- package/dist/solutions-components/utils/test/mocks/jsApi.js +74 -0
- package/dist/solutions-components/utils/test/pciUtils.spec.js +297 -0
- package/dist/solutions-components/utils/test/solution-store.spec.js +439 -0
- package/dist/solutions-components/utils/test/testUtils.js +135 -0
- package/dist/solutions-components/utils/types.js +14 -0
- package/dist/solutions-components_commit.txt +7 -0
- 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(/</gi, "<")
|
|
107
|
+
.replace(/>/gi, ">")
|
|
108
|
+
.replace(/ /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
|
+
}
|