@scality/data-browser-library 1.0.3 → 1.0.5

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 (51) hide show
  1. package/dist/components/DataBrowserUI.js +18 -8
  2. package/dist/components/__tests__/BucketList.test.js +74 -1
  3. package/dist/components/__tests__/ObjectList.test.js +94 -2
  4. package/dist/components/buckets/BucketCreate.d.ts +1 -0
  5. package/dist/components/buckets/BucketCreate.js +57 -7
  6. package/dist/components/buckets/BucketDetails.js +0 -1
  7. package/dist/components/buckets/BucketLifecycleFormPage.js +209 -213
  8. package/dist/components/buckets/BucketList.js +25 -4
  9. package/dist/components/buckets/BucketReplicationFormPage.js +9 -3
  10. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +1 -1
  11. package/dist/components/buckets/notifications/BucketNotificationList.js +1 -1
  12. package/dist/components/objects/DeleteObjectButton.d.ts +1 -0
  13. package/dist/components/objects/DeleteObjectButton.js +11 -5
  14. package/dist/components/objects/ObjectDetails/FormComponents.d.ts +9 -0
  15. package/dist/components/objects/ObjectDetails/FormComponents.js +37 -0
  16. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +182 -204
  17. package/dist/components/objects/ObjectDetails/ObjectSummary.js +22 -5
  18. package/dist/components/objects/ObjectDetails/ObjectTags.js +109 -154
  19. package/dist/components/objects/ObjectDetails/__tests__/ObjectMetadata.test.d.ts +1 -0
  20. package/dist/components/objects/ObjectDetails/__tests__/ObjectMetadata.test.js +230 -0
  21. package/dist/components/objects/ObjectDetails/__tests__/ObjectTags.test.d.ts +1 -0
  22. package/dist/components/objects/ObjectDetails/__tests__/ObjectTags.test.js +342 -0
  23. package/dist/components/objects/ObjectDetails/__tests__/formUtils.test.d.ts +1 -0
  24. package/dist/components/objects/ObjectDetails/__tests__/formUtils.test.js +202 -0
  25. package/dist/components/objects/ObjectDetails/index.d.ts +2 -1
  26. package/dist/components/objects/ObjectDetails/index.js +12 -16
  27. package/dist/components/objects/ObjectList.d.ts +3 -2
  28. package/dist/components/objects/ObjectList.js +204 -104
  29. package/dist/components/objects/ObjectPage.js +22 -5
  30. package/dist/components/ui/ArrayFieldActions.js +0 -2
  31. package/dist/components/ui/FilterFormSection.js +17 -36
  32. package/dist/components/ui/FormGrid.d.ts +7 -0
  33. package/dist/components/ui/FormGrid.js +37 -0
  34. package/dist/components/ui/Table.elements.js +1 -0
  35. package/dist/config/types.d.ts +45 -2
  36. package/dist/hooks/__tests__/usePresigningS3Client.test.d.ts +1 -0
  37. package/dist/hooks/__tests__/usePresigningS3Client.test.js +104 -0
  38. package/dist/hooks/factories/index.d.ts +1 -1
  39. package/dist/hooks/factories/index.js +2 -2
  40. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +2 -1
  41. package/dist/hooks/factories/useCreateS3MutationHook.js +10 -3
  42. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +1 -0
  43. package/dist/hooks/factories/useCreateS3QueryHook.js +9 -6
  44. package/dist/hooks/index.d.ts +1 -0
  45. package/dist/hooks/index.js +2 -1
  46. package/dist/hooks/presignedOperations.js +4 -4
  47. package/dist/hooks/useBucketLocations.d.ts +6 -0
  48. package/dist/hooks/useBucketLocations.js +45 -0
  49. package/dist/hooks/usePresigningS3Client.d.ts +13 -0
  50. package/dist/hooks/usePresigningS3Client.js +21 -0
  51. package/package.json +4 -4
@@ -1,5 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { AppContainer } from "@scality/core-ui";
2
+ import { AppContainer, ScrollbarWrapper } from "@scality/core-ui";
3
3
  import { Route, Routes } from "react-router";
4
4
  import styled_components from "styled-components";
5
5
  import { DataBrowserUICustomizationProvider } from "../contexts/DataBrowserUICustomizationContext.js";
