@esri/solutions-components 0.7.9 → 0.7.11

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 (58) hide show
  1. package/dist/cjs/basemap-gallery_7.cjs.entry.js +1 -1
  2. package/dist/cjs/calcite-alert_3.cjs.entry.js +1 -1
  3. package/dist/cjs/calcite-combobox_6.cjs.entry.js +1 -1
  4. package/dist/cjs/card-manager_3.cjs.entry.js +154 -17
  5. package/dist/cjs/crowdsource-manager.cjs.entry.js +2 -1
  6. package/dist/cjs/{downloadUtils-95e4a5b2.js → downloadUtils-8f50633d.js} +2 -2
  7. package/dist/cjs/{index.es-a88403f8.js → index.es-140aa937.js} +2 -2
  8. package/dist/cjs/loader.cjs.js +1 -1
  9. package/dist/cjs/map-select-tools_3.cjs.entry.js +2 -2
  10. package/dist/cjs/{mapViewUtils-b7d9e71c.js → mapViewUtils-569e9644.js} +17 -0
  11. package/dist/cjs/public-notification.cjs.entry.js +2 -2
  12. package/dist/cjs/solutions-components.cjs.js +1 -1
  13. package/dist/collection/components/crowdsource-manager/crowdsource-manager.js +3 -1
  14. package/dist/collection/components/layer-table/layer-table.js +145 -16
  15. package/dist/collection/components/map-card/map-card.js +10 -0
  16. package/dist/collection/components/map-picker/map-picker.js +1 -1
  17. package/dist/collection/demos/crowdsource-manager.html +21 -3
  18. package/dist/collection/utils/queryUtils.js +16 -0
  19. package/dist/collection/utils/queryUtils.ts +21 -0
  20. package/dist/components/crowdsource-manager.js +3 -1
  21. package/dist/components/layer-table2.js +144 -16
  22. package/dist/components/map-card2.js +10 -0
  23. package/dist/components/map-picker2.js +1 -1
  24. package/dist/components/map-select-tools2.js +1 -1
  25. package/dist/components/queryUtils.js +17 -1
  26. package/dist/components/refine-selection2.js +1 -1
  27. package/dist/esm/basemap-gallery_7.entry.js +1 -1
  28. package/dist/esm/calcite-alert_3.entry.js +1 -1
  29. package/dist/esm/calcite-combobox_6.entry.js +1 -1
  30. package/dist/esm/card-manager_3.entry.js +154 -17
  31. package/dist/esm/crowdsource-manager.entry.js +2 -1
  32. package/dist/esm/{downloadUtils-83dd2143.js → downloadUtils-9dee8bc0.js} +2 -2
  33. package/dist/esm/{index.es-0c98e2f3.js → index.es-54e86c8e.js} +2 -2
  34. package/dist/esm/loader.js +1 -1
  35. package/dist/esm/map-select-tools_3.entry.js +2 -2
  36. package/dist/esm/{mapViewUtils-3ff1c264.js → mapViewUtils-066602d5.js} +17 -1
  37. package/dist/esm/public-notification.entry.js +2 -2
  38. package/dist/esm/solutions-components.js +1 -1
  39. package/dist/solutions-components/demos/crowdsource-manager.html +21 -3
  40. package/dist/solutions-components/{p-a9bbd352.entry.js → p-13bfc206.entry.js} +1 -1
  41. package/dist/solutions-components/{p-d6050d57.js → p-1bdd64a0.js} +2 -2
  42. package/dist/solutions-components/{p-b7e2c75b.js → p-531d91d6.js} +1 -1
  43. package/dist/solutions-components/p-623321ac.entry.js +6 -0
  44. package/dist/solutions-components/{p-dcd6e7b9.entry.js → p-6656c53e.entry.js} +1 -1
  45. package/dist/solutions-components/{p-a5d924a9.entry.js → p-683cded6.entry.js} +1 -1
  46. package/dist/solutions-components/{p-95ebc2e5.entry.js → p-c2b20b85.entry.js} +1 -1
  47. package/dist/solutions-components/p-c7ff24df.entry.js +6 -0
  48. package/dist/solutions-components/{p-b030a151.js → p-dfdb8411.js} +1 -1
  49. package/dist/solutions-components/p-e726ae50.entry.js +6 -0
  50. package/dist/solutions-components/solutions-components.esm.js +1 -1
  51. package/dist/solutions-components/utils/queryUtils.ts +21 -0
  52. package/dist/types/components/crowdsource-manager/crowdsource-manager.d.ts +4 -4
  53. package/dist/types/components/layer-table/layer-table.d.ts +44 -1
  54. package/dist/types/utils/queryUtils.d.ts +11 -0
  55. package/package.json +1 -1
  56. package/dist/solutions-components/p-c556ed60.entry.js +0 -6
  57. package/dist/solutions-components/p-c9b4d52f.entry.js +0 -6
  58. package/dist/solutions-components/p-f7870ec1.entry.js +0 -6
