Skip to content

Commit 769b811

Browse files
author
Ahmed Hamouda
committed
feat(storage): add pageSize support to StorageBrowser
1 parent 172b461 commit 769b811

File tree

38 files changed

+583
-82
lines changed

38 files changed

+583
-82
lines changed
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
import React, { useState } from 'react';
2+
import { Amplify } from 'aws-amplify';
3+
4+
import {
5+
Flex,
6+
View,
7+
SelectField,
8+
Text,
9+
Alert,
10+
Tabs,
11+
} from '@aws-amplify/ui-react';
12+
import { StorageBrowser } from '@aws-amplify/ui-react-storage';
13+
import {
14+
createStorageBrowser,
15+
createAmplifyAuthAdapter,
16+
} from '@aws-amplify/ui-react-storage/browser';
17+
import config from './aws-exports';
18+
19+
import '@aws-amplify/ui-react-storage/styles.css';
20+
21+
Amplify.configure(config);
22+
23+
// Create StorageBrowser with composition API
24+
const { StorageBrowser: ComposableStorageBrowser } = createStorageBrowser({
25+
config: createAmplifyAuthAdapter(),
26+
});
27+
28+
function PaginationCompositionTest() {
29+
const [globalPageSize, setGlobalPageSize] = useState<number>(100);
30+
const [locationsPageSize, setLocationsPageSize] = useState<number>(25);
31+
const [detailPageSize, setDetailPageSize] = useState<number>(50);
32+
const [uploadPageSize, setUploadPageSize] = useState<number>(30);
33+
const [copyPageSize, setCopyPageSize] = useState<number>(20);
34+
const [deletePageSize, setDeletePageSize] = useState<number>(15);
35+
const [downloadPageSize, setDownloadPageSize] = useState<number>(25);
36+
const [showAlert, setShowAlert] = useState(true);
37+
38+
const pageSizeOptions = [
39+
{ value: 10, label: '10 items' },
40+
{ value: 20, label: '20 items' },
41+
{ value: 25, label: '25 items' },
42+
{ value: 30, label: '30 items' },
43+
{ value: 50, label: '50 items' },
44+
{ value: 100, label: '100 items' },
45+
{ value: 200, label: '200 items' },
46+
];
47+
48+
return (
49+
<Flex direction="column" width="100vw" height="100vh" padding="xl">
50+
{showAlert && (
51+
<Alert
52+
variation="info"
53+
isDismissible
54+
onDismiss={() => setShowAlert(false)}
55+
marginBlockEnd="medium"
56+
>
57+
<Text>
58+
<strong>🧪 StorageBrowser Per-View Pagination Test</strong>
59+
<br />
60+
Testing per-view pageSize configuration. Each view can override the
61+
global pageSize. LocationsView: {locationsPageSize},
62+
LocationDetailView: {detailPageSize}, UploadView: {uploadPageSize},
63+
CopyView: {copyPageSize}, DeleteView: {deletePageSize},
64+
DownloadView: {downloadPageSize}, Global: {globalPageSize} items.
65+
</Text>
66+
</Alert>
67+
)}
68+
69+
<Flex
70+
justifyContent="space-between"
71+
alignItems="center"
72+
marginBlockEnd="xl"
73+
wrap="wrap"
74+
gap="medium"
75+
>
76+
<Text fontSize="xl" fontWeight="bold">
77+
Per-View Pagination Configuration
78+
</Text>
79+
80+
<Flex alignItems="center" gap="large" wrap="wrap">
81+
<Flex alignItems="center" gap="small">
82+
<Text fontWeight="bold">Global:</Text>
83+
<SelectField
84+
label=""
85+
value={globalPageSize.toString()}
86+
onChange={(e) => setGlobalPageSize(parseInt(e.target.value))}
87+
width="100px"
88+
>
89+
{pageSizeOptions.map(({ value, label }) => (
90+
<option key={value} value={value}>
91+
{label}
92+
</option>
93+
))}
94+
</SelectField>
95+
</Flex>
96+
97+
<Flex alignItems="center" gap="small">
98+
<Text fontWeight="bold">Locations:</Text>
99+
<SelectField
100+
label=""
101+
value={locationsPageSize.toString()}
102+
onChange={(e) => setLocationsPageSize(parseInt(e.target.value))}
103+
width="100px"
104+
>
105+
{pageSizeOptions.map(({ value, label }) => (
106+
<option key={value} value={value}>
107+
{label}
108+
</option>
109+
))}
110+
</SelectField>
111+
</Flex>
112+
113+
<Flex alignItems="center" gap="small">
114+
<Text fontWeight="bold">Detail:</Text>
115+
<SelectField
116+
label=""
117+
value={detailPageSize.toString()}
118+
onChange={(e) => setDetailPageSize(parseInt(e.target.value))}
119+
width="100px"
120+
>
121+
{pageSizeOptions.map(({ value, label }) => (
122+
<option key={value} value={value}>
123+
{label}
124+
</option>
125+
))}
126+
</SelectField>
127+
</Flex>
128+
129+
<Flex alignItems="center" gap="small">
130+
<Text fontWeight="bold">Upload:</Text>
131+
<SelectField
132+
label=""
133+
value={uploadPageSize.toString()}
134+
onChange={(e) => setUploadPageSize(parseInt(e.target.value))}
135+
width="100px"
136+
>
137+
{pageSizeOptions.map(({ value, label }) => (
138+
<option key={value} value={value}>
139+
{label}
140+
</option>
141+
))}
142+
</SelectField>
143+
</Flex>
144+
145+
<Flex alignItems="center" gap="small">
146+
<Text fontWeight="bold">Copy:</Text>
147+
<SelectField
148+
label=""
149+
value={copyPageSize.toString()}
150+
onChange={(e) => setCopyPageSize(parseInt(e.target.value))}
151+
width="100px"
152+
>
153+
{pageSizeOptions.map(({ value, label }) => (
154+
<option key={value} value={value}>
155+
{label}
156+
</option>
157+
))}
158+
</SelectField>
159+
</Flex>
160+
161+
<Flex alignItems="center" gap="small">
162+
<Text fontWeight="bold">Delete:</Text>
163+
<SelectField
164+
label=""
165+
value={deletePageSize.toString()}
166+
onChange={(e) => setDeletePageSize(parseInt(e.target.value))}
167+
width="100px"
168+
>
169+
{pageSizeOptions.map(({ value, label }) => (
170+
<option key={value} value={value}>
171+
{label}
172+
</option>
173+
))}
174+
</SelectField>
175+
</Flex>
176+
177+
<Flex alignItems="center" gap="small">
178+
<Text fontWeight="bold">Download:</Text>
179+
<SelectField
180+
label=""
181+
value={downloadPageSize.toString()}
182+
onChange={(e) => setDownloadPageSize(parseInt(e.target.value))}
183+
width="100px"
184+
>
185+
{pageSizeOptions.map(({ value, label }) => (
186+
<option key={value} value={value}>
187+
{label}
188+
</option>
189+
))}
190+
</SelectField>
191+
</Flex>
192+
</Flex>
193+
</Flex>
194+
195+
<Tabs
196+
defaultValue="composition"
197+
items={[
198+
{
199+
label: 'Composition Mode',
200+
value: 'composition',
201+
content: (
202+
<View height="100%" overflow="auto">
203+
<ComposableStorageBrowser.Provider
204+
key={`${globalPageSize}-${locationsPageSize}-${detailPageSize}-${uploadPageSize}-${copyPageSize}-${deletePageSize}-${downloadPageSize}`}
205+
pageSize={globalPageSize}
206+
>
207+
<ComposableStorageBrowser.LocationsView
208+
pageSize={locationsPageSize}
209+
/>
210+
<ComposableStorageBrowser.LocationDetailView
211+
pageSize={detailPageSize}
212+
/>
213+
<ComposableStorageBrowser.UploadView
214+
pageSize={uploadPageSize}
215+
/>
216+
<ComposableStorageBrowser.CopyView pageSize={copyPageSize} />
217+
<ComposableStorageBrowser.DeleteView
218+
pageSize={deletePageSize}
219+
/>
220+
<ComposableStorageBrowser.DownloadView
221+
pageSize={downloadPageSize}
222+
/>
223+
</ComposableStorageBrowser.Provider>
224+
</View>
225+
),
226+
},
227+
{
228+
label: 'Standard Mode',
229+
value: 'standard',
230+
content: (
231+
<View height="600px" overflow="auto">
232+
<StorageBrowser
233+
key={globalPageSize}
234+
pageSize={globalPageSize}
235+
displayText={{
236+
LocationsView: {
237+
title: `Standard StorageBrowser - ${globalPageSize} items per page (all views)`,
238+
},
239+
}}
240+
/>
241+
</View>
242+
),
243+
},
244+
]}
245+
/>
246+
</Flex>
247+
);
248+
}
249+
250+
export default PaginationCompositionTest;

