@esri/solutions-components 0.6.32 → 0.6.34

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 (70) hide show
  1. package/dist/cjs/basemap-gallery_7.cjs.entry.js +14 -2
  2. package/dist/cjs/calcite-combobox_6.cjs.entry.js +1 -1
  3. package/dist/cjs/card-manager_3.cjs.entry.js +34 -20
  4. package/dist/cjs/crowdsource-manager.cjs.entry.js +13 -9
  5. package/dist/cjs/{downloadUtils-84024878.js → downloadUtils-b37689dd.js} +22 -2
  6. package/dist/cjs/{index.es-eb7cf427.js → index.es-83e253dc.js} +2 -2
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/cjs/map-select-tools_3.cjs.entry.js +2 -2
  9. package/dist/cjs/{mapViewUtils-786a219b.js → mapViewUtils-303bf42d.js} +1 -1
  10. package/dist/cjs/public-notification.cjs.entry.js +2 -2
  11. package/dist/cjs/solutions-components.cjs.js +1 -1
  12. package/dist/collection/components/crowdsource-manager/crowdsource-manager.css +8 -0
  13. package/dist/collection/components/crowdsource-manager/crowdsource-manager.js +13 -9
  14. package/dist/collection/components/floor-filter/floor-filter.js +2 -1
  15. package/dist/collection/components/layer-table/layer-table.js +38 -12
  16. package/dist/collection/components/map-card/map-card.css +5 -1
  17. package/dist/collection/components/map-card/map-card.js +44 -5
  18. package/dist/collection/components/map-tools/map-tools.js +15 -1
  19. package/dist/collection/demos/crowdsource-manager.html +5 -4
  20. package/dist/collection/utils/downloadUtils.js +20 -0
  21. package/dist/collection/utils/downloadUtils.ts +20 -0
  22. package/dist/collection/utils/queryUtils.js +1 -1
  23. package/dist/collection/utils/queryUtils.ts +1 -1
  24. package/dist/collection/utils/test/downloadUtils.spec.js +79 -5
  25. package/dist/collection/utils/test/downloadUtils.spec.tsx +84 -5
  26. package/dist/components/crowdsource-manager.js +13 -9
  27. package/dist/components/downloadUtils.js +20 -0
  28. package/dist/components/floor-filter2.js +2 -1
  29. package/dist/components/layer-table2.js +22 -12
  30. package/dist/components/map-card2.js +13 -6
  31. package/dist/components/map-tools2.js +14 -1
  32. package/dist/components/queryUtils.js +1 -1
  33. package/dist/esm/basemap-gallery_7.entry.js +14 -2
  34. package/dist/esm/calcite-combobox_6.entry.js +1 -1
  35. package/dist/esm/card-manager_3.entry.js +34 -20
  36. package/dist/esm/crowdsource-manager.entry.js +13 -9
  37. package/dist/esm/{downloadUtils-fa2b3718.js → downloadUtils-ddd7eeb7.js} +22 -2
  38. package/dist/esm/{index.es-cc671fd2.js → index.es-a53707d1.js} +2 -2
  39. package/dist/esm/loader.js +1 -1
  40. package/dist/esm/map-select-tools_3.entry.js +2 -2
  41. package/dist/esm/{mapViewUtils-8bfabd80.js → mapViewUtils-43c930f1.js} +1 -1
  42. package/dist/esm/polyfills/core-js.js +11 -0
  43. package/dist/esm/polyfills/dom.js +79 -0
  44. package/dist/esm/polyfills/es5-html-element.js +1 -0
  45. package/dist/esm/polyfills/index.js +34 -0
  46. package/dist/esm/polyfills/system.js +6 -0
  47. package/dist/esm/public-notification.entry.js +2 -2
  48. package/dist/esm/solutions-components.js +1 -1
  49. package/dist/solutions-components/demos/crowdsource-manager.html +5 -4
  50. package/dist/solutions-components/{p-e94c7cf2.js → p-05ba41f9.js} +1 -1
  51. package/dist/solutions-components/{p-ce3b40ca.entry.js → p-4792005c.entry.js} +1 -1
  52. package/dist/solutions-components/p-506db776.entry.js +6 -0
  53. package/dist/solutions-components/{p-86893d46.entry.js → p-50a3a887.entry.js} +1 -1
  54. package/dist/solutions-components/p-7b61f856.entry.js +6 -0
  55. package/dist/solutions-components/p-80243d29.entry.js +6 -0
  56. package/dist/solutions-components/{p-190c83b9.entry.js → p-978a26b3.entry.js} +1 -1
  57. package/dist/solutions-components/{p-37a58e04.js → p-b745143d.js} +3 -3
  58. package/dist/solutions-components/{p-53bc5fc1.js → p-f2194390.js} +1 -1
  59. package/dist/solutions-components/solutions-components.esm.js +1 -1
  60. package/dist/solutions-components/utils/downloadUtils.ts +20 -0
  61. package/dist/solutions-components/utils/queryUtils.ts +1 -1
  62. package/dist/solutions-components/utils/test/downloadUtils.spec.tsx +84 -5
  63. package/dist/types/components/layer-table/layer-table.d.ts +4 -0
  64. package/dist/types/components/map-card/map-card.d.ts +8 -0
  65. package/dist/types/components/map-tools/map-tools.d.ts +8 -0
  66. package/dist/types/components.d.ts +24 -0
  67. package/package.json +1 -1
  68. package/dist/solutions-components/p-792e171f.entry.js +0 -6
  69. package/dist/solutions-components/p-d44ad6c4.entry.js +0 -6
  70. package/dist/solutions-components/p-f2dcb05a.entry.js +0 -6
