Skip to content

Commit

Permalink
Merge branch 'main' into sto-bro-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanksdesign authored Nov 27, 2024
2 parents 522fb1c + 9ab56f4 commit 44c8d3f
Show file tree
Hide file tree
Showing 153 changed files with 3,378 additions and 2,911 deletions.
16 changes: 16 additions & 0 deletions .changeset/honest-beans-suffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@aws-amplify/ui-react-ai": minor
"@aws-amplify/ui": patch
---

feat(ai) add attachment validations

The current limitations on the Amplify AI kit for attachments is 400kb (of base64'd size) per image, and 20 images per message are now being enforced before the message is sent.
These limits can be adjusted via props as well.

```tsx
<AIConversation
maxAttachments={2}
maxAttachmentSize={100_000} // 100,000 bytes or 100kb
/>
```
5 changes: 5 additions & 0 deletions docs/src/components/ComponentsMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ export const ComponentsMetadata: ComponentClassNameItems = {
components: ['AIConversation'],
description: 'Class applied to the form element',
},
AIConversationFormError: {
className: ComponentClassName.AIConversationFormError,
components: ['AIConversation'],
description: 'Class applied to the error message of the form',
},
AIConversationFormAttach: {
className: ComponentClassName.AIConversationFormAttach,
components: ['AIConversation'],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as React from 'react';
import { Amplify } from 'aws-amplify';
import { signOut } from 'aws-amplify/auth';
import { createAIHooks, AIConversation } from '@aws-amplify/ui-react-ai';
import { generateClient } from 'aws-amplify/api';
import '@aws-amplify/ui-react/styles.css';

import outputs from './amplify_outputs';
import type { Schema } from '@environments/ai/gen2/amplify/data/resource';
import { Authenticator, Button, Card, Flex } from '@aws-amplify/ui-react';

const client = generateClient<Schema>({ authMode: 'userPool' });
const { useAIConversation } = createAIHooks(client);

Amplify.configure(outputs);

function Chat() {
const [
{
data: { messages },
isLoading,
},
sendMessage,
] = useAIConversation('pirateChat');

return (
<AIConversation
messages={messages}
isLoading={isLoading}
handleSendMessage={sendMessage}
allowAttachments
maxAttachmentSize={100_000}
maxAttachments={2}
/>
);
}

export default function Example() {
return (
<Authenticator>
<Flex direction="column">
<Button
onClick={() => {
signOut();
}}
>
Sign out
</Button>
<Card flex="1" variation="outlined" height="400px" margin="large">
<Chat />
</Card>
</Flex>
</Authenticator>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { Auth } from '../managedAuthAdapter';
import { Button, Flex, Breadcrumbs } from '@aws-amplify/ui-react';

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

const components: CreateStorageBrowserInput['components'] = {
Navigation: ({ items }) => (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React from 'react';

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

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

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

const { StorageBrowser } = createStorageBrowser({
actions: {
default: {
copy: {
actionListItem: {
icon: 'copy-file',
label: 'Override Copy',
},
handler: ({ data }) => {
const { key } = data;
return {
result: Promise.resolve({ status: 'COMPLETE', value: { key } }),
};
},
viewName: 'CopyView',
},
createFolder: {
actionListItem: {
icon: 'create-folder',
label: 'Override Create Folder',
},
handler: ({ data }) => {
const { key } = data;
return {
result: Promise.resolve({ status: 'COMPLETE', value: { key } }),
};
},
viewName: 'CreateFolderView',
},
delete: {
actionListItem: {
icon: 'delete-file',
label: 'Override Delete',
},
handler: ({ data }) => {
const { key } = data;
return {
result: Promise.resolve({ status: 'COMPLETE', value: { key } }),
};
},
viewName: 'DeleteView',
},
download: () => {
return {
result: Promise.resolve({
status: 'COMPLETE',
value: { url: new URL('') },
}),
};
},
upload: {
actionListItem: {
icon: 'upload-file',
label: 'Override Upload',
},
handler: ({ data }) => {
const { key } = data;
return {
result: Promise.resolve({ status: 'COMPLETE', value: { key } }),
};
},
viewName: 'UploadView',
},
listLocationItems: () =>
Promise.resolve({
items: [
{
id: 'jaskjkaska',
key: 'item-key',
lastModified: new Date(),
size: 1008,
type: 'FILE' as const,
},
],
nextToken: undefined,
}),
},
},
config: {
getLocationCredentials: () =>
Promise.resolve({
credentials: {
accessKeyId: '',
expiration: new Date(),
secretAccessKey: '',
sessionToken: '',
},
}),
region: '',
registerAuthListener: () => null,
listLocations: () =>
Promise.resolve({
items: [
{
bucket: 'my-bucket',
id: crypto.randomUUID(),
permissions: ['delete', 'get', 'list', 'write'],
prefix: 'my-prefix',
type: 'PREFIX',
},
],
nextToken: undefined,
}),
},
});

function Example() {
return (
<Flex
direction="column"
width="100vw"
height="100vh"
overflow="hidden"
padding="xl"
>
<StorageBrowser />
</Flex>
);
}

export default Example;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
import { StorageBrowser } from '@aws-amplify/ui-react-storage';

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

import config from './aws-exports';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import {
createAmplifyAuthAdapter,
createStorageBrowser,
} 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';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,104 @@
import React from 'react';
import { getUrl } from '@aws-amplify/storage/internals';

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

import { managedAuthAdapter } from '../managedAuthAdapter';
import { SignIn, SignOutButton } from './routed/components';

import { Flex, View } from '@aws-amplify/ui-react';
import {
Button,
Flex,
Link,
StepperField,
Text,
View,
} from '@aws-amplify/ui-react';

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

const { StorageBrowser } = createStorageBrowser({
type GetLink = ActionHandler<{ duration: number; fileKey: string }, string>;

const getLink: GetLink = ({ data, config }) => {
const result = getUrl({
path: data.key,
options: {
bucket: { bucketName: config.bucket, region: config.region },
locationCredentialsProvider: config.credentials,
expiresIn: data.duration * 60,
validateObjectExistence: true,
},
}).then((res) => ({
status: 'COMPLETE' as const,
value: res.url.toString(),
}));

return { result };
};

const generateLink: ActionViewConfig<GetLink, 'LinkActionView'> = {
handler: getLink,
viewName: 'LinkActionView',
actionListItem: {
icon: 'download',
label: 'Generate Download Links',
disable: (selected) => !selected?.length,
},
};

const { StorageBrowser, useAction, useView } = createStorageBrowser({
actions: { custom: { generateLink } },
config: managedAuthAdapter,
});

const LinkActionView = () => {
const [duration, setDuration] = React.useState(60);

const locationDetailState = useView('LocationDetail');
const { onActionExit, fileDataItems } = locationDetailState;

const items = React.useMemo(
() =>
!fileDataItems
? []
: fileDataItems.map((item) => ({ ...item, duration })),
[fileDataItems, duration]
);

const [{ tasks }, handleCreate] = useAction('generateLink', { items });

return (
<Flex direction="column">
<Button onClick={onActionExit}>Exit</Button>
<StepperField
label="Duration"
step={15}
value={duration}
min={15}
max={300}
onStepChange={(value) => {
setDuration(value);
}}
/>
<Button onClick={() => handleCreate()}>Start</Button>
{!tasks
? null
: tasks.map(({ data, status, value }) => {
return (
<Flex direction="row" key={data.fileKey}>
<Text>{data.fileKey}</Text>
{value ? <Link href={value}>link</Link> : null}
<Text>{status}</Text>
</Flex>
);
})}
</Flex>
);
};

function Example() {
const [showSignIn, setShowSignIn] = React.useState(false);

Expand All @@ -29,9 +114,8 @@ function Example() {
>
<SignOutButton onSignOut={() => setShowSignIn(false)} />
<View flex="1" overflow="hidden">
<StorageBrowser
displayText={{ LocationsView: { title: 'Home - Managed Auth' } }}
/>
<StorageBrowser views={{ LinkActionView }} />
<StorageBrowser.LocationActionView />
</View>
</Flex>
);
Expand Down
Loading

0 comments on commit 44c8d3f

Please sign in to comment.