From 701c4b34837e8ffabed95d4f0dbc622dd0428479 Mon Sep 17 00:00:00 2001 From: Jean-Marc Millet Date: Tue, 9 Apr 2024 17:40:47 +0200 Subject: [PATCH 1/5] use FormattedDate component for Date element when possible, improve table sorting --- src/react/account/AccountList.tsx | 20 +++++--- src/react/account/AccountUserAccessKeys.tsx | 49 +++++++++++-------- src/react/account/AccountUserList.tsx | 13 +++-- .../details/properties/AccountInfo.tsx | 6 ++- .../details/properties/AccountKeys.tsx | 36 +++++--------- 5 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/react/account/AccountList.tsx b/src/react/account/AccountList.tsx index 91c998abc..1e3be093f 100644 --- a/src/react/account/AccountList.tsx +++ b/src/react/account/AccountList.tsx @@ -4,8 +4,13 @@ import styled from 'styled-components'; import { spacing } from '@scality/core-ui/dist/style/theme'; import { Button } from '@scality/core-ui/dist/components/buttonv2/Buttonv2.component'; import { Table } from '@scality/core-ui/dist/components/tablev2/Tablev2.component'; -import { formatSimpleDate } from '../utils'; -import { ConstrainedText, Icon, Link, Stack } from '@scality/core-ui'; +import { + ConstrainedText, + FormattedDateTime, + Icon, + Link, + Stack, +} from '@scality/core-ui'; import { Account } from '../next-architecture/domain/entities/account'; import { CellProps, CoreUIColumn } from 'react-table'; import { @@ -70,10 +75,6 @@ function AccountList({ accounts }: { accounts: Account[] }) { ); }; - const createDateCell = ({ value }: CellProps) => { - return
{formatSimpleDate(new Date(value))}
; - }; - const columns: CoreUIColumn[] = React.useMemo(() => { const dataUsedColumn = getDataUsedColumn( (account: Account) => { @@ -103,7 +104,12 @@ function AccountList({ accounts }: { accounts: Account[] }) { textAlign: 'right', minWidth: '7rem', }, - Cell: (value: CellProps) => createDateCell(value), + Cell: ({ value }: CellProps) => ( + + ), }, ...(isStorageManager ? additionalStorageManagerColumns : []), ]; diff --git a/src/react/account/AccountUserAccessKeys.tsx b/src/react/account/AccountUserAccessKeys.tsx index e96d72402..e220ece16 100644 --- a/src/react/account/AccountUserAccessKeys.tsx +++ b/src/react/account/AccountUserAccessKeys.tsx @@ -1,8 +1,16 @@ -import { AppContainer, Banner, Stack, Toggle, Tooltip } from '@scality/core-ui'; -import { Icon } from '@scality/core-ui/dist/components/icon/Icon.component'; -import { TextBadge } from '@scality/core-ui/dist/components/textbadge/TextBadge.component'; -import { Box, Button, Table } from '@scality/core-ui/dist/next'; -import { spacing } from '@scality/core-ui/dist/style/theme'; +import { + AppContainer, + Banner, + FormattedDateTime, + Stack, + Toggle, + Tooltip, + Wrap, + Icon, + TextBadge, + spacing, +} from '@scality/core-ui'; +import { Box, Button, CopyButton, Table } from '@scality/core-ui/dist/next'; import { useMemo, useState } from 'react'; import { useMutation, useQueryClient } from 'react-query'; import { @@ -17,7 +25,6 @@ import styled from 'styled-components'; import { useIAMClient } from '../IAMProvider'; import { getUserAccessKeysQuery } from '../queries'; import { BreadcrumbAccount } from '../ui-elements/Breadcrumb'; -import { Clipboard } from '../ui-elements/Clipboard'; import DeleteConfirmation from '../ui-elements/DeleteConfirmation'; import { TitleRow as TableHeader } from '../ui-elements/TableKeyValue'; import { formatSimpleDate } from '../utils'; @@ -35,7 +42,7 @@ const CustomIcon = styled.i` const CreatedOnCell = (rowValue) => { const outdatedAlert = useAccessKeyOutdatedStatus(rowValue); return ( -
+ {outdatedAlert ? ( { ) : null} - {rowValue.createdOn} -
+ { + + } + ); }; @@ -91,14 +103,9 @@ const ToggleAccessKeyStatus = (rowValue) => { const AccessKeysCell = (rowValue) => { const { accessKey } = rowValue; return ( -
- {accessKey} -
+ + {accessKey} + ); }; @@ -196,7 +203,7 @@ const AccountUserAccessKeys = () => { cellStyle: { minWidth: '10rem', textAlign: 'right', - paddingRight: spacing.sp32, + paddingRight: spacing.r32, }, }, { @@ -204,7 +211,7 @@ const AccountUserAccessKeys = () => { accessor: 'status', cellStyle: { textAlign: 'left', - marginRight: spacing.sp32, + marginRight: spacing.r32, }, Cell: (value) => ToggleAccessKeyStatus(value.row.original), }, @@ -231,7 +238,7 @@ const AccountUserAccessKeys = () => { variant={'statusWarning'} //@ts-expect-error fix this when you are working on it text={accessKeysResultLength} - style={{ marginLeft: spacing.sp8 }} + style={{ marginLeft: spacing.r8 }} /> { style={{ display: 'flex', alignItems: 'center', - marginLeft: spacing.sp8, + marginLeft: spacing.r8, }} > { queryResult.data?.map((user) => { return { userName: user.UserName, - createdOn: formatSimpleDate(user.CreateDate), + createdOn: user.CreateDate, accessKeys: null, arn: user.Arn, actions: null, @@ -326,6 +326,11 @@ const AccountUserList = ({ accountName }: { accountName?: string }) => { textAlign: 'right', minWidth: '10%', }, + Cell: ({ value }: { value: Date }) => ( + + ), + sortType: (row1: Row, row2: Row) => + row1.original.createdOn.getTime() - row2.original.createdOn.getTime(), }, // Table cell for all the actions (Copy ARN, Edit and Delete) { Header: '', diff --git a/src/react/account/details/properties/AccountInfo.tsx b/src/react/account/details/properties/AccountInfo.tsx index 7083fe082..25197c491 100644 --- a/src/react/account/details/properties/AccountInfo.tsx +++ b/src/react/account/details/properties/AccountInfo.tsx @@ -19,7 +19,7 @@ import { ButtonContainer } from '../../../ui-elements/Container'; import DeleteConfirmation from '../../../ui-elements/DeleteConfirmation'; import * as T from '../../../ui-elements/TableKeyValue'; import Table, { TitleRow } from '../../../ui-elements/TableKeyValue'; -import { formatDate } from '../../../utils'; +import { formatShortDate } from '../../../utils'; import { useAccounts, useAuthGroups, @@ -173,7 +173,9 @@ function AccountInfo({ account }: Props) { Creation Date - {formatDate(new Date(account.CreationDate))} + + {formatShortDate(new Date(account.CreationDate))}{' '} + {/* We have to hide this two fields until the information is ready from GetRolesForWebIdentity() */} {/* diff --git a/src/react/account/details/properties/AccountKeys.tsx b/src/react/account/details/properties/AccountKeys.tsx index 134fcdab7..5a837e556 100644 --- a/src/react/account/details/properties/AccountKeys.tsx +++ b/src/react/account/details/properties/AccountKeys.tsx @@ -8,10 +8,8 @@ import { useDispatch, useSelector } from 'react-redux'; import { Row } from 'react-table'; import type { Account } from '../../../../types/account'; import type { AppState } from '../../../../types/state'; -import { Banner, Icon, Wrap } from '@scality/core-ui'; -import { Button, Table } from '@scality/core-ui/dist/next'; -import { Clipboard } from '../../../ui-elements/Clipboard'; -import { formatShortDate } from '../../../utils'; +import { Banner, FormattedDateTime, Icon, Wrap } from '@scality/core-ui'; +import { Button, CopyButton, Table } from '@scality/core-ui/dist/next'; import { spacing } from '@scality/core-ui/dist/style/theme'; import styled from 'styled-components'; import { useDataServiceRole } from '../../../DataServiceRoleProvider'; @@ -96,25 +94,14 @@ function AccountKeys({ account }: Props) { Header: 'Access key ID', accessor: 'access_key', cellStyle: { - flex: '0.25', + flex: '0.3', }, Cell({ value: access_key }: { value: string }) { return ( - - {access_key} -
- -
-
+ + {access_key} + + ); }, }, @@ -145,7 +132,9 @@ function AccountKeys({ account }: Props) { }, Cell({ value }: { value: string }) { - return formatShortDate(new Date(value)); + return ( + + ); }, }, { @@ -192,10 +181,7 @@ function AccountKeys({ account }: Props) { > {accessKeys && accessKeys.length > 0 && (
- } - > + }> <> Security Status: Root user Access keys give unrestricted access to account resources. It is a best practice to delete root From 4ef4aaa4472996e61487cd93337bf3e925ff3f60 Mon Sep 17 00:00:00 2001 From: Jean-Marc Millet Date: Wed, 10 Apr 2024 11:39:28 +0200 Subject: [PATCH 2/5] update test after changes in date format --- .../account/__tests__/AccountDetails.test.tsx | 5 +-- src/react/account/__tests__/Accounts.test.tsx | 4 +- .../properties/__tests__/AccountInfo.test.tsx | 43 +++++++++++-------- .../properties/__tests__/AccountKeys.test.tsx | 12 +++--- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/react/account/__tests__/AccountDetails.test.tsx b/src/react/account/__tests__/AccountDetails.test.tsx index a78b43e8c..8e335e0a1 100644 --- a/src/react/account/__tests__/AccountDetails.test.tsx +++ b/src/react/account/__tests__/AccountDetails.test.tsx @@ -5,7 +5,8 @@ import { _AuthContext, useAuth } from '../../next-architecture/ui/AuthProvider'; const account1 = { arn: 'arn1', canonicalId: 'canonicalId1', - createDate: Date.parse('04 Jan 2000 05:12:00 GMT'), + CreationDate: Date.parse('04 Jan 2000 05:12:00 GMT'), + Roles: [], email: 'test@email1.com', id: '1', quotaMax: 1, @@ -54,7 +55,6 @@ describe('AccountDetails', () => { }; }); const component = renderWithRouterMatch( - //@ts-expect-error fix this when you are working on it , { route: '/accounts/bart', @@ -70,7 +70,6 @@ describe('AccountDetails', () => { it('should render AccountDetails component without access keys for storage manager users', () => { //S const component = renderWithRouterMatch( - //@ts-expect-error fix this when you are working on it , { route: '/accounts/bart', diff --git a/src/react/account/__tests__/Accounts.test.tsx b/src/react/account/__tests__/Accounts.test.tsx index 52abbf9a3..7fa0a781a 100644 --- a/src/react/account/__tests__/Accounts.test.tsx +++ b/src/react/account/__tests__/Accounts.test.tsx @@ -90,9 +90,7 @@ describe('Accounts', () => { expect(screen.getByText(TEST_ACCOUNT)).toBeInTheDocument(); - expect( - screen.getByText(formatSimpleDate(new Date(TEST_ACCOUNT_CREATION_DATE))), - ).toBeInTheDocument(); + expect(screen.getByText('2022-03-18 12:51:44')).toBeInTheDocument(); }); it('should list accounts display an error when retrieval of accounts failed', async () => { diff --git a/src/react/account/details/properties/__tests__/AccountInfo.test.tsx b/src/react/account/details/properties/__tests__/AccountInfo.test.tsx index 2774d132c..9fbd7e154 100644 --- a/src/react/account/details/properties/__tests__/AccountInfo.test.tsx +++ b/src/react/account/details/properties/__tests__/AccountInfo.test.tsx @@ -10,7 +10,7 @@ import { } from '../../../../utils/testUtil'; import AccountInfo from '../AccountInfo'; import Table from '../../../../ui-elements/TableKeyValue'; -import { formatDate } from '../../../../utils'; +import { formatDate, formatShortDate } from '../../../../utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { INSTANCE_ID } from '../../../../actions/__tests__/utils/testUtil'; @@ -84,14 +84,11 @@ describe('AccountInfo', () => { extraCellComponent: 'Clipboard', }); const thirdRow = rows.at(2); - testRow( - thirdRow, - //@ts-expect-error fix this when you are working on it - { - key: 'Creation Date', - value: formatDate(new Date(account1.CreationDate)), - }, - ); + testRow(thirdRow, { + key: 'Creation Date', + value: formatShortDate(new Date(account1.CreationDate)), + extraCellComponent: undefined, + }); }); it('should not be able to delete an account when not a storage manager', () => { @@ -146,7 +143,9 @@ describe('AccountInfo', () => { ); //E - await userEvent.click(screen.getByRole('button', { name: /Delete Account/i })); + await userEvent.click( + screen.getByRole('button', { name: /Delete Account/i }), + ); await userEvent.click(screen.getByRole('button', { name: 'Delete' })); @@ -177,11 +176,15 @@ describe('AccountInfo', () => { renderWithRouterMatch(, undefined, { instances: { selectedId: INSTANCE_ID }, }); - await userEvent.click(screen.getByRole('button', { name: /Delete Account/i })); - await userEvent.click(within(screen.getByRole('dialog', { name: /Confirmation/i })).getByRole( - 'button', - { name: /delete/i }, - )); + await userEvent.click( + screen.getByRole('button', { name: /Delete Account/i }), + ); + await userEvent.click( + within(screen.getByRole('dialog', { name: /Confirmation/i })).getByRole( + 'button', + { name: /delete/i }, + ), + ); //V await waitFor(() => { expect( @@ -191,10 +194,12 @@ describe('AccountInfo', () => { ).toBeInTheDocument(); }); //E - await userEvent.click(within(screen.getByRole('dialog', { name: /Error/i })).getByRole( - 'button', - { name: /close/i }, - )); + await userEvent.click( + within(screen.getByRole('dialog', { name: /Error/i })).getByRole( + 'button', + { name: /close/i }, + ), + ); //V await waitFor(() => { expect( diff --git a/src/react/account/details/properties/__tests__/AccountKeys.test.tsx b/src/react/account/details/properties/__tests__/AccountKeys.test.tsx index ee06f8f4a..86fa2e702 100644 --- a/src/react/account/details/properties/__tests__/AccountKeys.test.tsx +++ b/src/react/account/details/properties/__tests__/AccountKeys.test.tsx @@ -1,6 +1,6 @@ import { screen } from '@testing-library/react'; import { accountAccessKeys } from '../../../../../js/mock/IAMClient'; -import { formatShortDate } from '../../../../utils'; + import { mockOffsetSize, reduxRender, @@ -11,7 +11,8 @@ import AccountKeys from '../AccountKeys'; const account1 = { arn: 'arn1', canonicalId: 'canonicalId1', - createDate: Date.parse('04 Jan 2000 05:12:00 GMT'), + CreationDate: Date.parse('04 Jan 2000 05:12:00 GMT'), + Roles: [], email: 'test@email1.com', id: '1', quotaMax: 1, @@ -30,7 +31,6 @@ describe('AccountKeys', () => { }); it('should render AccountKeys component', () => { - //@ts-expect-error fix this when you are working on it renderWithRouterMatch(, undefined, { configuration: { latest: { @@ -45,17 +45,16 @@ describe('AccountKeys', () => { expect(screen.getByText('Access key ID')).toBeInTheDocument(); expect(screen.getByText('Created On')).toBeInTheDocument(); - accountAccessKeys.forEach((accessKey) => { + accountAccessKeys.forEach((accessKey, i) => { expect(screen.getByText(accessKey.AccessKeyId)).toBeInTheDocument(); expect( - screen.getByText(formatShortDate(new Date(accessKey.CreateDate))), + screen.getByText(i === 0 ? '2020-04-19 16:15' : '2021-04-19 16:15'), ).toBeInTheDocument(); }); }); it('should render notification whenever there is at least 1 Root Access Key', () => { const accessKey = accountAccessKeys[0]; - //@ts-expect-error fix this when you are working on it renderWithRouterMatch(, undefined, { configuration: { latest: { @@ -75,7 +74,6 @@ describe('AccountKeys', () => { }); it('should render Warning/Banner accordingly to number of Access Key', () => { - //@ts-expect-error fix this when you are working on it const { component } = reduxRender(, { configuration: { latest: { From ac081a3512985abca860c6d52d0033a25fd016f7 Mon Sep 17 00:00:00 2001 From: Jean-Marc Millet Date: Wed, 10 Apr 2024 16:05:13 +0200 Subject: [PATCH 3/5] change formatShortDate for FormattedDateTime and change tests --- src/react/account/AccountPoliciesList.tsx | 21 ++++++++++++------- .../details/properties/AccountInfo.tsx | 8 ++++--- .../properties/__tests__/AccountInfo.test.tsx | 3 +-- src/react/databrowser/buckets/BucketList.tsx | 18 +++++++++------- .../buckets/__tests__/BucketList.test.tsx | 17 ++++----------- .../ObjectRestorationButtonAndModal.tsx | 7 +++++-- .../objects/details/Properties.tsx | 11 +++++++--- 7 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/react/account/AccountPoliciesList.tsx b/src/react/account/AccountPoliciesList.tsx index a369d5a2e..c57daf04b 100644 --- a/src/react/account/AccountPoliciesList.tsx +++ b/src/react/account/AccountPoliciesList.tsx @@ -2,9 +2,13 @@ import { useState } from 'react'; import { useHistory } from 'react-router-dom'; import { Box, Button, CopyButton } from '@scality/core-ui/dist/next'; import { spacing } from '@scality/core-ui/dist/style/theme'; -import { formatShortDate } from '../utils'; import { useIAMClient } from '../IAMProvider'; -import { ConstrainedText, Icon, Tooltip } from '@scality/core-ui'; +import { + ConstrainedText, + FormattedDateTime, + Icon, + Tooltip, +} from '@scality/core-ui'; import { notFalsyTypeGuard } from '../../types/typeGuards'; import { useMutation, useQuery, useQueryClient } from 'react-query'; import DeleteConfirmation from '../ui-elements/DeleteConfirmation'; @@ -310,7 +314,7 @@ const AccessPolicyNameCell = ({ rowValues }: { rowValues: InternalPolicy }) => { type InternalPolicy = { policyPath: string; policyName: string; - modifiedOn: string; + modifiedOn: string | Date; attachments: number; defaultVersionId: string; policyArn: string; @@ -333,9 +337,7 @@ const AccountPoliciesList = ({ accountName }: { accountName: string }) => { return { policyPath: policy.Path?.substring(1) || '', policyName: policy.PolicyName || '', - modifiedOn: policy.UpdateDate - ? formatShortDate(policy.UpdateDate) - : '-', + modifiedOn: policy.UpdateDate || '-', attachments: policy.AttachmentCount || 0, policyArn: policy.Arn || '', defaultVersionId: policy?.DefaultVersionId || '', @@ -371,7 +373,12 @@ const AccountPoliciesList = ({ accountName }: { accountName: string }) => { textAlign: 'right', minWidth: '20%', }, - Cell: ({ value }) => <>{value}, + Cell: ({ value }) => { + if (typeof value === 'string') { + return <>{value}; + } + return ; + }, }, { Header: 'Attachments', diff --git a/src/react/account/details/properties/AccountInfo.tsx b/src/react/account/details/properties/AccountInfo.tsx index 25197c491..7d2b92b5e 100644 --- a/src/react/account/details/properties/AccountInfo.tsx +++ b/src/react/account/details/properties/AccountInfo.tsx @@ -1,4 +1,4 @@ -import { Icon, Modal, Wrap } from '@scality/core-ui'; +import { FormattedDateTime, Icon, Modal, Wrap } from '@scality/core-ui'; import { Button } from '@scality/core-ui/dist/components/buttonv2/Buttonv2.component'; import { useMutation, useQueryClient } from 'react-query'; import { useHistory } from 'react-router-dom'; @@ -19,7 +19,6 @@ import { ButtonContainer } from '../../../ui-elements/Container'; import DeleteConfirmation from '../../../ui-elements/DeleteConfirmation'; import * as T from '../../../ui-elements/TableKeyValue'; import Table, { TitleRow } from '../../../ui-elements/TableKeyValue'; -import { formatShortDate } from '../../../utils'; import { useAccounts, useAuthGroups, @@ -174,7 +173,10 @@ function AccountInfo({ account }: Props) { Creation Date - {formatShortDate(new Date(account.CreationDate))}{' '} + {/* We have to hide this two fields until the information is ready from GetRolesForWebIdentity() */} diff --git a/src/react/account/details/properties/__tests__/AccountInfo.test.tsx b/src/react/account/details/properties/__tests__/AccountInfo.test.tsx index 9fbd7e154..078534c62 100644 --- a/src/react/account/details/properties/__tests__/AccountInfo.test.tsx +++ b/src/react/account/details/properties/__tests__/AccountInfo.test.tsx @@ -10,7 +10,6 @@ import { } from '../../../../utils/testUtil'; import AccountInfo from '../AccountInfo'; import Table from '../../../../ui-elements/TableKeyValue'; -import { formatDate, formatShortDate } from '../../../../utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { INSTANCE_ID } from '../../../../actions/__tests__/utils/testUtil'; @@ -86,7 +85,7 @@ describe('AccountInfo', () => { const thirdRow = rows.at(2); testRow(thirdRow, { key: 'Creation Date', - value: formatShortDate(new Date(account1.CreationDate)), + value: '', extraCellComponent: undefined, }); }); diff --git a/src/react/databrowser/buckets/BucketList.tsx b/src/react/databrowser/buckets/BucketList.tsx index 9c9ae58a4..d1577cf02 100644 --- a/src/react/databrowser/buckets/BucketList.tsx +++ b/src/react/databrowser/buckets/BucketList.tsx @@ -1,4 +1,10 @@ -import { ConstrainedText, Icon, Link, spacing } from '@scality/core-ui'; +import { + ConstrainedText, + FormattedDateTime, + Icon, + Link, + spacing, +} from '@scality/core-ui'; import { EmptyCell } from '@scality/core-ui/dist/components/tablev2/Tablev2.component'; import { Box, Table } from '@scality/core-ui/dist/next'; import { useMemo } from 'react'; @@ -14,8 +20,6 @@ import { useConfig } from '../../next-architecture/ui/ConfigProvider'; import { useMetricsAdapter } from '../../next-architecture/ui/MetricsAdapterProvider'; import { getDataUsedColumn } from '../../next-architecture/ui/metrics/DataUsedColumn'; import * as T from '../../ui-elements/Table'; -import { TextAligner } from '../../ui-elements/Utility'; -import { formatShortDate } from '../../utils'; import { useAuthGroups, useQueryParams } from '../../utils/hooks'; import { getLocationIngestionState } from '../../utils/storageOptions'; import { BucketLocationNameAndType } from '../../workflow/SourceBucketOption'; @@ -129,12 +133,12 @@ export default function BucketList({ paddingRight: spacing.r32, textAlign: 'right', }, - Cell({ value }: { value: string }) { return ( - - {formatShortDate(new Date(value))} - + ); }, }); diff --git a/src/react/databrowser/buckets/__tests__/BucketList.test.tsx b/src/react/databrowser/buckets/__tests__/BucketList.test.tsx index 41783e065..c48984979 100644 --- a/src/react/databrowser/buckets/__tests__/BucketList.test.tsx +++ b/src/react/databrowser/buckets/__tests__/BucketList.test.tsx @@ -1,7 +1,6 @@ import { List } from 'immutable'; import { MemoryRouter } from 'react-router-dom'; import { XDM_FEATURE } from '../../../../js/config'; -import { formatShortDate } from '../../../utils'; import { mockOffsetSize, reduxRender } from '../../../utils/testUtil'; import BucketList from '../BucketList'; @@ -78,9 +77,7 @@ describe.skip('BucketList', () => { 'us-east-1 / Local Filesystem', ); expect(firstBucketCellAsyncNotification.textContent).toBe('-'); - expect(firstBucketCellDate.textContent).toBe( - formatShortDate(new Date(buckets.get(0).CreationDate)), - ); + expect(firstBucketCellDate.textContent).toBe('2020-04-19 16:15:29'); const secondRow = rows[1]; const secondRowCells = secondRow.getElementsByClassName('td'); const secondBucketCellLink = secondRowCells[0]; @@ -92,9 +89,7 @@ describe.skip('BucketList', () => { 's3c-ring / Scality RING with S3 Connector', ); expect(secondBucketCellAsyncNotification.textContent).toBe('Active'); - expect(secondBucketCellDate.textContent).toBe( - formatShortDate(new Date(buckets.get(1).CreationDate)), - ); + expect(secondBucketCellDate.textContent).toBe('2020-04-19 16:15:29'); }); it('should list buckets with the data associated when XDM feature is disabled', () => { const { component } = reduxRender( @@ -139,9 +134,7 @@ describe.skip('BucketList', () => { expect(firstBucketCellLocation.textContent).toBe( 'us-east-1 / Local Filesystem', ); - expect(firstBucketCellDate.textContent).toBe( - formatShortDate(new Date(buckets.get(0).CreationDate)), - ); + expect(firstBucketCellDate.textContent).toBe('2020-04-19 16:15:29'); const secondRow = rows[1]; const secondRowCells = secondRow.getElementsByClassName('td'); const secondBucketCellLink = secondRowCells[0]; @@ -151,9 +144,7 @@ describe.skip('BucketList', () => { expect(secondBucketCellLocation.textContent).toBe( 's3c-ring / Scality RING with S3 Connector', ); - expect(secondBucketCellDate.textContent).toBe( - formatShortDate(new Date(buckets.get(1).CreationDate)), - ); + expect(secondBucketCellDate.textContent).toBe('2020-04-19 16:15:29'); }); it('should select row if the bucket name specified in the parameter matches one of the bucket names listed', () => { const { component } = reduxRender( diff --git a/src/react/databrowser/objects/details/ObjectRestorationButtonAndModal.tsx b/src/react/databrowser/objects/details/ObjectRestorationButtonAndModal.tsx index 93aa453a3..801dcadbc 100644 --- a/src/react/databrowser/objects/details/ObjectRestorationButtonAndModal.tsx +++ b/src/react/databrowser/objects/details/ObjectRestorationButtonAndModal.tsx @@ -1,6 +1,7 @@ import { ChangeEvent, useState } from 'react'; import { Banner, + FormattedDateTime, Icon, Modal, PrettyBytes, @@ -14,7 +15,6 @@ import { useSelector } from 'react-redux'; import { AWSError } from 'aws-sdk'; import { getClients } from '../../../utils/actions'; import { AppState } from '../../../../types/state'; -import { formatShortDate } from '../../../utils'; import { useTheme } from 'styled-components'; import { ObjectMetadata } from '../../../../types/s3'; @@ -50,7 +50,10 @@ const ObjectRestorationButtonAndModal = ({ {objectMetadata.objectKey} - {formatShortDate(new Date(objectMetadata.lastModified))} + diff --git a/src/react/databrowser/objects/details/Properties.tsx b/src/react/databrowser/objects/details/Properties.tsx index 1a5252824..be92d23ed 100644 --- a/src/react/databrowser/objects/details/Properties.tsx +++ b/src/react/databrowser/objects/details/Properties.tsx @@ -13,7 +13,6 @@ import { Toggle, } from '@scality/core-ui'; import { useEffect } from 'react'; -import { formatShortDate } from '../../../utils'; import styled from 'styled-components'; import { useDispatch, useSelector } from 'react-redux'; import { putObjectLegalHold } from '../../../actions/s3object'; @@ -115,14 +114,20 @@ function Properties({ objectMetadata }: Props) { Modified On - {formatShortDate(new Date(objectMetadata.lastModified))}{' '} + {objectMetadata.expiration ? ( Expires On - {formatShortDate(objectMetadata.expiration)}{' '} + ) : ( From 7212839e0664b8caff7c971fa39b4f46c14ac124 Mon Sep 17 00:00:00 2001 From: Jean-Marc Millet Date: Wed, 10 Apr 2024 16:22:15 +0200 Subject: [PATCH 4/5] remove formatShortDate from S3 and delete formatshortDate function --- .../objects/details/Properties.tsx | 20 +++++++++++++++++-- src/react/reducers/s3.ts | 13 +++++------- src/react/utils/index.ts | 5 ----- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/react/databrowser/objects/details/Properties.tsx b/src/react/databrowser/objects/details/Properties.tsx index be92d23ed..269856c12 100644 --- a/src/react/databrowser/objects/details/Properties.tsx +++ b/src/react/databrowser/objects/details/Properties.tsx @@ -210,7 +210,15 @@ function Properties({ objectMetadata }: Props) { Locked ( {objectMetadata.objectRetention.mode.toLowerCase()})
- until {objectMetadata.objectRetention.retainUntilDate} + until{' '} + ) } @@ -220,7 +228,15 @@ function Properties({ objectMetadata }: Props) { <> Released
- since {objectMetadata.objectRetention.retainUntilDate} + since{' '} + ) } diff --git a/src/react/reducers/s3.ts b/src/react/reducers/s3.ts index 214ff0d36..3cd4e6d0b 100644 --- a/src/react/reducers/s3.ts +++ b/src/react/reducers/s3.ts @@ -7,7 +7,6 @@ import { import { METADATA_SYSTEM_TYPE, METADATA_USER_TYPE, - formatShortDate, stripQuotes, systemMetadataKeys, } from '../utils'; @@ -40,7 +39,7 @@ const objects = (objs, prefix): Array => return { name: o.Key.replace(prefix, ''), key: o.Key, - lastModified: formatShortDate(new Date(o.LastModified)), + lastModified: o.LastModified, size: o.Size, isFolder: false, toggled: false, @@ -90,10 +89,8 @@ const _getObjectLockInformation = ( ? { //@ts-expect-error fix this when you are working on it mode: o.ObjectRetention.Mode, - retainUntilDate: formatShortDate( - //@ts-expect-error fix this when you are working on it - new Date(o.ObjectRetention.RetainUntilDate), - ), + //@ts-expect-error fix this when you are working on it + retainUntilDate: o.ObjectRetention.RetainUntilDate, } : undefined, }; @@ -104,7 +101,7 @@ const search = (objs): Array => { return { name: o.Key, key: o.Key, - lastModified: formatShortDate(new Date(o.LastModified)), + lastModified: o.LastModified, size: o.Size, isFolder: o.IsFolder, isLatest: true, @@ -129,7 +126,7 @@ const versioning = ( return { name: o.Key.replace(prefix, ''), key: o.Key, - lastModified: formatShortDate(new Date(o.LastModified)), + lastModified: o.LastModified, size: o.Size || null, isFolder: false, isLatest: o.IsLatest, diff --git a/src/react/utils/index.ts b/src/react/utils/index.ts index 8580b3697..909481313 100644 --- a/src/react/utils/index.ts +++ b/src/react/utils/index.ts @@ -53,11 +53,6 @@ export function errorParser(error) { export function formatDate(d) { return `${d.toDateString()} ${d.toTimeString().split(' ')[0]}`; } -export function formatShortDate(d: Date) { - const date = DateTime.fromISO(d?.toISOString()).toISODate(); - const time = DateTime.fromISO(d?.toISOString()).toFormat('TT'); - return `${date} ${time}`; -} export function formatSimpleDate(d) { return d.toISOString().split('T')[0]; } From 0c5ccf55071eb3ac5debd6557c9c60d0753f99f0 Mon Sep 17 00:00:00 2001 From: Jean-Marc Millet Date: Wed, 10 Apr 2024 16:41:58 +0200 Subject: [PATCH 5/5] add formattedDateTime to ObjectListtable --- src/react/databrowser/objects/ObjectListTable.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/react/databrowser/objects/ObjectListTable.tsx b/src/react/databrowser/objects/ObjectListTable.tsx index 5a9f199f1..8917db2e3 100644 --- a/src/react/databrowser/objects/ObjectListTable.tsx +++ b/src/react/databrowser/objects/ObjectListTable.tsx @@ -5,7 +5,7 @@ import { AutoSizer } from 'react-virtualized'; import { FixedSizeList } from 'react-window'; import InfiniteLoader from 'react-window-infinite-loader'; import { List } from 'immutable'; -import { PrettyBytes, Text } from '@scality/core-ui'; +import { FormattedDateTime, PrettyBytes, Text } from '@scality/core-ui'; import { convertRemToPixels } from '@scality/core-ui/dist/utils'; import { spacing } from '@scality/core-ui/dist/style/theme'; import styled from 'styled-components'; @@ -271,6 +271,15 @@ export default function ObjectListTable({ headerStyle: { textAlign: 'right', }, + Cell: ({ value }) => { + return ( + + ); + }, + cellStyle: { textAlign: 'right', },