Skip to content

Commit 18cb4f4

Browse files
committed
feat(os): add refresh button on objects
ref: #DATATR-2633 Signed-off-by: Lionel Bueno <lionel.bueno.ext@ovhcloud.com>
1 parent 8e435a1 commit 18cb4f4

File tree

7 files changed

+99
-29
lines changed

7 files changed

+99
-29
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Button } from '@datatr-ux/uxlib';
2+
import { RefreshCw } from 'lucide-react';
3+
4+
interface RefreshButtonProps {
5+
onRefresh: () => void;
6+
isRefetching: boolean;
7+
}
8+
9+
export default function RefreshButton({
10+
onRefresh,
11+
isRefetching,
12+
}: RefreshButtonProps) {
13+
return (
14+
<Button
15+
mode="outline"
16+
className="h-10 px-4"
17+
onClick={onRefresh}
18+
disabled={isRefetching}
19+
>
20+
<RefreshCw className={`size-4 ${isRefetching ? 'animate-spin' : ''}`} />
21+
</Button>
22+
);
23+
}

packages/manager/apps/pci-object-storage/src/configuration/polling.constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const POLLING = {
44
S3: 30_000,
55
OBJECT: 45_000,
66
USER_CREATION: 2500,
7+
OBJECTS_REFRESH: 10_000,
78
};
89

910
export const USER_INACTIVITY_TIMEOUT = 5 * 60_000; // inactivity after 5 minutes

packages/manager/apps/pci-object-storage/src/pages/object-storage/storage/s3Id/objects/Objects.page.tsx

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import S3ObjectBrowser from './_components/S3ObjectBrowser.component';
1717
import { useObjectStorageData } from '@/pages/object-storage/ObjectStorage.context';
1818
import { useIsLocaleZone } from '@/hooks/useIsLocalZone.hook';
1919
import SearchBar from './_components/SearchBar.component';
20+
import RefreshButton from '@/components/refresh-button/RefreshButton.component';
21+
import { POLLING } from '@/configuration/polling.constants';
2022

2123
const Objects = () => {
2224
const { projectId } = useParams();
@@ -32,6 +34,9 @@ const Objects = () => {
3234
region: s3.region,
3335
name: s3.name,
3436
withVersions: withVersion,
37+
options: {
38+
refetchInterval: POLLING.OBJECTS_REFRESH,
39+
},
3540
});
3641
const navigate = useNavigate();
3742

@@ -75,23 +80,30 @@ const Objects = () => {
7580
<Plus className="size-6" />
7681
{t('addNewObject')}
7782
</Button>
78-
{!isLocaleZone && (
79-
<div className="flex items-center space-x-2">
80-
<Switch
81-
id="versions"
82-
checked={withVersion}
83-
onCheckedChange={setWithVersion}
84-
/>
85-
<Label htmlFor="versions">{t('seeVersionsSwitchLabel')}</Label>
86-
<SearchBar
87-
searchQuery={searchQuery}
88-
onSearchChange={setSearchQuery}
89-
deferredSearchQuery={deferredSearchQuery}
90-
filteredObjects={filteredObjects}
91-
placeholder={t('searchPlaceholder') || 'Search...'}
92-
/>
93-
</div>
94-
)}
83+
<div className="flex items-center space-x-2">
84+
<RefreshButton
85+
onRefresh={() => objectQuery.refetch()}
86+
isRefetching={objectQuery.isFetching}
87+
/>
88+
{!isLocaleZone && (
89+
<>
90+
<Switch
91+
id="versions"
92+
checked={withVersion}
93+
onCheckedChange={setWithVersion}
94+
/>
95+
<Label htmlFor="versions">{t('seeVersionsSwitchLabel')}</Label>
96+
<SearchBar
97+
searchQuery={searchQuery}
98+
onSearchChange={setSearchQuery}
99+
deferredSearchQuery={deferredSearchQuery}
100+
filteredObjects={filteredObjects}
101+
placeholder={t('searchPlaceholder') || 'Search...'}
102+
/>
103+
</>
104+
)}
105+
106+
</div>
95107
</div>
96108
<S3ObjectBrowser
97109
objects={objects}

packages/manager/apps/pci-object-storage/src/pages/object-storage/storage/s3Id/objects/object/versions/Versions.page.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useS3Data } from '../../../S3.context';
55
import DataTable from '@/components/data-table';
66
import S3ObjectVersionList from './_components/S3VersionObjectListTable.component';
77
import { useGetS3ObjectVersions } from '@/data/hooks/s3-storage/useGetS3ObjectVersions.hook';
8+
import { POLLING } from '@/configuration/polling.constants';
89

910
const Versions = () => {
1011
const { t } = useTranslation('pci-object-storage/storages/s3/objects');
@@ -18,6 +19,9 @@ const Versions = () => {
1819
region: s3.region,
1920
name: s3.name,
2021
key: objectKey,
22+
options: {
23+
refetchInterval: POLLING.OBJECTS_REFRESH,
24+
},
2125
});
2226

