@esri/solutions-components 0.7.30 → 0.7.32

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 (62) hide show
  1. package/dist/assets/t9n/crowdsource-reporter/resources.json +7 -5
  2. package/dist/assets/t9n/crowdsource-reporter/resources_en.json +7 -5
  3. package/dist/assets/t9n/feature-list/resources.json +1 -1
  4. package/dist/assets/t9n/feature-list/resources_en.json +1 -1
  5. package/dist/assets/t9n/layer-list/resources.json +1 -1
  6. package/dist/assets/t9n/layer-list/resources_en.json +1 -1
  7. package/dist/cjs/{calcite-flow_4.cjs.entry.js → calcite-flow_5.cjs.entry.js} +286 -19
  8. package/dist/cjs/card-manager_3.cjs.entry.js +1 -1
  9. package/dist/cjs/crowdsource-reporter.cjs.entry.js +248 -32
  10. package/dist/cjs/{downloadUtils-83c6d3c3.js → downloadUtils-10e0de31.js} +2 -2
  11. package/dist/cjs/{index.es-bd1a93b2.js → index.es-72dc7ab9.js} +1 -1
  12. package/dist/cjs/loader.cjs.js +1 -1
  13. package/dist/cjs/map-select-tools_3.cjs.entry.js +1 -1
  14. package/dist/cjs/public-notification.cjs.entry.js +1 -1
  15. package/dist/cjs/solutions-components.cjs.js +1 -1
  16. package/dist/collection/collection-manifest.json +1 -0
  17. package/dist/collection/components/create-feature/create-feature.css +50 -0
  18. package/dist/collection/components/create-feature/create-feature.js +444 -0
  19. package/dist/collection/components/crowdsource-reporter/crowdsource-reporter.css +10 -1
  20. package/dist/collection/components/crowdsource-reporter/crowdsource-reporter.js +287 -33
  21. package/dist/collection/components/feature-list/feature-list.js +1 -0
  22. package/dist/collection/components/layer-list/layer-list.js +60 -16
  23. package/dist/collection/demos/create-feature.html +90 -0
  24. package/dist/collection/demos/crowdsource-reporter.html +26 -11
  25. package/dist/collection/utils/downloadUtils.js +1 -1
  26. package/dist/collection/utils/downloadUtils.ts +1 -1
  27. package/dist/components/create-feature.d.ts +11 -0
  28. package/dist/components/create-feature.js +11 -0
  29. package/dist/components/create-feature2.js +278 -0
  30. package/dist/components/crowdsource-reporter.js +324 -90
  31. package/dist/components/downloadUtils.js +1 -1
  32. package/dist/components/feature-list2.js +1 -0
  33. package/dist/components/layer-list2.js +38 -17
  34. package/dist/esm/{calcite-flow_4.entry.js → calcite-flow_5.entry.js} +286 -20
  35. package/dist/esm/card-manager_3.entry.js +1 -1
  36. package/dist/esm/crowdsource-reporter.entry.js +249 -33
  37. package/dist/esm/{downloadUtils-d070a467.js → downloadUtils-d297078f.js} +2 -2
  38. package/dist/esm/{index.es-d48535a2.js → index.es-3b4fa9d0.js} +1 -1
  39. package/dist/esm/loader.js +1 -1
  40. package/dist/esm/map-select-tools_3.entry.js +1 -1
  41. package/dist/esm/public-notification.entry.js +1 -1
  42. package/dist/esm/solutions-components.js +1 -1
  43. package/dist/solutions-components/demos/create-feature.html +90 -0
  44. package/dist/solutions-components/demos/crowdsource-reporter.html +26 -11
  45. package/dist/solutions-components/{p-f120ff40.entry.js → p-09ec8c8f.entry.js} +1 -1
  46. package/dist/solutions-components/{p-55b835a1.js → p-103c5318.js} +2 -2
  47. package/dist/solutions-components/{p-309cdea1.entry.js → p-57d49d15.entry.js} +1 -1
  48. package/dist/solutions-components/{p-b913a4fd.js → p-8ec25bf4.js} +1 -1
  49. package/dist/solutions-components/{p-f22ff57e.entry.js → p-921f21d5.entry.js} +1 -1
  50. package/dist/solutions-components/p-d5263cb9.entry.js +17 -0
  51. package/dist/solutions-components/p-ea17cefb.entry.js +6 -0
  52. package/dist/solutions-components/solutions-components.esm.js +1 -1
  53. package/dist/solutions-components/utils/downloadUtils.ts +1 -1
  54. package/dist/types/components/create-feature/create-feature.d.ts +125 -0
  55. package/dist/types/components/crowdsource-reporter/crowdsource-reporter.d.ts +146 -12
  56. package/dist/types/components/feature-list/feature-list.d.ts +1 -0
  57. package/dist/types/components/layer-list/layer-list.d.ts +6 -0
  58. package/dist/types/components.d.ts +102 -0
  59. package/dist/types/preact.d.ts +7 -0
  60. package/package.json +1 -1
  61. package/dist/solutions-components/p-2f162664.entry.js +0 -6
  62. package/dist/solutions-components/p-94ee3ef7.entry.js +0 -17