@@ -60,6 +60,7 @@ export class CrowdsourceManager {
60
60
  this._expandPopup = false;
61
61
  this._translations = undefined;
62
62
  this._layoutMode = ELayoutMode.GRID;
63
+ this._mapInfo = undefined;
63
64
  this._mapView = undefined;
64
65
  this._panelOpen = true;
65
66
  this._tableOnly = false;
@@ -388,7 +389,7 @@ export class CrowdsourceManager {
388
389
  return true;
389
390
  }
390
391
  });
391
- return mapInfo;
392
+ return Object.assign({}, mapInfo);
392
393
  }
393
394
  /**
394
395
  * Set the current map info when maps change
@@ -992,6 +993,7 @@ export class CrowdsourceManager {
992
993
  "_expandPopup": {},
993
994
  "_translations": {},
994
995
  "_layoutMode": {},
996
+ "_mapInfo": {},
995
997
  "_mapView": {},
996
998
  "_panelOpen": {},
997
999
  "_tableOnly": {}
@@ -22,7 +22,7 @@ import { Host, h } from "@stencil/core";
22
22
  import { loadModules } from "../../utils/loadModules";
23
23
  import { getLocaleComponentStrings } from "../../utils/locale";
24
24
  import { getLayerOrTable, goToSelection } from "../../utils/mapViewUtils";
25
- import { queryAllIds, queryFeaturesByGlobalID } from "../../utils/queryUtils";
25
+ import { queryAllIds, queryFeatureIds, queryFeaturesByGlobalID } from "../../utils/queryUtils";
26
26
  import * as downloadUtils from "../../utils/downloadUtils";
27
27
  import "@esri/instant-apps-components/dist/components/instant-apps-social-share";
28
28
  export class LayerTable {
@@ -31,6 +31,10 @@ export class LayerTable {
31
31
  * number[]: A list of all IDs for the current layer
32
32
  */
33
33
  this._allIds = [];
34
+ /**
35
+ * boolean: When true the ctrl key is currently pressed
36
+ */
37
+ this._ctrlIsPressed = false;
34
38
  /**
35
39
  * boolean: When true the default global id provided via url param has been honored and should now be ignored
36
40
  */
@@ -39,6 +43,14 @@ export class LayerTable {
39
43
  * boolean: When true the default OID provided via url param has been honored and should now be ignored
40
44
  */
41
45
  this._defaultOidHonored = false;
46
+ /**
47
+ * boolean: When true the shift key is currently pressed
48
+ */
49
+ this._shiftIsPressed = false;
50
+ /**
51
+ * boolean: When true any onChange handeling will be skipped
52
+ */
53
+ this._skipOnChange = false;
42
54
  /**
43
55
  * bool: When true the table is being sorted
44
56
  */
@@ -129,6 +141,15 @@ export class LayerTable {
129
141
  }
130
142
  });
131
143
  }
144
+ /**
145
+ * watch for changes in map info and recheck the tool infos
146
+ */
147
+ async mapInfoWatchHandler() {
148
+ var _a;
149
+ if (((_a = this._toolInfos) === null || _a === void 0 ? void 0 : _a.length) > 0) {
150
+ this._initToolInfos();
151
+ }
152
+ }
132
153
  /**
133
154
  * watch for changes in map view and get the first layer
134
155
  */