2327
if (objectVersionQuery.isLoading) {
@@ -41,7 +45,11 @@ const Versions = () => {
4145
return (
4246
<>
4347
<h2>{t('versionsTitle')}</h2>
44-
<S3ObjectVersionList objects={objectVersionQuery.data} />
48+
<S3ObjectVersionList
49+
objects={objectVersionQuery.data}
50+
onRefresh={() => objectVersionQuery.refetch()}
51+
isRefetching={objectVersionQuery.isFetching}
52+
/>
4553
<Outlet />
4654
</>
4755
);

packages/manager/apps/pci-object-storage/src/pages/object-storage/storage/s3Id/objects/object/versions/_components/S3VersionObjectListTable.component.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,19 @@ import { getObjectStoreApiErrorMessage } from '@/lib/apiHelper';
1414
import { useGetPresignUrlS3 } from '@/data/hooks/s3-storage/useGetPresignUrlS3.hook';
1515
import { useS3Data } from '../../../../S3.context';
1616
import Link from '@/components/links/Link.component';
17+
import RefreshButton from '@/components/refresh-button/RefreshButton.component';
1718

1819
interface ObjectsListProps {
1920
objects: StorageObject[];
21+
onRefresh: () => void;
22+
isRefetching: boolean;
2023
}
2124

22-
export default function S3ObjectVersionList({ objects }: ObjectsListProps) {
25+
export default function S3ObjectVersionList({
26+
objects,
27+
onRefresh,
28+
isRefetching,
29+
}: ObjectsListProps) {
2330
const { projectId } = useParams();
2431
const { s3 } = useS3Data();
2532
const [objectName, setObjectName] = useState<string>('');
@@ -78,10 +85,13 @@ export default function S3ObjectVersionList({ objects }: ObjectsListProps) {
7885
pageSize={25}
7986
filtersDefinition={storagesFilters}
8087
>
81-
<DataTable.Header>
82-
<DataTable.SearchBar />
83-
<DataTable.FiltersButton />
84-
</DataTable.Header>
88+
<div className="w-full flex flex-col sm:flex-row gap-2 pb-4">
89+
<div className="flex ml-auto gap-2">
90+
<RefreshButton onRefresh={onRefresh} isRefetching={isRefetching} />
91+
<DataTable.SearchBar />
92+
<DataTable.FiltersButton />
93+
</div>
94+
</div>
8595
<DataTable.FiltersList />
8696
<DataTable.Table />
8797
<DataTable.Pagination />

packages/manager/apps/pci-object-storage/src/pages/object-storage/storage/swiftId/Swift.context.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@ import { UseQueryResult } from '@tanstack/react-query';
22
import { useParams } from 'react-router-dom';
33
import storages from '@/types/Storages';
44
import { useGetSwift } from '@/data/hooks/swift-storage/useGetSwift.hook';
5+
import { OptionsFor } from '@/hooks/useImmediateRefetch';
6+
import { getSwiftStorage } from '@/data/api/storage/swiftStorage.api';
57

68
// Share data with the child routes
79
export type SwiftLayoutContext = {
810
swift: storages.ContainerDetail;
911
swiftQuery: UseQueryResult<storages.ContainerDetail, Error>;
1012
};
11-
export const useSwiftData = () => {
13+
export const useSwiftData = (
14+
queryOptions?: OptionsFor<typeof getSwiftStorage>,
15+
) => {
1216
const { projectId, swiftId } = useParams();
1317
const swiftQuery = useGetSwift({
1418
projectId,
1519
containerId: swiftId,
1620
noObjects: false,
21+
options: queryOptions,
1722
});
1823
return { projectId, swift: swiftQuery.data, swiftQuery };
1924
};

packages/manager/apps/pci-object-storage/src/pages/object-storage/storage/swiftId/objects/Objects.page.tsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ import { useSwiftData } from '../Swift.context';
66
import Guides from '@/components/guides/Guides.component';
77
import RoadmapChangelog from '@/components/roadmap-changelog/RoadmapChangelog.component';
88
import SwiftObjectBrowser from './_components/SwiftObjectBrowser.component';
9+
import RefreshButton from '@/components/refresh-button/RefreshButton.component';
10+
import { POLLING } from '@/configuration/polling.constants';
911

1012
const SwiftObjectsPage = () => {
1113
const { t } = useTranslation('pci-object-storage/storages/swift/objects');
12-
const { swiftQuery } = useSwiftData();
14+
const { swiftQuery } = useSwiftData({
15+
refetchInterval: POLLING.OBJECTS_REFRESH,
16+
});
1317
const navigate = useNavigate();
1418

1519
if (swiftQuery.isLoading) return <Skeleton className="h-96 w-full" />;
@@ -24,10 +28,17 @@ const SwiftObjectsPage = () => {
2428
</div>
2529
</div>
2630

27-
<Button onClick={() => navigate('./add-object')}>
28-
<Plus className="size-6" />
29-
{t('addNewObject')}
30-
</Button>
31+
<div className="flex items-center gap-2">
32+
<RefreshButton
33+
onRefresh={() => swiftQuery.refetch()}
34+
isRefetching={swiftQuery.isFetching}
35+
/>
36+
<Button onClick={() => navigate('./add-object')}>
37+
<Plus className="size-6" />
38+
{t('addNewObject')}
39+
</Button>
40+
41+
</div>
3142

3243
<SwiftObjectBrowser objects={objects} />
3344
<Outlet />

0 commit comments

Comments
 (0)