@@ -86,7 +86,8 @@ export class FloorFilter {
86
86
  * @protected
87
87
  */
88
88
  _initFloorFilter(view) {
89
- if (view && this.enabled && this.FloorFilter) {
89
+ var _a;
90
+ if (view && this.enabled && this.FloorFilter && ((_a = view === null || view === void 0 ? void 0 : view.map) === null || _a === void 0 ? void 0 : _a.floorInfo)) {
90
91
  if (!this.floorFilterWidget) {
91
92
  this.floorFilterWidget = new this.FloorFilter({
92
93
  container: this._floorFilterElement,
@@ -48,6 +48,7 @@ export class LayerTable {
48
48
  this.enableAutoRefresh = undefined;
49
49
  this.enableCSV = undefined;
50
50
  this.enableInlineEdit = undefined;
51
+ this.enableZoom = undefined;
51
52
  this.mapInfo = undefined;
52
53
  this.mapView = undefined;
53
54
  this.onlyShowUpdatableLayers = undefined;
@@ -294,13 +295,15 @@ export class LayerTable {
294
295
  _initToolInfos() {
295
296
  var _a;
296
297
  const featuresSelected = this._selectedIndexes.length > 0;
297
- this._toolInfos = [{
298
+ const featuresEmpty = this._allIds.length === 0;
299
+ this._toolInfos = [this.enableZoom ? {
298
300
  icon: "zoom-to-object",
299
301
  label: this._translations.zoom,
300
302
  func: () => this._zoom(),
301
303
  disabled: !featuresSelected,
302
304
  isOverflow: false
303
- }, ((_a = this.mapInfo) === null || _a === void 0 ? void 0 : _a.filters) ? {
305
+ } : undefined,
306
+ ((_a = this.mapInfo) === null || _a === void 0 ? void 0 : _a.filters) ? {
304
307
  icon: "filter",
305
308
  label: this._translations.filters,
306
309
  func: () => this._filter(),
@@ -330,27 +333,27 @@ export class LayerTable {
330
333
  icon: "list-check-all",
331
334
  func: () => this._selectAll(),
332
335
  label: this._translations.selectAll,
333
- disabled: false,
334
- isOverflow: true
336
+ disabled: featuresEmpty,
337
+ isOverflow: false
335
338
  }, {
336
339
  icon: "compare",
337
340
  func: () => this._switchSelected(),
338
341
  label: this._translations.switchSelected,
339
- disabled: false,
340
- isOverflow: true
342
+ disabled: featuresEmpty,
343
+ isOverflow: false
341
344
  }, {
342
345
  icon: "refresh",
343
346
  func: () => this._refresh(),
344
347
  label: this._translations.refresh,
345
348
  disabled: false,
346
- isOverflow: true
349
+ isOverflow: false
347
350
  },
348
351
  this.enableCSV ? {
349
352
  icon: "export",
350
353
  func: () => void this._exportToCSV(),
351
354
  label: this._translations.exportCSV,
352
- disabled: false,
353
- isOverflow: true
355
+ disabled: featuresEmpty,
356
+ isOverflow: false
354
357
  } : undefined];
355
358
  this._defaultVisibleToolSizeInfos = undefined;
356
359
  }
@@ -394,14 +397,20 @@ export class LayerTable {
394
397
  prev.push(cur.id);
395
398
  return prev;
396
399
  }, []);
400
+ let forceFinish = false;
397
401
  const controlsThatFit = [...this._defaultVisibleToolSizeInfos].reduce((prev, cur) => {
398
- if (skipControls.indexOf(cur.id) < 0 &&
402
+ if (!forceFinish && skipControls.indexOf(cur.id) < 0 &&
399
403
  (currentTools.indexOf(cur.id) > -1 || (controlsWidth + cur.width) <= toolbarWidth)) {
400
404
  if (currentTools.indexOf(cur.id) < 0) {
401
405
  controlsWidth += cur.width;
402
406
  }
403
407
  prev.push(cur);
404
408
  }
409
+ else if (skipControls.indexOf(cur.id) < 0 && (controlsWidth + cur.width) > toolbarWidth) {
410
+ // exit the first time we evalute this as true...otherwise it will add the next control that will fit
411
+ // and not preserve the overall order of controls
412
+ forceFinish = true;
413
+ }
405
414
  return prev;
406
415
  }, []);
407
416
  this._setControlsThatFit(controlsThatFit, skipControls);
@@ -480,9 +489,9 @@ export class LayerTable {
480
489
  */
481
490
  _getDropdown(id) {
482
491
  const dropdownItems = this._getDropdownItems();
483
- return (h("calcite-dropdown", { disabled: this._layer === undefined, id: "solutions-more" }, h("calcite-action", { appearance: "solid", id: id, label: "", slot: "trigger", text: "" }, h("calcite-button", { appearance: "transparent", iconEnd: "chevron-down", kind: "neutral" }, this._translations.more)), h("calcite-dropdown-group", { "selection-mode": "none" }, dropdownItems.map(item => {
492
+ return dropdownItems.length > 0 ? (h("calcite-dropdown", { disabled: this._layer === undefined, id: "solutions-more" }, h("calcite-action", { appearance: "solid", id: id, label: "", slot: "trigger", text: "" }, h("calcite-button", { appearance: "transparent", iconEnd: "chevron-down", kind: "neutral" }, this._translations.more)), h("calcite-dropdown-group", { "selection-mode": "none" }, dropdownItems.map(item => {
484
493
  return (h("calcite-dropdown-item", { iconStart: item.icon, onClick: item.func }, item.label));
485
- }))));
494
+ })))) : undefined;
486
495
  }
487
496
  /**
488
497
  * Get a list of toolInfos that should display in the dropdown
@@ -945,6 +954,23 @@ export class LayerTable {
945
954
  "attribute": "enable-inline-edit",
946
955
  "reflect": false
947
956
  },
957
+ "enableZoom": {
958
+ "type": "boolean",
959
+ "mutable": false,
960
+ "complexType": {
961
+ "original": "boolean",
962
+ "resolved": "boolean",
963
+ "references": {}
964
+ },
965
+ "required": false,
966
+ "optional": false,
967
+ "docs": {
968
+ "tags": [],
969
+ "text": "boolean: when true the zoom button will be enabled"
970
+ },
971
+ "attribute": "enable-zoom",
972
+ "reflect": false
973
+ },
948
974
  "mapInfo": {
949
975
  "type": "unknown",
950
976
  "mutable": false,
@@ -21,9 +21,13 @@
21
21
  }
22
22
 
23
23
  .map-height {
24
- height: calc(100% - 58px);
24
+ height: calc(100% - 51px);
25
25
  }
26
26
 
27
27
  .box-shadow {
28
28
  box-shadow: none !important;
29
29
  }
30
+
31
+ .visibility-hidden {
32
+ visibility: hidden;
33
+ }
@@ -32,12 +32,14 @@ export class MapCard {
32
32
  * string: the id of map currently displayed
33
33
  */
34
34
  this._loadedId = "";
35
+ this.enableHome = undefined;
35
36
  this.enableLegend = undefined;
36
37
  this.enableFloorFilter = undefined;
37
38
  this.enableFullscreen = undefined;
38
39
  this.enableSearch = undefined;
39
40
  this.enableBasemap = undefined;
40
41
  this.basemapConfig = undefined;
42
+ this.hidden = undefined;
41
43
  this.mapInfos = [];
42
44
  this.mapView = undefined;
43
45
  this._searchConfiguration = undefined;
@@ -64,7 +66,8 @@ export class MapCard {
64
66
  * Renders the component.
65
67
  */
66
68
  render() {
67
- return (h(Host, null, h("map-picker", { mapInfos: this.mapInfos }), h("div", { class: "map-height", ref: (el) => (this._mapDiv = el) }), h("map-tools", { basemapConfig: this.basemapConfig, class: "box-shadow", enableBasemap: this.enableBasemap, enableFloorFilter: this.enableFloorFilter, enableFullscreen: this.enableFullscreen, enableLegend: this.enableLegend, enableSearch: this.enableSearch, mapView: this.mapView, ref: (el) => this._mapTools = el, searchConfiguration: this._searchConfiguration })));
69
+ const mapClass = this.hidden ? "visibility-hidden" : "";
70
+ return (h(Host, null, h("map-picker", { mapInfos: this.mapInfos }), h("div", { class: `map-height ${mapClass}`, ref: (el) => (this._mapDiv = el) }), h("map-tools", { basemapConfig: this.basemapConfig, class: "box-shadow", enableBasemap: this.enableBasemap, enableFloorFilter: this.enableFloorFilter, enableFullscreen: this.enableFullscreen, enableLegend: this.enableLegend, enableSearch: this.enableSearch, mapView: this.mapView, ref: (el) => this._mapTools = el, searchConfiguration: this._searchConfiguration })));
68
71
  }
69
72
  //--------------------------------------------------------------------------
70
73
  //
@@ -116,10 +119,12 @@ export class MapCard {
116
119
  this._searchConfiguration = this._webMapInfo.searchConfiguration;
117
120
  this.beforeMapChanged.emit();
118
121
  await this.mapView.when(() => {
119
- const home = new this.Home({
120
- view: this.mapView
121
- });
122
- this.mapView.ui.add(home, { position: "top-left", index: 3 });
122
+ if (this.enableHome) {
123
+ const home = new this.Home({
124
+ view: this.mapView
125
+ });
126
+ this.mapView.ui.add(home, { position: "top-left", index: 3 });
127
+ }
123
128
  this.mapView.ui.add(this._mapTools, { position: "top-right", index: 0 });
124
129
  this.mapChanged.emit({
125
130
  id: id,
@@ -141,6 +146,23 @@ export class MapCard {
141
146
  }
142
147
  static get properties() {
143
148
  return {
149
+ "enableHome": {
150
+ "type": "boolean",
151
+ "mutable": false,
152
+ "complexType": {
153
+ "original": "boolean",
154
+ "resolved": "boolean",
155
+ "references": {}
156
+ },
157
+ "required": false,
158
+ "optional": false,
159
+ "docs": {
160
+ "tags": [],
161
+ "text": "boolean: when true the home widget will be available"
162
+ },
163
+ "attribute": "enable-home",
164
+ "reflect": false
165
+ },
144
166
  "enableLegend": {
145
167
  "type": "boolean",
146
168
  "mutable": false,
@@ -247,6 +269,23 @@ export class MapCard {
247
269
  "text": "IBasemapConfig: List of any basemaps to filter out from the basemap widget"
248
270
  }
249
271
  },
272
+ "hidden": {
273
+ "type": "boolean",
274
+ "mutable": false,
275
+ "complexType": {
276
+ "original": "boolean",
277
+ "resolved": "boolean",
278
+ "references": {}
279
+ },
280
+ "required": false,
281
+ "optional": false,
282
+ "docs": {
283
+ "tags": [],
284
+ "text": "boolean: When true the map display will be hidden"
285
+ },
286
+ "attribute": "hidden",
287
+ "reflect": false
288
+ },
250
289
  "mapInfos": {
251
290
  "type": "unknown",
252
291
  "mutable": false,
@@ -31,6 +31,7 @@ export class MapTools {
31
31
  this.layout = "vertical";
32
32
  this.mapView = undefined;
33
33
  this.searchConfiguration = undefined;
34
+ this._hasFloorInfo = false;
34
35
  this._translations = undefined;
35
36
  this._showTools = true;
36
37
  this._showBasemapWidget = false;
@@ -44,6 +45,15 @@ export class MapTools {
44
45
  // Watch handlers
45
46
  //
46
47
  //--------------------------------------------------------------------------
48
+ /**
49
+ * When the mapView loads check if it supports floor awareness
50
+ */
51
+ async mapViewWatchHandler() {
52
+ await this.mapView.when(() => {
53
+ var _a, _b;
54
+ this._hasFloorInfo = (_b = (_a = this.mapView) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.floorInfo;
55
+ });
56
+ }
47
57
  /**
48
58
  * When the _showBasemapWidget property is true display the basemap gallery
49
59
  */
@@ -157,7 +167,7 @@ export class MapTools {
157
167
  this._getActionGroup(fullscreenIcon, false, fullscreenTip, () => this._expand()) :
158
168
  undefined, this.enableBasemap ?
159
169
  this._getActionGroup("basemap", false, this._translations.basemap, () => this._toggleBasemapPicker()) :
160
- undefined, this.enableFloorFilter ?
170
+ undefined, this.enableFloorFilter && this._hasFloorInfo ?
161
171
  this._getActionGroup("urban-model", false, this._translations.floorFilter, () => this._toggleFloorFilter()) :
162
172
  undefined)), h("basemap-gallery", { basemapConfig: this.basemapConfig, class: basemapClass, mapView: this.mapView, ref: (el) => { this._basemapElement = el; } }), h("map-search", { class: searchClass, mapView: this.mapView, ref: (el) => { this._searchElement = el; }, resultGraphicEnabled: true, searchConfiguration: this.searchConfiguration }), h("map-legend", { class: legendClass, mapView: this.mapView, ref: (el) => { this._legendElement = el; } }), h("map-fullscreen", { class: fullscreenClass, mapView: this.mapView, ref: (el) => { this._fullscreenElement = el; } }), h("floor-filter", { class: floorFilterClass, enabled: this.enableFloorFilter, mapView: this.mapView, ref: (el) => { this._floorFilterElement = el; } })));
163
173
  }
@@ -432,6 +442,7 @@ export class MapTools {
432
442
  }
433
443
  static get states() {
434
444
  return {
445
+ "_hasFloorInfo": {},
435
446
  "_translations": {},
436
447
  "_showTools": {},
437
448
  "_showBasemapWidget": {},
@@ -444,6 +455,9 @@ export class MapTools {
444
455
  static get elementRef() { return "el"; }
445
456
  static get watchers() {
446
457
  return [{
458
+ "propName": "mapView",
459
+ "methodName": "mapViewWatchHandler"
460
+ }, {
447
461
  "propName": "_showBasemapWidget",
448
462
  "methodName": "_showBasemapWidgetWatchHandler"
449
463
  }, {
@@ -28,10 +28,9 @@
28
28
  }
29
29
  </style>
30
30
 
31
- <link
32
- rel="stylesheet"
33
- href="https://jsdev.arcgis.com/4.28/esri/themes/light/main.css"
34
- />
31
+ <link rel="stylesheet" href="https://jsdev.arcgis.com/4.28/esri/themes/light/main.css" />
32
+ <!-- <link rel="stylesheet" href="https://jsdev.arcgis.com/4.28/esri/themes/dark/main.css" /> -->
33
+
35
34
  <link rel="stylesheet" href="https://webapps-cdn.esri.com/CDN/fonts/v1.4.1/fonts.css" />
36
35
  <link rel="stylesheet" href="../solutions-components.css" type="text/css">
37
36
 
@@ -132,7 +131,9 @@
132
131
  </script>
133
132
  </head>
134
133
 
134
+ <!-- <body class="calcite-mode-dark" onload="addValues()"> -->
135
135
  <body onload="addValues()">
136
136
  <crowdsource-manager id="demo" class="crowdsource"/>
137
+ <!-- <crowdsource-manager id="demo" class="crowdsource" theme="dark"/> -->
137
138
  </body>
138
139
  </html>
@@ -514,6 +514,26 @@ export function _prepareAttributeValue(attributeValue, attributeType, attributeD
514
514
  // e.g., "12/31/1969, 4:00 PM"
515
515
  value = value.replace(/\xe2\x80\xaf/g, "");
516
516
  break;
517
+ case "date-only":
518
+ // Value is a string, e.g., "2020-12-08"
519
+ if (attributeFormat === null || attributeFormat === void 0 ? void 0 : attributeFormat.dateFormat) {
520
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat);
521
+ value = intl.formatDateOnly(value, dateFormatIntlOptions);
522
+ }
523
+ else {
524
+ value = intl.formatDateOnly(value);
525
+ }
526
+ break;
527
+ case "time-only":
528
+ // Value is a string, e.g., "14:51:44.2533333"
529
+ if (attributeFormat === null || attributeFormat === void 0 ? void 0 : attributeFormat.dateFormat) {
530
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat);
531
+ value = intl.formatTimeOnly(value, dateFormatIntlOptions);
532
+ }
533
+ else {
534
+ value = intl.formatTimeOnly(value);
535
+ }
536
+ break;
517
537
  case "double":
518
538
  case "integer":
519
539
  case "long":
@@ -688,6 +688,26 @@ export function _prepareAttributeValue(
688
688
  value = value.replace(/\xe2\x80\xaf/g, "");
689
689
  break;
690
690
 
691
+ case "date-only":
692
+ // Value is a string, e.g., "2020-12-08"
693
+ if (attributeFormat?.dateFormat) {
694
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat as any);
695
+ value = intl.formatDateOnly(value, dateFormatIntlOptions);
696
+ } else {
697
+ value = intl.formatDateOnly(value);
698
+ }
699
+ break;
700
+
701
+ case "time-only":
702
+ // Value is a string, e.g., "14:51:44.2533333"
703
+ if (attributeFormat?.dateFormat) {
704
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat as any);
705
+ value = intl.formatTimeOnly(value, dateFormatIntlOptions);
706
+ } else {
707
+ value = intl.formatTimeOnly(value);
708
+ }
709
+ break;
710
+
691
711
  case "double":
692
712
  case "integer":
693
713
  case "long":
@@ -49,7 +49,7 @@ export async function queryAllFeatures(start, layer, graphics) {
49
49
  */
50
50
  export async function queryAllIds(layer) {
51
51
  const query = layer.createQuery();
52
- query.where = "1=1";
52
+ query.where = layer.definitionExpression || "1=1";
53
53
  return await layer.queryObjectIds(query);
54
54
  }
55
55
  /**
@@ -59,7 +59,7 @@ export async function queryAllIds(
59
59
  layer: __esri.FeatureLayer
60
60
  ): Promise<number[]> {
61
61
  const query = layer.createQuery();
62
- query.where = "1=1";
62
+ query.where = layer.definitionExpression || "1=1";
63
63
  return await layer.queryObjectIds(query);
64
64
  }
65
65
 
@@ -803,21 +803,95 @@ describe("downloadUtils", () => {
803
803
  });
804
804
  });
805
805
  describe('_prepareAttributeValue', () => {
806
+ it('should format date attributes', () => {
807
+ const attributeValue = new Date('2022-02-01T00:00:00.000Z');
808
+ const attributeType = 'date';
809
+ const attributeDomain = null;
810
+ const attributeFormat = null;
811
+ const intl = {
812
+ formatDate: jest.fn().mockReturnValue('02/01/2022'),
813
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
814
+ };
815
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
816
+ expect(result).toEqual('02/01/2022');
817
+ expect(intl.formatDate).toHaveBeenCalledWith(attributeValue);
818
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
819
+ });
820
+ it('should format date-only attributes', () => {
821
+ const attributeValue = '2020-02-01';
822
+ const attributeType = 'date-only';
823
+ const attributeDomain = null;
824
+ const attributeFormat = null;
825
+ const intl = {
826
+ formatDateOnly: jest.fn().mockReturnValue('02/01/2022'),
827
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
828
+ };
829
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
830
+ expect(result).toEqual('02/01/2022');
831
+ expect(intl.formatDateOnly).toHaveBeenCalledWith(attributeValue);
832
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
833
+ });
834
+ it('should format time-only attributes', () => {
835
+ const attributeValue = '14:51:44.2533333';
836
+ const attributeType = 'time-only';
837
+ const attributeDomain = null;
838
+ const attributeFormat = null;
839
+ const intl = {
840
+ formatTimeOnly: jest.fn().mockReturnValue('14:41'),
841
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
842
+ };
843
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
844
+ expect(result).toEqual('14:41');
845
+ expect(intl.formatTimeOnly).toHaveBeenCalledWith(attributeValue);
846
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
847
+ });
806
848
  it('should format date attributes using the specified date format', () => {
807
- const attributeValue = new Date('2022-01-01T00:00:00.000Z');
849
+ const attributeValue = new Date('2022-02-01T00:00:00.000Z');
808
850
  const attributeType = 'date';
809
851
  const attributeDomain = null;
810
852
  const attributeFormat = {
811
- dateFormat: 'short-date'
853
+ dateFormat: 'shortdate'
812
854
  };
813
855
  const intl = {
814
- formatDate: jest.fn().mockReturnValue('01/01/2022'),
856
+ formatDate: jest.fn().mockReturnValue('02/01/2022'),
815
857
  convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
816
858
  };
817
859
  const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
818
- expect(result).toEqual('01/01/2022');
860
+ expect(result).toEqual('02/01/2022');
819
861
  expect(intl.formatDate).toHaveBeenCalledWith(attributeValue, {});
820
- expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('short-date');
862
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
863
+ });
864
+ it('should format date-only attributes using the specified date format', () => {
865
+ const attributeValue = '2020-02-01';
866
+ const attributeType = 'date-only';
867
+ const attributeDomain = null;
868
+ const attributeFormat = {
869
+ dateFormat: 'shortdate'
870
+ };
871
+ const intl = {
872
+ formatDateOnly: jest.fn().mockReturnValue('02/01/2022'),
873
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
874
+ };
875
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
876
+ expect(result).toEqual('02/01/2022');
877
+ expect(intl.formatDateOnly).toHaveBeenCalledWith(attributeValue, {});
878
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
879
+ });
880
+ it('should format time-only attributes using the specified date format', () => {
881
+ const attributeValue = '14:51:44.2533333';
882
+ const attributeType = 'time-only';
883
+ const attributeDomain = null;
884
+ const attributeFormat = {
885
+ dateFormat: 'shortdate'
886
+ };
887
+ const intl = {
888
+ formatTimeOnly: jest.fn().mockReturnValue('14:41'),
889
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
890
+ };
891
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
892
+ expect(result).toEqual('14:41');
893
+ expect(intl.formatTimeOnly).toHaveBeenCalledWith(attributeValue, {});
894
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
821
895
  });
822
896
  it('should format number attributes using the specified number format', () => {
823
897
  const attributeValue = 1234.5678;
@@ -924,21 +924,100 @@ describe("downloadUtils", () => {
924
924
 
925
925
  describe('_prepareAttributeValue', () => {
926
926
 
927
+ it('should format date attributes', () => {
928
+ const attributeValue = new Date('2022-02-01T00:00:00.000Z');
929
+ const attributeType = 'date';
930
+ const attributeDomain = null;
931
+ const attributeFormat = null;
932
+ const intl = {
933
+ formatDate: jest.fn().mockReturnValue('02/01/2022'),
934
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
935
+ };
936
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
937
+ expect(result).toEqual('02/01/2022');
938
+ expect(intl.formatDate).toHaveBeenCalledWith(attributeValue);
939
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
940
+ });
941
+
942
+ it('should format date-only attributes', () => {
943
+ const attributeValue = '2020-02-01';
944
+ const attributeType = 'date-only';
945
+ const attributeDomain = null;
946
+ const attributeFormat = null;
947
+ const intl = {
948
+ formatDateOnly: jest.fn().mockReturnValue('02/01/2022'),
949
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
950
+ };
951
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
952
+ expect(result).toEqual('02/01/2022');
953
+ expect(intl.formatDateOnly).toHaveBeenCalledWith(attributeValue);
954
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
955
+ });
956
+
957
+ it('should format time-only attributes', () => {
958
+ const attributeValue = '14:51:44.2533333';
959
+ const attributeType = 'time-only';
960
+ const attributeDomain = null;
961
+ const attributeFormat = null;
962
+ const intl = {
963
+ formatTimeOnly: jest.fn().mockReturnValue('14:41'),
964
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
965
+ };
966
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
967
+ expect(result).toEqual('14:41');
968
+ expect(intl.formatTimeOnly).toHaveBeenCalledWith(attributeValue);
969
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
970
+ });
971
+
927
972
  it('should format date attributes using the specified date format', () => {
928
- const attributeValue = new Date('2022-01-01T00:00:00.000Z');
973
+ const attributeValue = new Date('2022-02-01T00:00:00.000Z');
929
974
  const attributeType = 'date';
930
975
  const attributeDomain = null;
931
976
  const attributeFormat = {
932
- dateFormat: 'short-date'
977
+ dateFormat: 'shortdate'
933
978
  };
934
979
  const intl = {
935
- formatDate: jest.fn().mockReturnValue('01/01/2022'),
980
+ formatDate: jest.fn().mockReturnValue('02/01/2022'),
936
981
  convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
937
982
  };
938
983
  const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
939
- expect(result).toEqual('01/01/2022');
984
+ expect(result).toEqual('02/01/2022');
940
985
  expect(intl.formatDate).toHaveBeenCalledWith(attributeValue, {});
941
- expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('short-date');
986
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
987
+ });
988
+
989
+ it('should format date-only attributes using the specified date format', () => {
990
+ const attributeValue = '2020-02-01';
991
+ const attributeType = 'date-only';
992
+ const attributeDomain = null;
993
+ const attributeFormat = {
994
+ dateFormat: 'shortdate'
995
+ };
996
+ const intl = {
997
+ formatDateOnly: jest.fn().mockReturnValue('02/01/2022'),
998
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
999
+ };
1000
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
1001
+ expect(result).toEqual('02/01/2022');
1002
+ expect(intl.formatDateOnly).toHaveBeenCalledWith(attributeValue, {});
1003
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
1004
+ });
1005
+
1006
+ it('should format time-only attributes using the specified date format', () => {
1007
+ const attributeValue = '14:51:44.2533333';
1008
+ const attributeType = 'time-only';
1009
+ const attributeDomain = null;
1010
+ const attributeFormat = {
1011
+ dateFormat: 'shortdate'
1012
+ };
1013
+ const intl = {
1014
+ formatTimeOnly: jest.fn().mockReturnValue('14:41'),
1015
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
1016
+ };
1017
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
1018
+ expect(result).toEqual('14:41');
1019
+ expect(intl.formatTimeOnly).toHaveBeenCalledWith(attributeValue, {});
1020
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
942
1021
  });
943
1022
 
944
1023
  it('should format number attributes using the specified number format', () => {