@@ -21,7 +21,8 @@
21
21
  import { Host, h } from "@stencil/core";
22
22
  import { getLocaleComponentStrings } from "../../utils/locale";
23
23
  import { loadModules } from "../../utils/loadModules";
24
- import { getAllLayers } from "../../utils/mapViewUtils";
24
+ import { getAllLayers, getLayerOrTable } from "../../utils/mapViewUtils";
25
+ import { queryFeaturesByID } from "../../utils/queryUtils";
25
26
  export class CrowdsourceReporter {
26
27
  constructor() {
27
28
  this.description = undefined;
@@ -34,6 +35,8 @@ export class CrowdsourceReporter {
34
35
  this.layers = undefined;
35
36
  this.loginTitle = undefined;
36
37
  this.mapView = undefined;
38
+ this.layerId = undefined;
39
+ this.objectId = undefined;
37
40
  this.reportButtonText = undefined;
38
41
  this.reportsHeader = undefined;
39
42
  this.reportSubmittedMessage = undefined;
@@ -51,6 +54,9 @@ export class CrowdsourceReporter {
51
54
  this._translations = undefined;
52
55
  this._hasValidLayers = false;
53
56
  this._selectedLayerName = undefined;
57
+ this._reportSubmitted = false;
58
+ this._showSubmitCancelButton = false;
59
+ this._featureCreationFailedErrorMsg = undefined;
54
60
  }
55
61
  //--------------------------------------------------------------------------
56
62
  //
@@ -82,6 +88,7 @@ export class CrowdsourceReporter {
82
88
  * @returns Promise when complete
83
89
  */
84
90
  async componentWillLoad() {
91
+ this._urlParamsLoaded = false;
85
92
  await this._initModules();
86
93
  await this._getTranslations();
87
94
  }
@@ -89,7 +96,8 @@ export class CrowdsourceReporter {
89
96
  * Renders the component.
90
97
  */
91
98
  render() {
92
- return (h(Host, null, h("div", null, h("calcite-shell", { "content-behind": true }, this._getReporter()))));
99
+ const themeClass = this.theme === "dark" ? "calcite-mode-dark" : "calcite-mode-light";
100
+ return (h(Host, null, this._reportSubmitted && h("calcite-alert", { "auto-close": true, class: themeClass, closable: true, icon: "check-circle", kind: "success", onCalciteAlertClose: () => { this._reportSubmitted = false; }, open: true, placement: "top" }, h("div", { slot: "title" }, this._translations.reportSubmit), h("div", { slot: "message" }, this._translations.submitMsg)), this._featureCreationFailedErrorMsg && h("calcite-alert", { "auto-close": true, class: themeClass, closable: true, icon: "x-octagon", kind: "danger", onCalciteAlertClose: () => { this._featureCreationFailedErrorMsg = ""; }, open: true, placement: "top" }, h("div", { slot: "title" }, this._translations.error), h("div", { slot: "message" }, this._featureCreationFailedErrorMsg)), h("div", null, h("calcite-shell", { "content-behind": true }, this._getReporter()))));
93
101
  }
94
102
  //--------------------------------------------------------------------------
95
103
  //
@@ -109,6 +117,20 @@ export class CrowdsourceReporter {
109
117
  ]);
110
118
  this.reactiveUtils = reactiveUtils;
111
119
  }
120
+ /**
121
+ * Set the selected layer id and layer name
122
+ * @param layerId string layerId of the selected layer
123
+ * @param layerName string layerName of the selected layer
124
+ */
125
+ setSelectedLayer(layerId, layerName) {
126
+ this._selectedLayerId = layerId;
127
+ this._selectedLayerName = layerName;
128
+ //show only current layer on map and hide other valid editable layers
129
+ //if layerId is empty then show all the layers on map
130
+ this._validLayers.forEach(layer => {
131
+ layer.set('visible', !layerId || (layer.id === layerId));
132
+ });
133
+ }
112
134
  /**
113
135
  * Get the reporter app functionality
114
136
  * @protected
@@ -126,6 +148,12 @@ export class CrowdsourceReporter {
126
148
  case "feature-details":
127
149
  renderLists.push(this.getFeatureDetailsFlowItem());
128
150
  break;
151
+ case "reporting-layer-list":
152
+ renderLists.push(this.getChooseCategoryFlowItem());
153
+ break;
154
+ case "feature-create":
155
+ renderLists.push(this.getFeatureCreateFlowItem());
156
+ break;
129
157
  }
130
158
  });
131
159
  const themeClass = this.theme === "dark" ? "calcite-mode-dark" : "calcite-mode-light";
@@ -142,34 +170,156 @@ export class CrowdsourceReporter {
142
170
  return (h("calcite-flow-item", { collapsed: this.isMobile && this._sidePanelCollapsed, heading: this.reportsHeader }, this._hasValidLayers &&
143
171
  h("calcite-action", { icon: "sort-ascending-arrow", slot: this.isMobile ? "header-menu-actions" : "header-actions-end", text: this._translations.sort, "text-enabled": this.isMobile }), this._hasValidLayers &&
144
172
  h("calcite-action", { icon: "filter", slot: this.isMobile ? "header-menu-actions" : "header-actions-end", text: this._translations.filter, "text-enabled": this.isMobile }), this.isMobile && this.getActionToExpandCollapsePanel(), this._hasValidLayers && this.enableNewReports &&
145
- h("calcite-button", { appearance: "secondary", slot: "footer", width: "full" }, this.reportButtonText), h("calcite-panel", { "full-height": true, "full-width": true }, h("layer-list", { class: "height-full", layers: this.layers, mapView: this.mapView, noLayerErrorMsg: this._translations.noLayerToDisplayErrorMsg, onLayerSelect: this.displayFeaturesList.bind(this), onLayersListLoaded: this.layerListLoaded.bind(this), showFeatureCount: true, showNextIcon: true }))));
173
+ h("calcite-button", { appearance: "secondary", onClick: this.navigateToChooseCategory.bind(this), slot: "footer", width: "full" }, this.reportButtonText), h("calcite-panel", { "full-height": true, "full-width": true }, h("layer-list", { class: "height-full", layers: this.layers, mapView: this.mapView, noLayerErrorMsg: this._translations.noLayerToDisplayErrorMsg, onLayerSelect: this.displayFeaturesList.bind(this), onLayersListLoaded: this.layerListLoaded.bind(this), ref: el => this._layerList = el, showFeatureCount: true, showNextIcon: true }))));
174
+ }
175
+ /**
176
+ * Get the layer list for creating a report
177
+ * @returns Choose category flow item
178
+ * @protected
179
+ */
180
+ getChooseCategoryFlowItem() {
181
+ return (h("calcite-flow-item", { collapsed: this.isMobile && this._sidePanelCollapsed, heading: this._translations.createReportHeader, onCalciteFlowItemBack: this.backFromSelectedPanel.bind(this) }, this.isMobile && this.getActionToExpandCollapsePanel(), h("div", { class: "width-full", slot: "footer" }, h("calcite-button", { appearance: "secondary", class: "footer-top-button footer-button", disabled: !this._selectedLayerId, onClick: this.navigateToCreateFeature.bind(this), width: "full" }, this._translations.next), h("calcite-button", { appearance: "outline", class: "footer-button", onClick: this.backFromSelectedPanel.bind(this), width: "full" }, this._translations.cancel)), h("calcite-panel", { "full-height": true, "full-width": true }, h("calcite-notice", { class: "notice-msg", icon: "lightbulb", kind: "success", open: true }, h("div", { slot: "message" }, this._translations.chooseCategoryMsg)), h("layer-list", { class: "height-full", layers: this.layers, mapView: this.mapView, noLayerErrorMsg: this._translations.noLayerToDisplayErrorMsg, onLayerSelect: this.highlightSelectedLayer.bind(this), showFeatureCount: false, showNextIcon: false }))));
182
+ }
183
+ /**
184
+ * Get Feature create form of the selected feature layer
185
+ * @returns feature create form
186
+ * @protected
187
+ */
188
+ getFeatureCreateFlowItem() {
189
+ return (h("calcite-flow-item", { collapsed: this.isMobile && this._sidePanelCollapsed, heading: this._selectedLayerName, onCalciteFlowItemBack: this.backFromCreateFeaturePanel.bind(this) }, this.isMobile && this.getActionToExpandCollapsePanel(), this._showSubmitCancelButton && h("div", { class: "width-full", slot: "footer" }, h("calcite-button", { appearance: "secondary", class: "footer-top-button footer-button", onClick: this.onSubmitButtonClick.bind(this), width: "full" }, this._translations.submit), h("calcite-button", { appearance: "outline", class: "footer-button", onClick: this.backFromCreateFeaturePanel.bind(this), width: "full" }, this._translations.cancel)), h("calcite-panel", { "full-height": true, "full-width": true }, h("calcite-notice", { class: "notice-msg", icon: "lightbulb", kind: "success", open: true }, h("div", { slot: "message" }, this._translations.featureEditFormInfoMsg)), h("create-feature", { customizeSubmit: true, mapView: this.mapView, onDrawComplete: this.onDrawComplete.bind(this), onEditingAttachment: this.showSubmitCancelButton.bind(this), onFail: this.createFeatureFailed.bind(this), onSuccess: this.onReportSubmitted.bind(this), ref: el => this._createFeature = el, selectedLayerId: this._selectedLayerId }))));
190
+ }
191
+ /**
192
+ * When drawing of incident location completed on map show the submit and cancel button
193
+ * @protected
194
+ */
195
+ onDrawComplete() {
196
+ this._showSubmitCancelButton = true;
197
+ }
198
+ /**
199
+ * When Add attachment panel is enabled hide the submit and cancel button
200
+ * @protected
201
+ */
202
+ showSubmitCancelButton(evt) {
203
+ this._showSubmitCancelButton = !evt.detail;
204
+ }
205
+ /**
206
+ * On back from create feature, call submit editor to destroy the Editor widget instance
207
+ * @protected
208
+ */
209
+ onSubmitButtonClick() {
210
+ if (this._createFeature) {
211
+ this._createFeature.submit();
212
+ }
213
+ }
214
+ /**
215
+ * On back from create feature, call close editor to destroy the Editor widget instance
216
+ * @protected
217
+ */
218
+ backFromCreateFeaturePanel() {
219
+ if (this._createFeature) {
220
+ this._createFeature.close();
221
+ }
222
+ this.backFromSelectedPanel();
223
+ }
224
+ /**
225
+ * On creating the feature is failed, show the error message
226
+ * @param evt Event which has feature failed message
227
+ * @protected
228
+ */
229
+ createFeatureFailed(evt) {
230
+ console.error(evt.detail);
231
+ this._featureCreationFailedErrorMsg = evt.detail.message;
232
+ }
233
+ /**
234
+ * On submit report navigate to the layer list home page and refresh the layer list
235
+ * @protected
236
+ */
237
+ onReportSubmitted() {
238
+ this._reportSubmitted = true;
239
+ this.navigateToHomePage();
240
+ }
241
+ /**
242
+ * Navigates to layer-list
243
+ * @protected
244
+ */
245
+ navigateToHomePage() {
246
+ if (this._createFeature) {
247
+ this._createFeature.close();
248
+ }
249
+ if (this._layerList) {
250
+ this._layerList.refresh();
251
+ }
252
+ this.setSelectedFeatures([]);
253
+ this._flowItems = ["layer-list"];
254
+ }
255
+ /**
256
+ * Update the selected layer id and name
257
+ * @param evt Event which has details of selected layerId and layerName
258
+ * @protected
259
+ */
260
+ highlightSelectedLayer(evt) {
261
+ this.setSelectedLayer(evt.detail.layerId, evt.detail.layerName);
262
+ }
263
+ /**
264
+ * On next button click open the feature create flow item
265
+ * @protected
266
+ */
267
+ async navigateToCreateFeature() {
268
+ this._showSubmitCancelButton = false;
269
+ this._flowItems = [...this._flowItems, "feature-create"];
270
+ }
271
+ /**
272
+ * On report an incident button click open the create a report panel with the layer list
273
+ * @protected
274
+ */
275
+ navigateToChooseCategory() {
276
+ this._flowItems = [...this._flowItems, "reporting-layer-list"];
146
277
  }
147
278
  /**
148
279
  * When layer list is loaded, we will receive the list of layers, if its means we don't have any valid layer to be listed
149
280
  * @param evt Event which has list of layers
150
281
  * @protected
151
282
  */
152
- layerListLoaded(evt) {
283
+ async layerListLoaded(evt) {
153
284
  const layersListed = evt.detail;
154
- this.handleMapClick(layersListed);
285
+ //consider only the layers listed in the layer-list component
286
+ const allMapLayers = await getAllLayers(this.mapView);
287
+ this._validLayers = [];
288
+ allMapLayers.forEach((eachLayer) => {
289
+ if (layersListed.includes(eachLayer.id)) {
290
+ this._validLayers.push(eachLayer);
291
+ }
292
+ });
293
+ //handleMap click on layer list loaded
294
+ this.handleMapClick();
295
+ //update the has valid layer state
155
296
  this._hasValidLayers = layersListed.length > 0;
297
+ //navigate to the feature details if URL params found
298
+ if (!this._urlParamsLoaded) {
299
+ this._urlParamsLoaded = true;
300
+ await this.loadFeatureFromURLParams();
301
+ }
156
302
  }
157
303
  /**On click of layer list item show feature list
158
304
  * @param evt Event which has details of selected layerId and layerName
159
305
  * @protected
160
306
  */
161
307
  displayFeaturesList(evt) {
162
- this._selectedLayerId = evt.detail.layerId;
163
- this._selectedLayerName = evt.detail.layerName;
308
+ this.setSelectedLayer(evt.detail.layerId, evt.detail.layerName);
164
309
  this._flowItems = [...this._flowItems, "feature-list"];
165
310
  }
166
311
  /**
167
- * On back from feature list navigate to the Layer list panel
312
+ * On back from selected panel navigate to the previous panel
168
313
  * @protected
169
314
  */
170
- backFromFeatureList() {
315
+ backFromSelectedPanel() {
171
316
  const updatedFlowItems = [...this._flowItems];
172
317
  updatedFlowItems.pop();
318
+ //Back to layer list, and return as the flowItems will be reset in navigateToHomePage
319
+ if (updatedFlowItems.length === 1) {
320
+ this.navigateToHomePage();
321
+ return;
322
+ }
173
323
  this._flowItems = [...updatedFlowItems];
174
324
  }
175
325
  /**
@@ -185,7 +335,7 @@ export class CrowdsourceReporter {
185
335
  * @param evt Event which has details of selected feature
186
336
  */
187
337
  async onFeatureSelectFromList(evt) {
188
- this._selectedFeature = [evt.detail];
338
+ this.setSelectedFeatures([evt.detail]);
189
339
  this._flowItems = [...this._flowItems, "feature-details"];
190
340
  }
191
341
  /**
@@ -196,26 +346,50 @@ export class CrowdsourceReporter {
196
346
  * @protected
197
347
  */
198
348
  getFeatureListFlowItem(layerId, layerName) {
199
- return (h("calcite-flow-item", { collapsed: this.isMobile && this._sidePanelCollapsed, heading: layerName, onCalciteFlowItemBack: this.backFromFeatureList.bind(this) }, h("calcite-action", { icon: "sort-ascending-arrow", slot: this.isMobile ? "header-menu-actions" : "header-actions-end", text: this._translations.sort, "text-enabled": this.isMobile }), h("calcite-action", { icon: "filter", slot: this.isMobile ? "header-menu-actions" : "header-actions-end", text: this._translations.filter, "text-enabled": this.isMobile }), this.isMobile && this.getActionToExpandCollapsePanel(), this.enableNewReports &&
200
- h("calcite-button", { appearance: "secondary", slot: "footer", width: "full" }, this.reportButtonText), h("calcite-panel", { "full-height": true }, h("feature-list", { class: "height-full", highlightOnMap: true, mapView: this.mapView, noFeaturesFoundMsg: this._translations.featureErrorMsg, onFeatureSelect: this.onFeatureSelectFromList.bind(this), pageSize: 30, selectedLayerId: layerId }))));
349
+ return (h("calcite-flow-item", { collapsed: this.isMobile && this._sidePanelCollapsed, heading: layerName, onCalciteFlowItemBack: this.backFromSelectedPanel.bind(this) }, h("calcite-action", { icon: "sort-ascending-arrow", slot: this.isMobile ? "header-menu-actions" : "header-actions-end", text: this._translations.sort, "text-enabled": this.isMobile }), h("calcite-action", { icon: "filter", slot: this.isMobile ? "header-menu-actions" : "header-actions-end", text: this._translations.filter, "text-enabled": this.isMobile }), this.isMobile && this.getActionToExpandCollapsePanel(), this.enableNewReports &&
350
+ h("calcite-button", { appearance: "secondary", onClick: this.navigateToCreateFeature.bind(this), slot: "footer", width: "full" }, this.reportButtonText), h("calcite-panel", { "full-height": true }, h("feature-list", { class: "height-full", highlightOnMap: true, mapView: this.mapView, noFeaturesFoundMsg: this._translations.featureErrorMsg, onFeatureSelect: this.onFeatureSelectFromList.bind(this), pageSize: 30, selectedLayerId: layerId }))));
201
351
  }
202
352
  /**
203
353
  * Returns the calcite-flow item for feature details
204
354
  * @returns Node
205
355
  */
206
356
  getFeatureDetailsFlowItem() {
207
- return (h("calcite-flow-item", { collapsed: this.isMobile && this._sidePanelCollapsed, heading: this._selectedLayerName, onCalciteFlowItemBack: this.backFromFeatureList.bind(this) }, this.isMobile && this.getActionToExpandCollapsePanel(), h("calcite-action", { icon: "share", slot: "header-actions-end", text: this._translations.share }), h("calcite-panel", { "full-height": true }, h("info-card", { allowEditing: false, graphics: this._selectedFeature, isLoading: false, isMobile: false, mapView: this.mapView, onSelectionChanged: this.featureDetailsChanged.bind(this), zoomAndScrollToSelected: true }))));
357
+ return (h("calcite-flow-item", { collapsed: this.isMobile && this._sidePanelCollapsed, heading: this._selectedLayerName, onCalciteFlowItemBack: this.backFromSelectedPanel.bind(this) }, this.isMobile && this.getActionToExpandCollapsePanel(), h("instant-apps-social-share", { autoUpdateShareUrl: false, embed: false, popoverButtonIconScale: "s", ref: el => this._shareNode = el, scale: "m", shareButtonColor: "neutral", shareButtonType: "action", slot: "header-actions-end", socialMedia: true, view: this.mapView }), h("calcite-panel", { "full-height": true }, h("info-card", { allowEditing: false, graphics: this._selectedFeature, isLoading: false, isMobile: false, mapView: this.mapView, onSelectionChanged: this.featureDetailsChanged.bind(this), zoomAndScrollToSelected: true }))));
358
+ }
359
+ /**
360
+ * Sets the selected features and updates the first feature as the current selected feature
361
+ * @param features Graphics array of the features selected
362
+ */
363
+ setSelectedFeatures(features) {
364
+ this._selectedFeature = features;
365
+ this.setCurrentFeature(this._selectedFeature.length ? this._selectedFeature[0] : null);
366
+ }
367
+ /**
368
+ * Set the object id of the current selected feature, and also updates the current selected layer details
369
+ * @param selectedFeature Graphic currently shown in feature details
370
+ */
371
+ setCurrentFeature(selectedFeature) {
372
+ if (selectedFeature && selectedFeature.layer) {
373
+ const layer = selectedFeature.layer;
374
+ this.setSelectedLayer(layer.id, layer.title);
375
+ this._currentFeatureId = selectedFeature.attributes[layer.objectIdField];
376
+ }
377
+ else {
378
+ this.setSelectedLayer('', '');
379
+ this._currentFeatureId = '';
380
+ }
381
+ this._updateShareURL();
208
382
  }
209
383
  /**
210
384
  * On Feature details change update the Layer title and the current selected layer id
211
385
  * @param evt Event hold the details of current feature graphic in the info-card
212
386
  */
213
387
  featureDetailsChanged(evt) {
214
- this._selectedLayerId = evt.detail[0].layer.id;
215
- this._selectedLayerName = evt.detail[0].layer.title;
388
+ this.setCurrentFeature(evt.detail[0]);
216
389
  }
217
390
  /**
218
391
  * Returns the action button to Expand/Collapse side panel in mobile mode
392
+ * @protected
219
393
  */
220
394
  getActionToExpandCollapsePanel() {
221
395
  return (h("calcite-action", { icon: this._sidePanelCollapsed ? "chevrons-up" : "chevrons-down", onClick: this.toggleSidePanel.bind(this), slot: "header-actions-end", text: this._sidePanelCollapsed ? this._translations.expand : this._translations.collapse }));
@@ -239,36 +413,26 @@ export class CrowdsourceReporter {
239
413
  * Handle map click event
240
414
  * @param layers Array of layerIds
241
415
  *
242
- * @protected
416
+ * @protected
243
417
  */
244
- handleMapClick(layers) {
418
+ handleMapClick() {
245
419
  if (this._mapClickHandle) {
246
420
  this._mapClickHandle.remove();
247
421
  }
248
- this._mapClickHandle = this.reactiveUtils.on(() => this.mapView, "click", (event) => {
249
- void this.onMapClick(event, layers);
250
- });
422
+ this._mapClickHandle = this.reactiveUtils.on(() => this.mapView, "click", this.onMapClick.bind(this));
251
423
  }
252
424
  /**
253
425
  * On map click do hitTest and get the clicked graphics of valid layers and show feature details
254
- * @param event
255
- * @param layers
426
+ * @param event IMapClick map click event details
256
427
  *
257
428
  * @protected
258
429
  */
259
- async onMapClick(event, layers) {
430
+ async onMapClick(event) {
260
431
  //disable map popup
261
432
  this.mapView.popupEnabled = false;
262
433
  // only include graphics from valid layers listed in the layer list widget
263
- const allMapLayers = await getAllLayers(this.mapView);
264
- const validLayers = [];
265
- allMapLayers.forEach((eachLayer) => {
266
- if (layers.includes(eachLayer.id)) {
267
- validLayers.push(eachLayer);
268
- }
269
- });
270
434
  const opts = {
271
- include: validLayers
435
+ include: this._validLayers
272
436
  };
273
437
  // Perform a hitTest on the View
274
438
  const hitTest = await this.mapView.hitTest(event, opts);
@@ -281,7 +445,7 @@ export class CrowdsourceReporter {
281
445
  }
282
446
  });
283
447
  //update the selectedFeature
284
- this._selectedFeature = clickedGraphics;
448
+ this.setSelectedFeatures(clickedGraphics);
285
449
  //if featureDetails not open then add it to the list else just reInit flowItems which will update details with newly selected features
286
450
  // eslint-disable-next-line unicorn/prefer-ternary
287
451
  if (this._flowItems.length && this._flowItems[this._flowItems.length - 1] !== "feature-details") {
@@ -301,6 +465,59 @@ export class CrowdsourceReporter {
301
465
  const messages = await getLocaleComponentStrings(this.el);
302
466
  this._translations = messages[0];
303
467
  }
468
+ /**
469
+ * Updates the share url for current selected feature
470
+ * @protected
471
+ */
472
+ _updateShareURL() {
473
+ var _a, _b;
474
+ const url = (_a = this._shareNode) === null || _a === void 0 ? void 0 : _a.shareUrl;
475
+ if (!url) {
476
+ return;
477
+ }
478
+ const urlObj = new URL(url);
479
+ //set the selected layers id
480
+ if (this._selectedLayerId) {
481
+ urlObj.searchParams.set("layerid", this._selectedLayerId);
482
+ }
483
+ else {
484
+ urlObj.searchParams.delete("layerid");
485
+ }
486
+ //Set the selected features objectid
487
+ if ((_b = this._selectedFeature) === null || _b === void 0 ? void 0 : _b.length) {
488
+ urlObj.searchParams.set("oid", this._currentFeatureId);
489
+ }
490
+ else {
491
+ urlObj.searchParams.delete("oid");
492
+ }
493
+ //update the url in share component
494
+ this._shareNode.shareUrl = urlObj.href;
495
+ }
496
+ /**
497
+ * Navigates to selected features detail based on the URL params
498
+ * @protected
499
+ */
500
+ async loadFeatureFromURLParams() {
501
+ if (this.layerId && this.objectId) {
502
+ const layer = await getLayerOrTable(this.mapView, this.layerId);
503
+ if (layer) {
504
+ // only query if we have some ids...query with no ids will result in all features being returned
505
+ const featureSet = await queryFeaturesByID([Number(this.objectId)], layer, [], false, this.mapView.spatialReference);
506
+ if (featureSet.length) {
507
+ //update the selectedFeature
508
+ this._selectedFeature = featureSet;
509
+ //if featureDetails not open then add it to the list else just reInit flowItems which will update details with newly selected features
510
+ // eslint-disable-next-line unicorn/prefer-ternary
511
+ if (this._flowItems.length && this._flowItems[this._flowItems.length - 1] !== "feature-details") {
512
+ this._flowItems = [...this._flowItems, "feature-details"];
513
+ }
514
+ else {
515
+ this._flowItems = [...this._flowItems];
516
+ }
517
+ }
518
+ }
519
+ }
520
+ }
304
521
  static get is() { return "crowdsource-reporter"; }
305
522
  static get originalStyleUrls() {
306
523
  return {
@@ -485,6 +702,40 @@ export class CrowdsourceReporter {
485
702
  "text": "esri/views/MapView: https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html"
486
703
  }
487
704
  },
705
+ "layerId": {
706
+ "type": "string",
707
+ "mutable": false,
708
+ "complexType": {
709
+ "original": "string",
710
+ "resolved": "string",
711
+ "references": {}
712
+ },
713
+ "required": false,
714
+ "optional": false,
715
+ "docs": {
716
+ "tags": [],
717
+ "text": "string: Layer id of the feature from URL params"
718
+ },
719
+ "attribute": "layer-id",
720
+ "reflect": false
721
+ },
722
+ "objectId": {
723
+ "type": "string",
724
+ "mutable": false,
725
+ "complexType": {
726
+ "original": "string",
727
+ "resolved": "string",
728
+ "references": {}
729
+ },
730
+ "required": false,
731
+ "optional": false,
732
+ "docs": {
733
+ "tags": [],
734
+ "text": "string: Object id of the feature from URL params"
735
+ },
736
+ "attribute": "object-id",
737
+ "reflect": false
738
+ },
488
739
  "reportButtonText": {
489
740
  "type": "string",
490
741
  "mutable": false,
@@ -701,7 +952,10 @@ export class CrowdsourceReporter {
701
952
  "_sidePanelCollapsed": {},
702
953
  "_translations": {},
703
954
  "_hasValidLayers": {},
704
- "_selectedLayerName": {}
955
+ "_selectedLayerName": {},
956
+ "_reportSubmitted": {},
957
+ "_showSubmitCancelButton": {},
958
+ "_featureCreationFailedErrorMsg": {}
705
959
  };
706
960
  }
707
961
  static get events() {
@@ -84,6 +84,7 @@ export class FeatureList {
84
84
  //--------------------------------------------------------------------------
85
85
  /**
86
86
  * Initialize the features list using the selected layer
87
+ * @protected
87
88
  */
88
89
  async initializeFeatureItems() {
89
90
  if (this._selectedLayer) {
@@ -36,6 +36,23 @@ export class LayerList {
36
36
  }
37
37
  //--------------------------------------------------------------------------
38
38
  //
39
+ // Watch handlers
40
+ //
41
+ //--------------------------------------------------------------------------
42
+ //--------------------------------------------------------------------------
43
+ //
44
+ // Methods (public)
45
+ //
46
+ //--------------------------------------------------------------------------
47
+ /**
48
+ * Refresh the layer list which will fetch the latest layer count and update the list
49
+ * @returns Promise that resolves when the operation is complete
50
+ */
51
+ async refresh() {
52
+ await this.setLayers();
53
+ }
54
+ //--------------------------------------------------------------------------
55
+ //
39
56
  // Functions (lifecycle)
40
57
  //
41
58
  //--------------------------------------------------------------------------
@@ -60,7 +77,7 @@ export class LayerList {
60
77
  render() {
61
78
  return (h(Fragment, null, this._isLoading && h("calcite-loader", { scale: "m" }), !this._isLoading && this.mapView && this._noLayersToDisplay &&
62
79
  h("calcite-notice", { class: "error-msg", icon: "layers-reference", kind: "danger", open: true }, h("div", { slot: "title" }, this._translations.error), h("div", { slot: "message" }, this.noLayerErrorMsg ? this.noLayerErrorMsg : this._translations.noLayerToDisplayErrorMsg)), !this._isLoading && this.mapView &&
63
- h("calcite-list", { "selection-appearance": "border", "selection-mode": this.showNextIcon ? "none" : "single" }, this.renderLayerList())));
80
+ h("calcite-list", { "selection-appearance": "border", "selection-mode": this.showNextIcon ? "none" : "single-persist" }, this.renderLayerList())));
64
81
  }
65
82
  //--------------------------------------------------------------------------
66
83
  //
@@ -87,21 +104,24 @@ export class LayerList {
87
104
  this._layerItemsHash = await getMapLayerHash(this.mapView, true);
88
105
  const allMapLayers = await getAllLayers(this.mapView);
89
106
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
90
- this.showFeatureCount && allMapLayers.forEach(async (eachLayer) => {
107
+ allMapLayers.forEach(async (eachLayer) => {
91
108
  var _a, _b;
92
109
  //TODO: checking editable condition could be configurable
93
- if ((eachLayer === null || eachLayer === void 0 ? void 0 : eachLayer.type) === "feature" && (eachLayer === null || eachLayer === void 0 ? void 0 : eachLayer.editingEnabled) && ((_b = (_a = eachLayer === null || eachLayer === void 0 ? void 0 : eachLayer.capabilities) === null || _a === void 0 ? void 0 : _a.operations) === null || _b === void 0 ? void 0 : _b.supportsUpdate)) {
94
- const q = eachLayer.createQuery();
95
- const result = eachLayer.queryFeatureCount(q);
96
- def.push(result);
97
- void result.then(async (resCount) => {
98
- const formattedCount = !isNaN(resCount) ? await formatNumber(resCount, {
99
- places: 0,
100
- api: 4,
101
- type: "decimal"
102
- }) : "";
103
- this._layerItemsHash[eachLayer.id].formattedFeatureCount = formattedCount;
104
- });
110
+ if ((eachLayer === null || eachLayer === void 0 ? void 0 : eachLayer.type) === "feature" && (eachLayer === null || eachLayer === void 0 ? void 0 : eachLayer.editingEnabled) && ((_b = (_a = eachLayer === null || eachLayer === void 0 ? void 0 : eachLayer.capabilities) === null || _a === void 0 ? void 0 : _a.operations) === null || _b === void 0 ? void 0 : _b.supportsAdd)) {
111
+ this._layerItemsHash[eachLayer.id].supportsAdd = true;
112
+ if (this.showFeatureCount) {
113
+ const q = eachLayer.createQuery();
114
+ const result = eachLayer.queryFeatureCount(q);
115
+ def.push(result);
116
+ void result.then(async (resCount) => {
117
+ const formattedCount = !isNaN(resCount) ? await formatNumber(resCount, {
118
+ places: 0,
119
+ api: 4,
120
+ type: "decimal"
121
+ }) : "";
122
+ this._layerItemsHash[eachLayer.id].formattedFeatureCount = formattedCount;
123
+ });
124
+ }
105
125
  }
106
126
  });
107
127
  await Promise.all(def).then(() => {
@@ -129,9 +149,9 @@ export class LayerList {
129
149
  var _a;
130
150
  const configuredLayers = ((_a = this.layers) === null || _a === void 0 ? void 0 : _a.length) > 0 ? this.layers : [];
131
151
  return Object.keys(hash).reduce((prev, cur) => {
132
- let showLayer = hash[cur].supportsUpdate;
152
+ let showLayer = hash[cur].supportsAdd;
133
153
  if ((configuredLayers === null || configuredLayers === void 0 ? void 0 : configuredLayers.length) > 0) {
134
- showLayer = configuredLayers.indexOf(cur) > -1 ? hash[cur].supportsUpdate : false;
154
+ showLayer = configuredLayers.indexOf(cur) > -1 ? hash[cur].supportsAdd : false;
135
155
  }
136
156
  if (showLayer) {
137
157
  prev.push(cur);
@@ -323,5 +343,29 @@ export class LayerList {
323
343
  }
324
344
  }];
325
345
  }
346
+ static get methods() {
347
+ return {
348
+ "refresh": {
349
+ "complexType": {
350
+ "signature": "() => Promise<void>",
351
+ "parameters": [],
352
+ "references": {
353
+ "Promise": {
354
+ "location": "global",
355
+ "id": "global::Promise"
356
+ }
357
+ },
358
+ "return": "Promise<void>"
359
+ },
360
+ "docs": {
361
+ "text": "Refresh the layer list which will fetch the latest layer count and update the list",
362
+ "tags": [{
363
+ "name": "returns",
364
+ "text": "Promise that resolves when the operation is complete"
365
+ }]
366
+ }
367
+ }
368
+ };
369
+ }
326
370
  static get elementRef() { return "el"; }
327
371
  }