@@ -243,6 +264,8 @@ export class LayerTable {
243
264
  async componentDidLoad() {
244
265
  this._resizeObserver.observe(this._toolbar);
245
266
  document.onclick = (e) => this._handleDocumentClick(e);
267
+ document.onkeydown = (e) => this._handleKeyDown(e);
268
+ document.onkeyup = (e) => this._handleKeyUp(e);
246
269
  }
247
270
  /**
248
271
  * Called after the component is rendered
@@ -722,18 +745,8 @@ export class LayerTable {
722
745
  this._initColumnsInfo();
723
746
  this._checkEditEnabled();
724
747
  await this._table.when(() => {
725
- this._table.highlightIds.on("change", () => {
726
- // https://github.com/Esri/solutions-components/issues/365
727
- this._selectedIndexes = this._table.highlightIds.toArray().reverse();
728
- if (this._showOnlySelected) {
729
- if (this._featuresSelected()) {
730
- this._table.filterBySelection();
731
- }
732
- else {
733
- this._toggleShowSelected();
734
- }
735
- }
736
- this.featureSelectionChange.emit(this._selectedIndexes);
748
+ this._table.highlightIds.on("change", (evt) => {
749
+ void this._handleOnChange(evt);
737
750
  });
738
751
  this.reactiveUtils.watch(() => this._table.activeSortOrders, (sortOrders) => {
739
752
  var _a, _b, _c, _d;
@@ -743,6 +756,93 @@ export class LayerTable {
743
756
  });
744
757
  }
745
758
  }
759
+ async _handleOnChange(evt) {
760
+ const ids = [...this._table.highlightIds.toArray()];
761
+ if (!this._skipOnChange) {
762
+ if (!this._ctrlIsPressed && !this._shiftIsPressed) {
763
+ if (this._selectedIndexes.length > 0) {
764
+ this._skipOnChange = true;
765
+ // only readd in specific case where we have multiple selected and then click one of the currently selected
766
+ const reAdd = this._selectedIndexes.length > 1 && evt.removed.length === 1;
767
+ const newIndexes = reAdd ? evt.removed : ids.filter(id => this._selectedIndexes.indexOf(id) < 0);
768
+ this._clearSelection();
769
+ this._selectedIndexes = [...newIndexes];
770
+ if (newIndexes.length > 0) {
771
+ this._table.highlightIds.add(newIndexes[0]);
772
+ }
773
+ }
774
+ else {
775
+ // https://github.com/Esri/solutions-components/issues/365
776
+ this._selectedIndexes = ids.reverse();
777
+ }
778
+ }
779
+ else if (this._ctrlIsPressed) {
780
+ this._selectedIndexes = ids.reverse();
781
+ }
782
+ else if (this._shiftIsPressed) {
783
+ this._skipOnChange = true;
784
+ this._previousCurrentId = this._currentId;
785
+ this._currentId = [...this._table.highlightIds.toArray()].reverse()[0];
786
+ if (this._previousCurrentId !== this._currentId) {
787
+ // query the layer based on current sort and filters then grab between the current id and previous id
788
+ const orderBy = this._table.activeSortOrders.reduce((prev, cur) => {
789
+ prev.push(`${cur.fieldName} ${cur.direction}`);
790
+ return prev;
791
+ }, []);
792
+ const oids = await queryFeatureIds(this._layer, this._layer.definitionExpression, orderBy);
793
+ let isBetween = false;
794
+ const _start = this._table.viewModel.getObjectIdIndex(this._previousCurrentId);
795
+ const _end = this._table.viewModel.getObjectIdIndex(this._currentId);
796
+ const startIndex = _start < _end ? _start : _end;
797
+ const endIndex = _end > _start ? _end : _start;
798
+ this._selectedIndexes = oids.reduce((prev, cur) => {
799
+ const id = cur;
800
+ const index = this._table.viewModel.getObjectIdIndex(id);
801
+ if ((id === this._currentId || id === this._previousCurrentId)) {
802
+ isBetween = !isBetween;
803
+ if (prev.indexOf(id) < 0) {
804
+ prev.push(id);
805
+ }
806
+ }
807
+ // The oids are sorted so after we have reached the start or end oid add all ids even if the index is -1.
808
+ // Index of -1 will occur for features between the start and and oid if
809
+ // you select a row then scroll faster than the FeatureTable loads the data to select the next id
810
+ if (isBetween && prev.indexOf(id) < 0) {
811
+ prev.push(id);
812
+ }
813
+ // Also add index based check.
814
+ // In some cases the FeatureTable and Layer query will have differences in how null/undefined field values are sorted
815
+ if ((this._selectedIndexes.indexOf(id) > -1 || (index >= startIndex && index <= endIndex)) && prev.indexOf(id) < 0 && index > -1) {
816
+ prev.push(id);
817
+ }
818
+ return prev;
819
+ }, []);
820
+ this._table.highlightIds.addMany(this._selectedIndexes.filter(i => ids.indexOf(i) < 0));
821
+ }
822
+ }
823
+ this._finishOnChange();
824
+ }
825
+ else {
826
+ this._skipOnChange = false;
827
+ }
828
+ this._currentId = [...this._table.highlightIds.toArray()].reverse()[0];
829
+ }
830
+ /**
831
+ * Handle any updates after a selection change has occured and emit the results
832
+ *
833
+ * @returns void
834
+ */
835
+ _finishOnChange() {
836
+ if (this._showOnlySelected) {
837
+ if (this._featuresSelected()) {
838
+ this._table.filterBySelection();
839
+ }
840
+ else {
841
+ this._toggleShowSelected();
842
+ }
843
+ }
844
+ this.featureSelectionChange.emit(this._selectedIndexes);
845
+ }
746
846
  /**
747
847
  * Reset basic table props
748
848
  *
@@ -878,6 +978,24 @@ export class LayerTable {
878
978
  }
879
979
  }
880
980
  }
981
+ /**
982
+ * Keep track of key down for ctrl and shift
983
+ *
984
+ * @returns void
985
+ */
986
+ _handleKeyDown(e) {
987
+ this._ctrlIsPressed = e.ctrlKey;
988
+ this._shiftIsPressed = e.shiftKey;
989
+ }
990
+ /**
991
+ * Keep track of key up for ctrl and shift
992
+ *
993
+ * @returns void
994
+ */
995
+ _handleKeyUp(e) {
996
+ this._ctrlIsPressed = e.ctrlKey;
997
+ this._shiftIsPressed = e.shiftKey;
998
+ }
881
999
  /**
882
1000
  * Show filter component in modal
883
1001
  *
@@ -885,15 +1003,19 @@ export class LayerTable {
885
1003
  */
886
1004
  _filterModal() {
887
1005
  var _a, _b, _c;
888
- return (h("calcite-modal", { "aria-labelledby": "modal-title", kind: "brand", onCalciteModalClose: () => this._closeFilter(), open: this._filterOpen, widthScale: "s" }, h("div", { class: "display-flex align-center", id: "modal-title", slot: "header" }, (_b = (_a = this._translations) === null || _a === void 0 ? void 0 : _a.filter) === null || _b === void 0 ? void 0 : _b.replace("{{title}}", (_c = this._layer) === null || _c === void 0 ? void 0 : _c.title)), h("div", { slot: "content" }, h("instant-apps-filter-list", { autoUpdateUrl: false, closeBtn: true, closeBtnOnClick: () => this._closeFilter(), layerExpressions: this._layerExpressions, ref: (el) => this._filterList = el, view: this.mapView }))));
1006
+ return (h("calcite-modal", { "aria-labelledby": "modal-title", kind: "brand", onCalciteModalClose: async () => this._closeFilter(), open: this._filterOpen, widthScale: "s" }, h("div", { class: "display-flex align-center", id: "modal-title", slot: "header" }, (_b = (_a = this._translations) === null || _a === void 0 ? void 0 : _a.filter) === null || _b === void 0 ? void 0 : _b.replace("{{title}}", (_c = this._layer) === null || _c === void 0 ? void 0 : _c.title)), h("div", { slot: "content" }, h("instant-apps-filter-list", { autoUpdateUrl: false, closeBtn: true, closeBtnOnClick: async () => this._closeFilter(), layerExpressions: this._layerExpressions, ref: (el) => this._filterList = el, view: this.mapView }))));
889
1007
  }
890
1008
  /**
891
1009
  * Close the filter modal
892
1010
  *
893
1011
  * @returns void
894
1012
  */
895
- _closeFilter() {
896
- this._filterOpen = false;
1013
+ async _closeFilter() {
1014
+ if (this._filterOpen) {
1015
+ // reset allIds
1016
+ this._allIds = await queryAllIds(this._layer);
1017
+ this._filterOpen = false;
1018
+ }
897
1019
  }
898
1020
  /**
899
1021
  * Show delete confirmation message
@@ -966,8 +1088,10 @@ export class LayerTable {
966
1088
  _selectAll() {
967
1089
  const ids = this._allIds;
968
1090
  this._table.highlightIds.removeAll();
1091
+ this._skipOnChange = true;
969
1092
  this._table.highlightIds.addMany(ids);
970
1093
  this._selectedIndexes = ids;
1094
+ this._finishOnChange();
971
1095
  }
972
1096
  /**
973
1097
  * Toggle the show only selected flag
@@ -1027,8 +1151,10 @@ export class LayerTable {
1027
1151
  }
1028
1152
  return prev;
1029
1153
  }, []).sort((a, b) => a - b);
1154
+ this._skipOnChange = true;
1030
1155
  this._table.highlightIds.addMany(ids);
1031
1156
  this._selectedIndexes = ids;
1157
+ this._finishOnChange();
1032
1158
  }
1033
1159
  /**
1034
1160
  * Export all selected rows as CSV
@@ -1513,6 +1639,9 @@ export class LayerTable {
1513
1639
  }, {
1514
1640
  "propName": "_controlsThatFit",
1515
1641
  "methodName": "_controlsThatFitWatchHandler"
1642
+ }, {
1643
+ "propName": "mapInfo",
1644
+ "methodName": "mapInfoWatchHandler"
1516
1645
  }, {
1517
1646
  "propName": "mapView",
1518
1647
  "methodName": "mapViewWatchHandler"
@@ -126,6 +126,7 @@ export class MapCard {
126
126
  // on the first render use the default webmap id if provided otherwise use the first child of the provided mapInfos
127
127
  const loadDefaultMap = !this._defaultWebmapHonored && this.defaultWebmapId;
128
128
  const defaultMap = (_a = this.mapInfos) === null || _a === void 0 ? void 0 : _a.filter(i => i.id === this.defaultWebmapId);
129
+ const mapConfigChanged = JSON.stringify(webMapInfo) !== JSON.stringify(this._webMapInfo);
129
130
  this._webMapInfo = loadDefaultMap && defaultMap ? defaultMap[0] :
130
131
  !(webMapInfo === null || webMapInfo === void 0 ? void 0 : webMapInfo.id) && this.mapInfos.length > 0 ? this.mapInfos[0] : webMapInfo;
131
132
  const id = this._webMapInfo.id;
@@ -156,6 +157,15 @@ export class MapCard {
156
157
  this._defaultWebmapHonored = true;
157
158
  this._mapPicker.setMapByID(id);
158
159
  }
160
+ else if (mapConfigChanged) {
161
+ // Map is the same so no need to reload but we need to update for any changes from the config
162
+ this._searchConfiguration = this._webMapInfo.searchConfiguration;
163
+ this.beforeMapChanged.emit();
164
+ this.mapChanged.emit({
165
+ id: id,
166
+ mapView: this.mapView
167
+ });
168
+ }
159
169
  }
160
170
  /**
161
171
  * Add/remove the home widget base on enableHome prop
@@ -132,7 +132,7 @@ export class MapPicker {
132
132
  * @protected
133
133
  */
134
134
  _getMapNameList(show) {
135
- const listClass = show ? "map-list" : "display-none";
135
+ const listClass = show ? "map-list border-bottom-1" : "display-none";
136
136
  return (h("div", { class: listClass }, h("calcite-list", { id: "mapList", ref: (el) => this._list = el, selectionAppearance: "border", selectionMode: "single" }, this.mapInfos.map(mapInfo => {
137
137
  return (h("calcite-list-item", { label: mapInfo.name, onClick: () => this._webMapSelected(mapInfo), selected: mapInfo.id === this._loadedId, value: mapInfo.id }));
138
138
  }))));
@@ -94,10 +94,10 @@
94
94
  operator: " AND ",
95
95
  expressions: [
96
96
  {
97
- definitionExpression: "OBJECTID > 700",
97
+ definitionExpression: "OBJECTID > 690",
98
98
  id: 1701793260225,
99
99
  index: 0,
100
- name: "greater than 700",
100
+ name: "greater than 690",
101
101
  active: false
102
102
  }
103
103
  ]
@@ -145,7 +145,25 @@
145
145
  }, {
146
146
  id: "b422923b7a4c4958b9788118255f2f0a",
147
147
  name: "Floor aware map"
148
- }]
148
+ }, {
149
+ id: "5dc8ae351ff34280a75f7ffe1115b36b",
150
+ name: "Standalone table",
151
+ filterConfig: {
152
+ "mapId": "5dc8ae351ff34280a75f7ffe1115b36b",
153
+ "layerExpressions": [{
154
+ "id": "18c4a8cda15-layer-2",
155
+ "title": "Table_1",
156
+ "operator": " AND ",
157
+ "expressions": [{
158
+ "definitionExpression": "OBJECTID > 14",
159
+ "id": 1702486334825,
160
+ "index": 0,
161
+ "name": "> 14",
162
+ "active": false
163
+ }]
164
+ }]
165
+ }
166
+ }, ]
149
167
  ];