@@ -12,14 +12,22 @@ const RoutesContainer = styled_components.div`
12
12
  width: 100%;
13
13
  overflow: hidden;
14
14
  `;
15
+ const HeaderSlot = styled_components.div`
16
+ &:has([data-header-content]:empty) {
17
+ display: none;
18
+ }
19
+ `;
15
20
  const DataBrowserUIContent = ({ header })=>{
16
21
  useS3ConfigSwitch();
17
22
  return /*#__PURE__*/ jsx(AppContainer, {
18
23
  children: /*#__PURE__*/ jsxs(Fragment, {
19
24
  children: [
20
- header && /*#__PURE__*/ jsx(AppContainer.ContextContainer, {
21
- children: /*#__PURE__*/ jsx("div", {
22
- children: header
25
+ header && /*#__PURE__*/ jsx(HeaderSlot, {
26
+ children: /*#__PURE__*/ jsx(AppContainer.ContextContainer, {
27
+ children: /*#__PURE__*/ jsx("div", {
28
+ "data-header-content": true,
29
+ children: header
30
+ })
23
31
  })
24
32
  }),
25
33
  /*#__PURE__*/ jsx(AppContainer.MainContent, {
@@ -90,10 +98,12 @@ const DataBrowserUIContent = ({ header })=>{
90
98
  })
91
99
  });
92
100
  };
93
- const DataBrowserUI = (props)=>/*#__PURE__*/ jsx(DataBrowserUICustomizationProvider, {
94
- config: props,
95
- children: /*#__PURE__*/ jsx(DataBrowserUIContent, {
96
- header: props.header
101
+ const DataBrowserUI = (props)=>/*#__PURE__*/ jsx(ScrollbarWrapper, {
102
+ children: /*#__PURE__*/ jsx(DataBrowserUICustomizationProvider, {
103
+ config: props,
104
+ children: /*#__PURE__*/ jsx(DataBrowserUIContent, {
105
+ header: props.header
106
+ })
97
107
  })
98
108
  });
99
109
  export { DataBrowserUI };
@@ -3,6 +3,7 @@ import { fireEvent, render, screen } from "@testing-library/react";
3
3
  import { MemoryRouter } from "react-router";
4
4
  import { createTestWrapper, mockOffsetSize } from "../../test/testUtils.js";
5
5
  import { BucketList } from "../buckets/BucketList.js";
6
+ import * as __rspack_external__hooks_index_js_a0d26731 from "../../hooks/index.js";
6
7
  import * as __rspack_external__contexts_DataBrowserUICustomizationContext_js_f267b01c from "../../contexts/DataBrowserUICustomizationContext.js";
7
8
  const mockUseDataBrowserUICustomization = (config = {})=>{
8
9
  jest.spyOn(__rspack_external__contexts_DataBrowserUICustomizationContext_js_f267b01c, 'useDataBrowserUICustomization').mockReturnValue(config);
@@ -37,6 +38,7 @@ describe('BucketList', ()=>{
37
38
  jest.clearAllMocks();
38
39
  mockOffsetSize(800, 600);
39
40
  mockUseDataBrowserUICustomization({});
41
+ jest.spyOn(__rspack_external__hooks_index_js_a0d26731, 'useBucketLocations').mockReturnValue(new Map());
40
42
  });
41
43
  it('shows a table with proper headers', ()=>{
42
44
  renderBucketList({
@@ -76,7 +78,7 @@ describe('BucketList', ()=>{
76
78
  });
77
79
  const rows = screen.getAllByRole('row');
78
80
  fireEvent.click(rows[1]);
79
- expect(onBucketSelect).toHaveBeenCalledWith('test-bucket-3');
81
+ expect(onBucketSelect).toHaveBeenCalledWith('test-bucket-1');
80
82
  });
81
83
  it('shows selected bucket when selectedBucketName is provided', ()=>{
82
84
  renderBucketList({
@@ -205,6 +207,77 @@ describe('BucketList', ()=>{
205
207
  fireEvent.click(bucketName.closest('[role="row"]') || bucketName);
206
208
  expect(onBucketSelect).not.toHaveBeenCalled();
207
209
  });
210
+ it('sorts by creation date by default, not by bucket name', ()=>{
211
+ const bucketsWithReversedDateOrder = [
212
+ {
213
+ Name: 'alpha-bucket',
214
+ CreationDate: new Date('2024-03-01T00:00:00Z')
215
+ },
216
+ {
217
+ Name: 'beta-bucket',
218
+ CreationDate: new Date('2024-01-01T00:00:00Z')
219
+ },
220
+ {
221
+ Name: 'gamma-bucket',
222
+ CreationDate: new Date('2024-02-01T00:00:00Z')
223
+ }
224
+ ];
225
+ renderBucketList({
226
+ buckets: bucketsWithReversedDateOrder
227
+ });
228
+ const rows = screen.getAllByRole('row');
229
+ expect(rows[1]).toHaveTextContent('beta-bucket');
230
+ expect(rows[2]).toHaveTextContent('gamma-bucket');
231
+ expect(rows[3]).toHaveTextContent('alpha-bucket');
232
+ });
233
+ it('toggles to date descending when Created on header is clicked', ()=>{
234
+ const bucketsWithReversedDateOrder = [
235
+ {
236
+ Name: 'alpha-bucket',
237
+ CreationDate: new Date('2024-03-01T00:00:00Z')
238
+ },
239
+ {
240
+ Name: 'beta-bucket',
241
+ CreationDate: new Date('2024-01-01T00:00:00Z')
242
+ },
243
+ {
244
+ Name: 'gamma-bucket',
245
+ CreationDate: new Date('2024-02-01T00:00:00Z')
246
+ }
247
+ ];
248
+ renderBucketList({
249
+ buckets: bucketsWithReversedDateOrder
250
+ });
251
+ fireEvent.click(screen.getByText('Created on'));
252
+ const rows = screen.getAllByRole('row');
253
+ expect(rows[1]).toHaveTextContent('alpha-bucket');
254
+ expect(rows[2]).toHaveTextContent('gamma-bucket');
255
+ expect(rows[3]).toHaveTextContent('beta-bucket');
256
+ });
257
+ it('sorts by storage location when location column header is clicked', ()=>{
258
+ jest.spyOn(__rspack_external__hooks_index_js_a0d26731, 'useBucketLocations').mockReturnValue(new Map([
259
+ [
260
+ 'test-bucket-1',
261
+ 'us-west-2'
262
+ ],
263
+ [
264
+ 'test-bucket-2',
265
+ 'eu-west-1'
266
+ ],
267
+ [
268
+ 'test-bucket-3',
269
+ 'ap-southeast-1'
270
+ ]
271
+ ]));
272
+ renderBucketList({
273
+ buckets: mockBuckets
274
+ });
275
+ fireEvent.click(screen.getByText('Storage Location'));
276
+ const rows = screen.getAllByRole('row');
277
+ expect(rows[1]).toHaveTextContent('test-bucket-3');
278
+ expect(rows[2]).toHaveTextContent('test-bucket-2');
279
+ expect(rows[3]).toHaveTextContent('test-bucket-1');
280
+ });
208
281
  describe('extraBucketListColumns support', ()=>{
209
282
  it('renders extra columns when extraBucketListColumns is configured', ()=>{
210
283
  const CustomColumn = ({ data })=>/*#__PURE__*/ jsxs("span", {
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { fireEvent, render, renderHook, screen, waitFor } from "@testing-library/react";
2
+ import { act, fireEvent, render, renderHook, screen, waitFor } from "@testing-library/react";
3
3
  import { MemoryRouter } from "react-router";
4
4
  import { DataBrowserUICustomizationProvider } from "../../contexts/DataBrowserUICustomizationContext.js";
5
5
  import { useListObjectVersions, useListObjects } from "../../hooks/index.js";
@@ -281,14 +281,42 @@ describe('ObjectList', ()=>{
281
281
  expect(screen.getByText('Version ID')).toBeInTheDocument();
282
282
  });
283
283
  });
284
+ it('notifies parent to clear selection when toggling versions', async ()=>{
285
+ const onObjectSelect = jest.fn();
286
+ renderObjectList({
287
+ onObjectSelect
288
+ });
289
+ await waitFor(()=>{
290
+ expect(screen.getByText('file1.txt')).toBeInTheDocument();
291
+ });
292
+ const rows = screen.getAllByRole('row');
293
+ const objectRow = rows.find((row)=>row.textContent?.includes('file1.txt'));
294
+ expect(objectRow).toBeDefined();
295
+ fireEvent.click(objectRow);
296
+ expect(onObjectSelect).toHaveBeenCalledWith(expect.objectContaining({
297
+ Key: 'file1.txt',
298
+ type: 'object'
299
+ }));
300
+ onObjectSelect.mockClear();
301
+ const toggleLabel = screen.getByText(/list versions/i);
302
+ const toggle = toggleLabel.closest('label')?.querySelector('input[type="checkbox"]');
303
+ fireEvent.click(toggle);
304
+ await waitFor(()=>{
305
+ expect(screen.getByText('Version ID')).toBeInTheDocument();
306
+ });
307
+ expect(onObjectSelect).toHaveBeenCalledWith(null);
308
+ });
284
309
  });
285
310
  describe('Search Features', ()=>{
286
- it('renders table search when metadata-search feature is disabled', async ()=>{
311
+ it('renders SearchInput when metadata-search feature is disabled', async ()=>{
287
312
  jest.spyOn(__rspack_external__hooks_useFeatures_js_a6a84786, 'useFeatures').mockReturnValue(false);
288
313
  renderObjectList();
289
314
  await waitFor(()=>{
290
315
  expect(screen.getByRole('grid')).toBeInTheDocument();
291
316
  });
317
+ expect(screen.getByRole('searchbox', {
318
+ name: 'search'
319
+ })).toBeInTheDocument();
292
320
  expect(screen.queryByPlaceholderText(/Metadata Search/i)).not.toBeInTheDocument();
293
321
  });
294
322
  it('renders MetadataSearch component when metadata-search feature is enabled', async ()=>{
@@ -299,6 +327,70 @@ describe('ObjectList', ()=>{
299
327
  });
300
328
  expect(screen.getByPlaceholderText(/Metadata Search/i)).toBeInTheDocument();
301
329
  });
330
+ it('filters table rows when typing in search input', async ()=>{
331
+ jest.useFakeTimers();
332
+ jest.spyOn(__rspack_external__hooks_useFeatures_js_a6a84786, 'useFeatures').mockReturnValue(false);
333
+ renderObjectList();
334
+ await waitFor(()=>{
335
+ expect(screen.getByText('file1.txt')).toBeInTheDocument();
336
+ expect(screen.getByText('file2.txt')).toBeInTheDocument();
337
+ expect(screen.getByText('folder1/')).toBeInTheDocument();
338
+ });
339
+ const searchInput = screen.getByRole('searchbox', {
340
+ name: 'search'
341
+ });
342
+ fireEvent.change(searchInput, {
343
+ target: {
344
+ value: 'file1'
345
+ }
346
+ });
347
+ act(()=>{
348
+ jest.advanceTimersByTime(300);
349
+ });
350
+ await waitFor(()=>{
351
+ expect(screen.getByText('file1.txt')).toBeInTheDocument();
352
+ expect(screen.queryByText('file2.txt')).not.toBeInTheDocument();
353
+ expect(screen.queryByText('folder1/')).not.toBeInTheDocument();
354
+ });
355
+ jest.useRealTimers();
356
+ });
357
+ it('shows all rows when search is cleared', async ()=>{
358
+ jest.useFakeTimers();
359
+ jest.spyOn(__rspack_external__hooks_useFeatures_js_a6a84786, 'useFeatures').mockReturnValue(false);
360
+ renderObjectList();
361
+ await waitFor(()=>{
362
+ expect(screen.getByText('file1.txt')).toBeInTheDocument();
363
+ expect(screen.getByText('file2.txt')).toBeInTheDocument();
364
+ });
365
+ const searchInput = screen.getByRole('searchbox', {
366
+ name: 'search'
367
+ });
368
+ fireEvent.change(searchInput, {
369
+ target: {
370
+ value: 'file1'
371
+ }
372
+ });
373
+ act(()=>{
374
+ jest.advanceTimersByTime(300);
375
+ });
376
+ await waitFor(()=>{
377
+ expect(screen.queryByText('file2.txt')).not.toBeInTheDocument();
378
+ });
379
+ fireEvent.change(searchInput, {
380
+ target: {
381
+ value: ''
382
+ }
383
+ });
384
+ act(()=>{
385
+ jest.advanceTimersByTime(300);
386
+ });
387
+ await waitFor(()=>{
388
+ expect(screen.getByText('file1.txt')).toBeInTheDocument();
389
+ expect(screen.getByText('file2.txt')).toBeInTheDocument();
390
+ expect(screen.getByText('folder1/')).toBeInTheDocument();
391
+ });
392
+ jest.useRealTimers();
393
+ });
302
394
  });
303
395
  describe('Multi-Selection', ()=>{
304
396
  it('integrates with MultiSelectableContent', async ()=>{
@@ -5,6 +5,7 @@ export declare const bucketNameValidationSchema: Joi.StringSchema<string>;
5
5
  export declare const baseBucketCreateSchema: Joi.ObjectSchema<any>;
6
6
  export type BucketCreateFormData = {
7
7
  name: string;
8
+ locationConstraint?: string;
8
9
  isVersioning: boolean;
9
10
  isEncryptionEnabled: boolean;
10
11
  isObjectLockEnabled: boolean;
@@ -4,7 +4,9 @@ import { Checkbox, Form, FormGroup, FormSection, Stack, useToast } from "@scalit
4
4
  import { Button, Input } from "@scality/core-ui/dist/next";
5
5
  import { convertRemToPixels } from "@scality/core-ui/dist/utils";
6
6
  import joi from "joi";
7
- import { FormProvider, useForm } from "react-hook-form";
7
+ import { useMemo } from "react";
8
+ import { Controller, FormProvider, useForm } from "react-hook-form";
9
+ import { useDataBrowserUICustomization } from "../../contexts/DataBrowserUICustomizationContext.js";
8
10
  import { useCreateBucket, useSetBucketEncryption, useSetBucketObjectLockConfiguration, useSetBucketVersioning } from "../../hooks/index.js";
9
11
  import { useDataBrowserNavigate } from "../../hooks/useDataBrowserNavigate.js";
10
12
  import ObjectLockRetentionSettings from "../objects/ObjectLock/ObjectLockRetentionSettings.js";
@@ -58,8 +60,12 @@ const baseBucketCreateSchema = joi.object({
58
60
  const BucketCreate = ({ subTitle, validationSchema, validationContext, defaultValues: customDefaultValues, children, onSubmit: onSubmitProp, onCancel: onCancelProp })=>{
59
61
  const navigate = useDataBrowserNavigate();
60
62
  const { showToast } = useToast();
63
+ const { locationSelector: LocationSelector, bucketCreateExtraFields, transformBucketCreateData, bucketCreateVersioning: VersioningRenderer } = useDataBrowserUICustomization();
61
64
  const baseDefaultValues = {
62
65
  name: '',
66
+ ...LocationSelector ? {
67
+ locationConstraint: ''
68
+ } : {},
63
69
  isVersioning: false,
64
70
  isEncryptionEnabled: false,
65
71
  isObjectLockEnabled: false,
@@ -69,15 +75,32 @@ const BucketCreate = ({ subTitle, validationSchema, validationContext, defaultVa
69
75
  retentionPeriodFrequencyChoice: 'DAYS',
70
76
  ...customDefaultValues
71
77
  };
78
+ const hasExtraFields = !!bucketCreateExtraFields;
79
+ const resolvedSchema = useMemo(()=>{
80
+ let schema = validationSchema || baseBucketCreateSchema;
81
+ if (LocationSelector) schema = schema.keys({
82
+ locationConstraint: joi.string().required().messages({
83
+ 'string.empty': 'Location is required'
84
+ })
85
+ });
86
+ if (hasExtraFields) schema = schema.options({
87
+ allowUnknown: true
88
+ });
89
+ return schema;
90
+ }, [
91
+ validationSchema,
92
+ LocationSelector,
93
+ hasExtraFields
94
+ ]);
72
95
  const useFormMethods = useForm({
73
96
  mode: 'all',
74
- resolver: joiResolver(validationSchema || baseBucketCreateSchema, {
97
+ resolver: joiResolver(resolvedSchema, {
75
98
  context: validationContext || {}
76
99
  }),
77
100
  defaultValues: baseDefaultValues,
78
101
  context: validationContext
79
102
  });
80
- const { register, handleSubmit, formState, watch } = useFormMethods;
103
+ const { register, handleSubmit, formState, watch, control } = useFormMethods;
81
104
  const { isValid, errors } = formState;
82
105
  const isObjectLockEnabled = watch('isObjectLockEnabled');
83
106
  const isEncryptionEnabled = watch('isEncryptionEnabled');
@@ -106,15 +129,21 @@ const BucketCreate = ({ subTitle, validationSchema, validationContext, defaultVa
106
129
  status: 'error'
107
130
  });
108
131
  };
109
- const onSubmit = (data)=>{
110
- if (onSubmitProp) return void onSubmitProp(data);
132
+ const onSubmit = (rawData)=>{
133
+ if (onSubmitProp) return void onSubmitProp(rawData);
134
+ const data = transformBucketCreateData ? transformBucketCreateData(rawData) : rawData;
111
135
  const bucketName = data.name;
112
136
  const needsExplicitVersioning = data.isVersioning && !data.isObjectLockEnabled;
113
137
  const needsRetentionConfig = data.isObjectLockEnabled && data.isDefaultRetentionEnabled;
114
138
  const needsEncryption = data.isEncryptionEnabled;
115
139
  createBucket({
116
140
  Bucket: bucketName,
117
- ObjectLockEnabledForBucket: data.isObjectLockEnabled || void 0
141
+ ObjectLockEnabledForBucket: data.isObjectLockEnabled || void 0,
142
+ ...data.locationConstraint ? {
143
+ CreateBucketConfiguration: {
144
+ LocationConstraint: data.locationConstraint
145
+ }
146
+ } : {}
118
147
  }, {
119
148
  onSuccess: ()=>{
120
149
  if (needsExplicitVersioning) setBucketVersioning({
@@ -236,6 +265,24 @@ const BucketCreate = ({ subTitle, validationSchema, validationContext, defaultVa
236
265
  helpErrorPosition: "bottom",
237
266
  error: errors.name ? errors.name?.type === 'string.pattern.base' ? bucketErrorMessage : errors.name?.message : void 0
238
267
  }),
268
+ LocationSelector && /*#__PURE__*/ jsx(FormGroup, {
269
+ id: "locationConstraint",
270
+ label: "Storage Service Location",
271
+ required: true,
272
+ direction: "horizontal",
273
+ labelHelpTooltip: "Cannot be modified after creation",
274
+ helpErrorPosition: "bottom",
275
+ error: errors?.locationConstraint?.message,
276
+ content: /*#__PURE__*/ jsx(Controller, {
277
+ name: "locationConstraint",
278
+ control: control,
279
+ render: ({ field })=>/*#__PURE__*/ jsx(LocationSelector, {
280
+ value: field.value ?? '',
281
+ onChange: field.onChange
282
+ })
283
+ })
284
+ }),
285
+ bucketCreateExtraFields,
239
286
  children,
240
287
  s3Capabilities?.bucketEncryption && /*#__PURE__*/ jsx(FormGroup, {
241
288
  id: "isEncryptionEnabled",
@@ -248,7 +295,10 @@ const BucketCreate = ({ subTitle, validationSchema, validationContext, defaultVa
248
295
  ...register('isEncryptionEnabled')
249
296
  })
250
297
  }),
251
- /*#__PURE__*/ jsx(FormGroup, {
298
+ VersioningRenderer ? /*#__PURE__*/ jsx(VersioningRenderer, {
299
+ isVersioning: isVersioning,
300
+ isObjectLockEnabled: isObjectLockEnabled
301
+ }) : /*#__PURE__*/ jsx(FormGroup, {
252
302
  id: "isVersioning",
253
303
  label: "Versioning",
254
304
  disabled: isObjectLockEnabled,
@@ -179,7 +179,6 @@ const DefaultTabs = ()=>{
179
179
  id: 'overview',
180
180
  label: 'Overview',
181
181
  path: '',
182
- withoutPadding: false,
183
182
  query: {
184
183
  tab: ''
185
184
  },