Skip to content

Commit

Permalink
feat(storage-browser): add routed example app
Browse files Browse the repository at this point in the history
  • Loading branch information
calebpollman committed Oct 24, 2024
1 parent 7df9f79 commit 65bb318
Show file tree
Hide file tree
Showing 14 changed files with 443 additions and 48 deletions.
2 changes: 0 additions & 2 deletions examples/next/pages/_document.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ class MyDocument extends Document {
</Head>
<body>
<title>React Example App</title>
<h1>React Example App</h1>

<Main />
<NextScript />
</body>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Amplify } from 'aws-amplify';

import {
createAmplifyAuthAdapter,
createStorageBrowser,
elementsDefault,
} from '@aws-amplify/ui-react-storage/browser';
import '@aws-amplify/ui-react-storage/styles.css';
import '@aws-amplify/ui-react-storage/storage-browser-styles.css';

import config from './aws-exports';

Amplify.configure(config);

const defaultPrefixes = [
'public/',
// intentionally added to test a prefix that should return 403 forbidden
'forbidden/',
(identityId: string) => `protected/${identityId}/`,
(identityId: string) => `private/${identityId}/`,
];

export const { StorageBrowser } = createStorageBrowser({
elements: elementsDefault,
config: createAmplifyAuthAdapter({ options: { defaultPrefixes } }),
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useRouter } from 'next/router';

import { signOut } from 'aws-amplify/auth';
import { Button, Flex } from '@aws-amplify/ui-react';

import { StorageBrowser } from '../../StorageBrowser';

import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
import '@aws-amplify/ui-react-storage/styles.css';

export default function Page() {
const router = useRouter();

if (!router.query.bucket) return null;

return (
<Flex>
<Button
onClick={() => {
signOut();
router.replace(
router.pathname.replace('[locations]/[location-detail]', '')
);
}}
>
Sign Out
</Button>
<StorageBrowser.Provider
actionType={
typeof router.query.actionType === 'string'
? router.query.actionType
: undefined
}
location={router.query as any}
>
<StorageBrowser.LocationDetailView
onActionSelect={(actionType) => {
router.replace({ query: { ...router.query, actionType } });
}}
onExit={() => {
router.back();
}}
/>
{typeof router.query.actionType === 'string' ? (
<dialog open={!!router.query.actionType}>
<StorageBrowser.LocationActionView
onClose={() => {
router.replace({
query: { ...router.query, actionType: undefined },
});
}}
/>
</dialog>
) : null}
</StorageBrowser.Provider>
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { useRouter } from 'next/router';

import { signOut } from 'aws-amplify/auth';
import { Button, Flex } from '@aws-amplify/ui-react';

import { StorageBrowser } from '../StorageBrowser';

import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
import '@aws-amplify/ui-react-storage/styles.css';

function Locations() {
const router = useRouter();

return (
<Flex direction="column">
<Button
onClick={() => {
signOut();
router.replace(router.pathname.replace('[locations]', ''));
}}
>
Sign Out
</Button>
<StorageBrowser.Provider>
<StorageBrowser.Provider>
<StorageBrowser.LocationsView
onNavigate={(destination) => {
router.push({
pathname: `${router.pathname}/location-detail`,
query: { ...destination },
});
}}
/>
</StorageBrowser.Provider>
</StorageBrowser.Provider>
</Flex>
);
}

export default Locations;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import awsExports from '@environments/storage/file-uploader/src/aws-exports';
export default awsExports;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { useRouter } from 'next/router';

import useIsSignedIn from './useIsSignedIn';

import { Authenticator } from '@aws-amplify/ui-react';

import '@aws-amplify/ui-react-storage/styles.css';
import '@aws-amplify/ui-react-storage/storage-browser-styles.css';

function Example() {
const router = useRouter();

useIsSignedIn({
onSignIn: () => {
router.push(`${router.pathname}/locations`);
},
});

return <Authenticator />;
}

export default Example;
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';

import { fetchAuthSession } from 'aws-amplify/auth';
import { Hub, HubCallback } from '@aws-amplify/core';
import { isFunction } from '@aws-amplify/ui';

export interface UseIsSignedInParams {
onSignIn?: () => void;
onSignOut?: () => void;
}

interface UseIsSignedIn {
isSignedIn: boolean;
}

const INITIAL_STATE: UseIsSignedIn = { isSignedIn: false };

/**
* listens for `Auth` sign in and sign out events
*
* @param {UseIsSignedInParams} params `onSignIn` and `onSignOut` event callbacks
* @returns {UseIsSignedIn} Outputs `isSignedIn`
*/
export default function useIsSignedIn({
onSignIn,
onSignOut,
}: UseIsSignedInParams): UseIsSignedIn {
const [output, setOutput] = React.useState<UseIsSignedIn>(
() => INITIAL_STATE
);

React.useEffect(() => {
fetchAuthSession().then(() => {
if (isFunction(onSignIn)) onSignIn();
});
}, [onSignIn]);

const handleEvent: HubCallback = React.useCallback(
({ payload }) => {
switch (payload.event) {
case 'signIn':
case 'autoSignIn': {
if (isFunction(onSignIn)) {
onSignIn();
}
setOutput({ isSignedIn: true });
break;
}
case 'signOut': {
if (isFunction(onSignOut)) {
onSignOut();
}
setOutput({ isSignedIn: false });
break;
}
default: {
break;
}
}
},
[onSignIn, onSignOut]
);

React.useEffect(() => {
const unsubscribe = Hub.listen('auth', handleEvent, 'useIsSignedIn');

return unsubscribe;
}, [handleEvent]);

return output;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,22 @@ import React from 'react';

import { createStorageBrowser } from '@aws-amplify/ui-react-storage/browser';

import { auth, managedAuthAdapter } from '../managedAuthAdapter';

import { Button, Flex } from '@aws-amplify/ui-react';
import { managedAuthAdapter } from '../managedAuthAdapter';
import { SignIn, SignOutButton } from './routed/components';

import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
import '@aws-amplify/ui-react-storage/styles.css';

const { StorageBrowser } = createStorageBrowser({ config: managedAuthAdapter });

function Example() {
const [authenticated, setAuthenticated] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState<string | undefined>();
const [showSignIn, setShowSignIn] = React.useState(false);

return !authenticated ? (
<Flex>
<Button
onClick={() => {
setIsLoading(true);
auth.signIn({
onSignIn: () => {
setAuthenticated(true);
setIsLoading(false);
},
onError: (e: Error) => {
setErrorMessage(e.message);
setIsLoading(false);
},
});
}}
>
Sign In
</Button>
{isLoading ? <span>Authenticating...</span> : null}
{errorMessage ? <span>{errorMessage}</span> : null}
</Flex>
return !showSignIn ? (
<SignIn onSignIn={() => setShowSignIn(true)} />
) : (
<>
<Button
size="small"
marginBlockEnd="xl"
onClick={() => {
auth.signOut({ onSignOut: () => setAuthenticated(false) });
}}
>
Sign Out
</Button>
<SignOutButton onSignOut={() => setShowSignIn(false)} />
<StorageBrowser />
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Auth } from '../../managedAuthAdapter';
import {
createManagedAuthAdapter,
createStorageBrowser,
} from '@aws-amplify/ui-react-storage/browser';

export const routedAuth = new Auth({ persistCredentials: true });

const config = createManagedAuthAdapter({
credentialsProvider: routedAuth.credentialsProvider,
region: process.env.NEXT_PUBLIC_MANAGED_AUTH_REGION,
accountId: process.env.NEXT_PUBLIC_MANAGED_AUTH_ACCOUNT_ID,
registerAuthListener: routedAuth.registerAuthListener,
});

export const { StorageBrowser } = createStorageBrowser({ config });
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useRouter } from 'next/router';

import { Flex } from '@aws-amplify/ui-react';

import { SignOutButton } from '../../components';
import { StorageBrowser } from '../../StorageBrowser';

import '@aws-amplify/ui-react-storage/storage-browser-styles.css';
import '@aws-amplify/ui-react-storage/styles.css';

export default function Page() {
const { back, query, pathname, replace } = useRouter();

if (!query.bucket) return null;

return (
<Flex>
<SignOutButton
onSignOut={() => {
replace(pathname.replace('[locations]/[location-detail]', ''));
}}
/>
<StorageBrowser.Provider
actionType={
typeof query.actionType === 'string' ? query.actionType : undefined
}
location={query as any}
>
<StorageBrowser.LocationDetailView
onActionSelect={(actionType) => {
replace({ query: { ...query, actionType } });
}}
onNavigate={(destination) => {
replace({ query: { ...destination } });
}}
onExit={() => {
back();
}}
/>
{typeof query.actionType === 'string' ? (
<dialog open={!!query.actionType}>
<StorageBrowser.LocationActionView
onClose={() => {
replace({ query: { ...query, actionType: undefined } });
}}
/>
</dialog>
) : null}
</StorageBrowser.Provider>
</Flex>
);
}
Loading

0 comments on commit 65bb318

Please sign in to comment.