Skip to content

Commit 181f4db

Browse files
authored
[Chat] Updated Storybook For File Sharing GA Release (#4620)
1 parent fa0261c commit 181f4db

15 files changed

+370
-56
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "minor",
3+
"area": "improvement",
4+
"workstream": "File Sharing",
5+
"comment": "Updated Storybook for File Sharing GA Release",
6+
"packageName": "@azure/communication-react",
7+
"email": "[email protected]",
8+
"dependentChangeType": "patch"
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "minor",
3+
"area": "improvement",
4+
"workstream": "File Sharing",
5+
"comment": "Updated Storybook for File Sharing GA Release",
6+
"packageName": "@azure/communication-react",
7+
"email": "[email protected]",
8+
"dependentChangeType": "patch"
9+
}

packages/storybook/stories/MessageThread/MessageThread.stories.tsx

+33-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
IDropdownOption
2222
} from '@fluentui/react';
2323
import { Divider } from '@fluentui/react-components';
24-
import { Canvas, Description, Heading, Props, Source, Title } from '@storybook/addon-docs';
24+
import { Canvas, Description, Heading, Props, Source, Subtitle, Title } from '@storybook/addon-docs';
2525
import { Meta } from '@storybook/react/types-6-0';
2626
import React, { useEffect, useRef, useState } from 'react';
2727
import { DetailedBetaBanner } from '../BetaBanners/DetailedBetaBanner';
@@ -54,6 +54,7 @@ import { MessageThreadWithCustomTimestampExample } from './snippets/CustomTimest
5454
import { DefaultMessageThreadExample } from './snippets/Default.snippet';
5555
import { MessageThreadWithMessageStatusIndicatorExample } from './snippets/MessageStatusIndicator.snippet';
5656
import { MessageWithAttachment } from './snippets/MessageWithAttachment.snippet';
57+
import { MessageWithAttachmentFromTeams } from './snippets/MessageWithAttachmentFromTeams.snippet';
5758
import { MessageWithCustomAttachment } from './snippets/MessageWithCustomAttachment.snippet';
5859
import { MessageWithCustomMentionRenderer } from './snippets/MessageWithCustomMentionRenderer.snippet';
5960
import { MessageThreadWithSystemMessagesExample } from './snippets/SystemMessages.snippet';
@@ -80,6 +81,8 @@ const DefaultMessageThreadExampleText = require('!!raw-loader!./snippets/Default
8081
const MessageThreadWithMessageStatusIndicatorExampleText =
8182
require('!!raw-loader!./snippets/MessageStatusIndicator.snippet.tsx').default;
8283
const MessageWithAttachmentText = require('!!raw-loader!./snippets/MessageWithAttachment.snippet.tsx').default;
84+
const MessageWithAttachmentFromTeamsText =
85+
require('!!raw-loader!./snippets/MessageWithAttachmentFromTeams.snippet.tsx').default;
8386
const MessageWithCustomAttachmentText =
8487
require('!!raw-loader!./snippets/MessageWithCustomAttachment.snippet.tsx').default;
8588
const MessageWithCustomMentionRendererText =
@@ -346,19 +349,37 @@ const Docs: () => JSX.Element = () => {
346349

347350
<div ref={refDisplayAttachments}>
348351
<Heading>Display Messages with Attachments</Heading>
352+
<Subtitle>Basic Usage: Default Attachment Rendering</Subtitle>
349353
<DetailedBetaBanner />
350354
<Description>
351-
The MessageThread component supports rendering of message attachments, including multiple ways to customize
352-
it. Developers can opt to use the default attachment rendering by not providing `attachmentOptions`. In the
353-
following example, the default attachment rendering is shown with an attachment on the first chat message. By
354-
default, the browser `window.open` method will be called with the target URL.
355+
The MessageThread component renders message attachments without any additional configuration. Simply provide a
356+
list of `ChatMessages` with attachments of type `AttachmentMetadata` and the component will render the message
357+
content along with associated attachments.
358+
</Description>
359+
<Description>
360+
By default, the button associated with the attachment card will open the attachment in a new tab.
361+
Specifically, `window.open` method will be called for target `URL` defined in `AttachmentMetadata`.
355362
</Description>
356363
<Canvas mdxSource={MessageWithAttachmentText}>
357364
<MessageWithAttachment />
358365
</Canvas>
359366
<Description>
360-
The `attachmentOptions` allows the attachmentCard to be customized in multiple ways. For example, developers
361-
can have a custom icon, label for the button and custom `onClick` callback.
367+
If the identity of message sender is a Microsoft Teams user, the attachment will be rendered with an `open`
368+
icon shown below.
369+
</Description>
370+
<Canvas mdxSource={MessageWithAttachmentFromTeamsText}>
371+
<MessageWithAttachmentFromTeams />
372+
</Canvas>
373+
<Subtitle>Advanced Usage: Customizing Attachment Rendering</Subtitle>
374+
<DetailedBetaBanner />
375+
<Description>
376+
The MessageThread component also supports multiple ways to customize the rendering. You can leverage the
377+
`attachmentOptions.downloadOptions` props to provide a dynamic list of menu action buttons that will be based
378+
on properties of the attachment or the chat message associated with it. Moreover, you can also opt to provide
379+
a static list for all secanrios.
380+
</Description>
381+
<Description>
382+
For example, the following code snippet demonstrates how to customize the download options for attachments.
362383
</Description>
363384
<Canvas mdxSource={MessageWithCustomAttachmentText}>
364385
<MessageWithCustomAttachment />
@@ -657,7 +678,11 @@ export default {
657678
onRenderMessage: hiddenControl,
658679
onUpdateMessage: hiddenControl,
659680
onDeleteMessage: hiddenControl,
660-
disableEditing: hiddenControl
681+
disableEditing: hiddenControl,
682+
// hide unnecessary props since we "send message with attachments" option
683+
onRenderAttachmentDownloads: hiddenControl,
684+
attachmentOptions: hiddenControl,
685+
onSendMessage: hiddenControl
661686
},
662687
parameters: {
663688
docs: {

packages/storybook/stories/MessageThread/snippets/MessageWithAttachment.snippet.tsx

+9-9
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,28 @@ export const MessageWithAttachment: () => JSX.Element = () => {
1313
messages={[
1414
{
1515
messageType: 'chat',
16-
senderId: 'user1',
17-
senderDisplayName: 'Kat Larsson',
18-
messageId: Math.random().toString(),
19-
content: 'Here is my router configuration file.',
16+
senderId: '8:acs:7a7894bb-0d53-4fe8-b83e-dce84ade5e89',
17+
senderDisplayName: 'Robert Tolbert',
18+
messageId: `64d334be-f30c-4218-bc1c-853a28512187`,
19+
content: 'Here is my router configuration file',
2020
createdOn: new Date('2019-04-13T00:00:00.000+08:10'),
2121
mine: false,
2222
attached: false,
2323
status: 'seen' as MessageStatus,
2424
contentType: 'text',
2525
attachments: [
2626
{
27-
id: 'a021eacd612d',
28-
name: 'RouterConfig.xlsx',
29-
url: 'https://<file_url>/RouterConfig.xlsx'
27+
id: 'p121eacd612d',
28+
name: 'RouterConfig.txt',
29+
url: 'https://www.bing.com'
3030
}
3131
]
3232
},
3333
{
3434
messageType: 'chat',
3535
senderId: 'user2',
36-
senderDisplayName: 'Robert Tolbert',
37-
messageId: Math.random().toString(),
36+
senderDisplayName: 'Kat Larsson',
37+
messageId: `348eda2f-1582-4f29-bb5d-cda7295ca398`,
3838
content: 'Thanks for sharing. This will help me troubleshoot your internet connection.',
3939
createdOn: new Date('2019-04-13T00:00:00.000+08:09'),
4040
mine: true,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { FluentThemeProvider, MessageStatus, MessageThread } from '@azure/communication-react';
2+
import { initializeFileTypeIcons } from '@fluentui/react-file-type-icons';
3+
import React from 'react';
4+
5+
initializeFileTypeIcons();
6+
7+
export const MessageWithAttachmentFromTeams: () => JSX.Element = () => {
8+
return (
9+
<FluentThemeProvider>
10+
<MessageThread
11+
userId={'1'}
12+
showMessageDate={true}
13+
messages={[
14+
{
15+
messageType: 'chat',
16+
senderId: '8:orgid:f949b075-4ab2-43de-8803-e01371df20a3',
17+
senderDisplayName: 'Kat Larsson',
18+
messageId: `f0a6096c-da7b-42d0-9d67-05297c926bf9`,
19+
content: 'Checkout these files from my OneDrive, let me know what do you think',
20+
createdOn: new Date('2019-04-13T00:00:00.000+08:10'),
21+
mine: false,
22+
attached: false,
23+
status: 'seen' as MessageStatus,
24+
contentType: 'text',
25+
attachments: [
26+
{
27+
id: 'a021eacd612d',
28+
name: 'Report.ppt',
29+
url: 'https://www.onedrive.com'
30+
},
31+
{
32+
id: 'zc1eacd612d',
33+
name: 'Budget.xlsx',
34+
url: 'https://www.bing.com'
35+
}
36+
]
37+
},
38+
{
39+
messageType: 'chat',
40+
senderId: 'user2',
41+
senderDisplayName: 'Robert Tolbert',
42+
messageId: `2a57431b-0b86-4e37-92e9-37fc03553a9d`,
43+
content: 'will do, thanks!',
44+
createdOn: new Date('2019-04-13T00:00:00.000+08:09'),
45+
mine: true,
46+
attached: false,
47+
contentType: 'text'
48+
}
49+
]}
50+
/>
51+
</FluentThemeProvider>
52+
);
53+
};

packages/storybook/stories/MessageThread/snippets/MessageWithCustomAttachment.snippet.tsx

+68-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
import {
22
AttachmentMenuAction,
33
AttachmentMetadata,
4+
ChatMessage,
45
FluentThemeProvider,
56
MessageStatus,
67
MessageThread,
78
defaultAttachmentMenuAction
89
} from '@azure/communication-react';
910
import { initializeFileTypeIcons } from '@fluentui/react-file-type-icons';
10-
import { ShareIos24Regular, WindowNew24Regular } from '@fluentui/react-icons';
11+
import {
12+
Bookmark24Filled,
13+
Heart24Filled,
14+
Pin24Filled,
15+
ShareIos24Regular,
16+
WindowNew24Regular
17+
} from '@fluentui/react-icons';
1118
import React from 'react';
1219

1320
initializeFileTypeIcons();
@@ -20,7 +27,10 @@ export const MessageWithCustomAttachment: () => JSX.Element = () => {
2027
showMessageDate={true}
2128
attachmentOptions={{
2229
downloadOptions: {
23-
actionsForAttachment: (attachment: AttachmentMetadata): AttachmentMenuAction[] => {
30+
actionsForAttachment: (
31+
attachment: AttachmentMetadata,
32+
message: ChatMessage | undefined
33+
): AttachmentMenuAction[] => {
2434
// allows the menu actions to be dynamically generated based on the attachment content
2535
// (i.e. name, extension, etc.), or the message content (i.e. senderID, etc.)
2636
// in this example, we are constructing a dynamic menu based on the attachment extension
@@ -39,7 +49,41 @@ export const MessageWithCustomAttachment: () => JSX.Element = () => {
3949
}
4050
}
4151
];
52+
} else if (message?.senderId === 'user4') {
53+
// alternatively, you can return a dynamic menu based on the message metadata such as user ID
54+
return [
55+
// you can reuse default action if you would like to
56+
defaultAttachmentMenuAction,
57+
// you can also overwrite the default action and reuse only a part of it
58+
{
59+
name: 'Bookmark',
60+
icon: <Bookmark24Filled />,
61+
onClick: defaultAttachmentMenuAction.onClick
62+
},
63+
// or you can create a new action from scratch
64+
{
65+
name: 'Favorite',
66+
icon: <Heart24Filled />,
67+
onClick: () => {
68+
return new Promise((resolve) => {
69+
window.alert('Favorite button clicked');
70+
resolve();
71+
});
72+
}
73+
},
74+
{
75+
name: 'Pin',
76+
icon: <Pin24Filled />,
77+
onClick: () => {
78+
return new Promise((resolve) => {
79+
window.alert('pin button clicked');
80+
resolve();
81+
});
82+
}
83+
}
84+
];
4285
} else {
86+
// or return a static list of menu actions for all other cases
4387
return [
4488
{
4589
...defaultAttachmentMenuAction,
@@ -70,7 +114,7 @@ export const MessageWithCustomAttachment: () => JSX.Element = () => {
70114
messageType: 'chat',
71115
senderId: 'user1',
72116
senderDisplayName: 'Kat Larsson',
73-
messageId: Math.random().toString(),
117+
messageId: '6c5c239c-905f-439e-b040-fcfdb1344df1',
74118
content: 'This is the report:',
75119
createdOn: new Date('2019-04-13T00:00:00.000+08:10'),
76120
mine: false,
@@ -81,15 +125,15 @@ export const MessageWithCustomAttachment: () => JSX.Element = () => {
81125
{
82126
id: '750e4dbd2900',
83127
name: 'Report.docx',
84-
url: 'https://<file_url>/report.docx'
128+
url: 'https://www.bing.com'
85129
}
86130
]
87131
},
88132
{
89133
messageType: 'chat',
90134
senderId: 'user3',
91135
senderDisplayName: 'Robert Tolbert',
92-
messageId: Math.random().toString(),
136+
messageId: '463a7aa5-0ad7-45fb-9780-dcbf00f39c0e',
93137
content: 'Also take a look at this user manual as well.',
94138
createdOn: new Date('2019-04-13T00:00:00.000+08:00'),
95139
mine: false,
@@ -99,7 +143,25 @@ export const MessageWithCustomAttachment: () => JSX.Element = () => {
99143
{
100144
id: '607b3100f37a',
101145
name: 'Manual.pdf',
102-
url: 'https://<file_url>/manual.pdf'
146+
url: 'https://www.bing.com'
147+
}
148+
]
149+
},
150+
{
151+
messageType: 'chat',
152+
senderId: 'user4',
153+
senderDisplayName: 'John Doe',
154+
messageId: 'c6919002-f9e7-459f-89bc-3a99cb284e48',
155+
content: 'Great, I just need you two to sign off on this document.',
156+
createdOn: new Date('2019-04-13T00:00:00.000+08:00'),
157+
mine: true,
158+
attached: false,
159+
contentType: 'text',
160+
attachments: [
161+
{
162+
id: 'bv7b3100f37a',
163+
name: 'RSVP.xlsx',
164+
url: 'https://www.bing.com'
103165
}
104166
]
105167
}

packages/storybook/stories/SendBox/RichTextSendBox.stories.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ const RichTextSendBoxStory = (args): JSX.Element => {
7474
args.hasAttachments
7575
? [
7676
{
77-
id: '1',
77+
id: 'f2d1fce73c98',
7878
name: 'file1.txt',
7979
url: 'https://www.contoso.com/file1.txt',
8080
progress: 1
8181
},
8282
{
83-
id: '2',
83+
id: 'dc3a33ebd321',
8484
name: 'file2.docx',
8585
url: 'https://www.contoso.com/file2.txt',
8686
progress: 1

packages/storybook/stories/SendBox/SendBox.stories.tsx

+16-2
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,24 @@ const SendBoxStory = (args): JSX.Element => {
111111
<div style={{ width: '31.25rem' }}>
112112
<SendBoxComponent
113113
disabled={args.disabled}
114-
onSendMessage={async (message) => {
114+
onSendMessage={async (message, options) => {
115115
timeoutRef.current = setTimeout(() => {
116-
alert(`sent message: ${message} `);
116+
alert(`sent message: "${message}" with options ${JSON.stringify(options)}`);
117117
}, delayForSendButton);
118118
}}
119119
onTyping={(): Promise<void> => {
120120
console.log(`sending typing notifications`);
121121
return Promise.resolve();
122122
}}
123123
systemMessage={args.hasWarning ? args.warningMessage : undefined}
124+
attachments={
125+
args.hasAttachments
126+
? [{ id: 'f2d1fce73c98', name: 'file1.txt', progress: 1, url: 'https://www.bing.com' }]
127+
: undefined
128+
}
129+
onCancelAttachmentUpload={(attachmentId) => {
130+
window.alert(`onCancelAttachmentUpload callback is called for attachment id: "${attachmentId}"`);
131+
}}
124132
/>
125133
</div>
126134
);
@@ -135,9 +143,15 @@ export default {
135143
title: `${COMPONENT_FOLDER_PREFIX}/Send Box/Send Box`,
136144
component: SendBoxComponent,
137145
argTypes: {
146+
// hide unnecessary props from storybook controls
147+
// since we now have `hasAttachments` for attachments
148+
attachments: hiddenControl,
149+
onCancelAttachmentUpload: hiddenControl,
150+
onRenderAttachmentUploads: hiddenControl,
138151
disabled: controlsToAdd.disabled,
139152
hasWarning: controlsToAdd.isSendBoxWithWarning,
140153
warningMessage: controlsToAdd.sendBoxWarningMessage,
154+
hasAttachments: controlsToAdd.isSendBoxWithAttachments,
141155
// Hiding auto-generated controls
142156
systemMessage: hiddenControl,
143157
onSendMessage: hiddenControl,

packages/storybook/stories/SendBox/snippets/AttachmentUploads.snippet.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ export const AttachmentUploadsExample: () => JSX.Element = () => (
77
<SendBox
88
attachments={[
99
{
10-
id: '1',
10+
id: '7e61ebe5ae4a',
1111
name: 'Sample.pdf',
1212
progress: 0.75
1313
},
1414
{
15-
id: '2',
15+
id: 'a81018dc2064',
1616
name: 'SampleXl.xlsx',
1717
progress: 0.33
1818
}

0 commit comments

Comments
 (0)