150
168
  }
151
169
  </script>
@@ -165,6 +165,22 @@ export async function queryFeaturesByGeometry(start, layer, geometry, featuresCo
165
165
  queryFeaturesByGeometry(start += num, layer, geometry, featuresCollection) :
166
166
  Promise.resolve(featuresCollection);
167
167
  }
168
+ /**
169
+ * Query the layer for feature ids that match the provided where clause.
170
+ * If no where clause is provided all features will be returned.
171
+ *
172
+ * @param layer the layer to retrieve features from
173
+ * @param where the where clause for the query
174
+ * @param orderBy any sort order to apply to the query
175
+ *
176
+ * @returns Promise with the ids from the layer that match the where and are sorted as defined by orderBy
177
+ */
178
+ export async function queryFeatureIds(layer, where, orderBy) {
179
+ const query = layer.createQuery();
180
+ query.where = where ? where : "1=1";
181
+ query.orderByFields = orderBy;
182
+ return await layer.queryObjectIds(query);
183
+ }
168
184
  /**
169
185
  * Query the layer for the extent of features with the provided OIDs
170
186
  *
@@ -212,6 +212,27 @@ export async function queryFeaturesByGeometry(
212
212
  Promise.resolve(featuresCollection);
213
213
  }
214
214
 
215
+ /**
216
+ * Query the layer for feature ids that match the provided where clause.
217
+ * If no where clause is provided all features will be returned.
218
+ *
219
+ * @param layer the layer to retrieve features from
220
+ * @param where the where clause for the query
221
+ * @param orderBy any sort order to apply to the query
222
+ *
223
+ * @returns Promise with the ids from the layer that match the where and are sorted as defined by orderBy
224
+ */
225
+ export async function queryFeatureIds(
226
+ layer: any,
227
+ where: any,
228
+ orderBy: any
229
+ ): Promise<number[]> {
230
+ const query = layer.createQuery();
231
+ query.where = where ? where : "1=1";
232
+ query.orderByFields = orderBy;
233
+ return await layer.queryObjectIds(query);
234
+ }
235
+
215
236
  /**
216
237
  * Query the layer for the extent of features with the provided OIDs
217
238
  *
@@ -106,6 +106,7 @@ const CrowdsourceManager$1 = /*@__PURE__*/ proxyCustomElement(class CrowdsourceM
106
106
  this._expandPopup = false;
107
107
  this._translations = undefined;
108
108
  this._layoutMode = ELayoutMode.GRID;
109
+ this._mapInfo = undefined;
109
110
  this._mapView = undefined;
110
111
  this._panelOpen = true;
111
112
  this._tableOnly = false;
@@ -434,7 +435,7 @@ const CrowdsourceManager$1 = /*@__PURE__*/ proxyCustomElement(class CrowdsourceM
434
435
  return true;
435
436
  }
436
437
  });
437
- return mapInfo;
438
+ return Object.assign({}, mapInfo);
438
439
  }
439
440
  /**
440
441
  * Set the current map info when maps change
@@ -524,6 +525,7 @@ const CrowdsourceManager$1 = /*@__PURE__*/ proxyCustomElement(class CrowdsourceM
524
525
  "_expandPopup": [32],
525
526
  "_translations": [32],
526
527
  "_layoutMode": [32],
528
+ "_mapInfo": [32],
527
529
  "_mapView": [32],
528
530
  "_panelOpen": [32],
529
531
  "_tableOnly": [32]