examples/next/pages/ui/components/storage/storage-browser/default-auth/pagination-test.page.tsx

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ Amplify.configure(config);
1111

1212
function PaginationTest() {
1313
const [pageSize, setPageSize] = useState<number>(10);
14-
const [showPagination, setShowPagination] = useState<boolean>(false);
1514
const [showAlert, setShowAlert] = useState(true);
1615

1716
const pageSizeOptions = [
@@ -20,6 +19,8 @@ function PaginationTest() {
2019
{ value: 25, label: '25 items per page' },
2120
{ value: 50, label: '50 items per page' },
2221
{ value: 100, label: '100 items per page' },
22+
{ value: 500, label: '500 items per page' },
23+
{ value: 1000, label: '1000 items per page' },
2324
];
2425

2526
return (
@@ -40,9 +41,10 @@ function PaginationTest() {
4041
<Text>
4142
<strong>🧪 StorageBrowser Pagination Test</strong>
4243
<br />
43-
Testing the new pageSize prop. Change the page size below and
44-
observe the pagination behavior. Check browser console for
45-
validation warnings when invalid values are used.
44+
Testing the new pageSize prop with per-view configuration support.
45+
Change the page size below and observe the pagination behavior.
46+
Check browser console for validation warnings when invalid values
47+
are used. No upper limit on pageSize - test with large values!
4648
</Text>
4749
</Alert>
4850
)}
@@ -68,7 +70,7 @@ function PaginationTest() {
6870
setPageSize(newPageSize);
6971
console.log(`📄 Page size changed to: ${newPageSize}`);
7072
}}
71-
width="180px"
73+
width="200px"
7274
>
7375
{pageSizeOptions.map(({ value, label }) => (
7476
<option key={value} value={value}>
@@ -77,30 +79,18 @@ function PaginationTest() {
7779
))}
7880
{/* Test invalid values */}
7981
<option value="0">0 (invalid - will use default)</option>
80-
<option value="1001">1001 (invalid - will use default)</option>
82+
<option value="-5">-5 (invalid - will use default)</option>
8183
</SelectField>
82-
83-
<label>
84-
<input
85-
type="checkbox"
86-
checked={showPagination}
87-
onChange={(e) => setShowPagination(e.target.checked)}
88-
/>
89-
<Text marginLeft="small">Show Pagination</Text>
90-
</label>
9184
</Flex>
9285
</Flex>
9386

9487
<View flex="1" overflow="hidden">
9588
<StorageBrowser
96-
key={`${pageSize}-${showPagination}`}
89+
key={pageSize}
9790
pageSize={pageSize}
98-
showPagination={showPagination}
9991
displayText={{
10092
LocationsView: {
101-
title: `Pagination Test - ${pageSize} items per page${
102-
showPagination ? ' (with pagination)' : ''
103-
}`,
93+
title: `Pagination Test - ${pageSize} items per page`,
10494
},
10595
}}
10696
/>

packages/react-storage/src/components/StorageBrowser/configuration/paginationContext.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { createContextUtilities } from '@aws-amplify/ui-react-core';
33

44
export interface PaginationConfig {
55
pageSize: number;
6-
showPagination: boolean;
76
}
87

98
const ERROR_MESSAGE =
@@ -18,18 +17,13 @@ export const { usePaginationConfig, PaginationConfigContext } =
1817
export interface PaginationConfigProviderProps {
1918
children?: React.ReactNode;
2019
pageSize: number;
21-
showPagination: boolean;
2220
}
2321

2422
export function PaginationConfigProvider({
2523
children,
2624
pageSize,
27-
showPagination,
2825
}: PaginationConfigProviderProps): React.JSX.Element {
29-
const value = React.useMemo(
30-
() => ({ pageSize, showPagination }),
31-
[pageSize, showPagination]
32-
);
26+
const value = React.useMemo(() => ({ pageSize }), [pageSize]);
3327

3428
return (
3529
<PaginationConfigContext.Provider value={value}>

packages/react-storage/src/components/StorageBrowser/createStorageBrowser/__tests__/createProvider.spec.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import { render } from '@testing-library/react';
33

44
import { ActionConfigsProvider, getActionConfigs } from '../../actions';
55
import { ComponentsProvider } from '../../components';
6-
import { createConfigurationProvider } from '../../configuration';
6+
import {
7+
createConfigurationProvider,
8+
PaginationConfigProvider,
9+
} from '../../configuration';
710
import { DisplayTextProvider } from '../../displayText';
811
import { FileItemsProvider } from '../../fileItems';
912
import { FilePreviewProvider } from '../../filePreview';
@@ -25,6 +28,9 @@ jest.mock('../../configuration');
2528
jest.mock('../../store');
2629
jest.mock('../../useAction');
2730
jest.mock('../../views');
31+
jest
32+
.mocked(PaginationConfigProvider)
33+
.mockImplementation(({ children }) => <>{children}</>);
2834

2935
const mockActionConfigsProvider = jest
3036
.mocked(ActionConfigsProvider)

packages/react-storage/src/components/StorageBrowser/createStorageBrowser/createProvider.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,14 @@ export default function createProvider<
9292
displayText,
9393
views,
9494
pageSize,
95-
showPagination = false,
9695
...props
9796
}: StorageBrowserProviderProps) {
9897
const validatedPageSize = validatePageSize(pageSize);
9998

10099
return (
101100
<StoreProvider {...props}>
102101
<ConfigurationProvider>
103-
<PaginationConfigProvider
104-
pageSize={validatedPageSize}
105-
showPagination={showPagination}
106-
>
102+
<PaginationConfigProvider pageSize={validatedPageSize}>
107103
<ActionConfigsProvider actionConfigs={actionConfigs}>
108104
<ActionHandlersProvider handlers={handlers}>
109105
<DisplayTextProvider displayText={displayText}>

0 commit comments

Comments
 (0)