Skip to content

Commit fb9cdb2

Browse files
r-farkhutdinovRuslan Farkhutdinov
andauthored
Chat: Add File Attachments demo (#31593)
Co-authored-by: Ruslan Farkhutdinov <[email protected]>
1 parent 45fb81f commit fb9cdb2

File tree

7 files changed

+189
-0
lines changed

7 files changed

+189
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
MockDate.set(new Date('2025/05/05 16:35:10'));
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const getTimestamp = function (date, offsetMinutes = 0) {
2+
return date.getTime() + offsetMinutes * 60000;
3+
};
4+
5+
const date = new Date();
6+
date.setHours(0, 0, 0, 0);
7+
8+
const currentUser = {
9+
id: 'c94c0e76-fb49-4b9b-8f07-9f93ed93b4f3',
10+
name: 'John Doe',
11+
};
12+
13+
const supportAgent = {
14+
id: 'd16d1a4c-5c67-4e20-b70e-2991c22747c3',
15+
name: 'Support Agent',
16+
avatarUrl: '../../../../images/petersmith.png',
17+
};
18+
19+
const createEmptyAttachment = (name, type) => {
20+
const blob = new Blob([''], { type });
21+
const url = URL.createObjectURL(blob);
22+
23+
return {
24+
name,
25+
url,
26+
size: 1024 * 10,
27+
};
28+
};
29+
30+
const screenshot1 = createEmptyAttachment('Screenshot1.jpg', 'image/jpeg');
31+
const screenshot2 = createEmptyAttachment('Screenshot2.jpg', 'image/jpeg');
32+
const screenshot3 = createEmptyAttachment('Screenshot3.jpg', 'image/jpeg');
33+
const instructions = createEmptyAttachment('Instructions.pdf', 'application/pdf');
34+
35+
const messages = [
36+
{
37+
id: new DevExpress.data.Guid(),
38+
timestamp: getTimestamp(date, -9),
39+
author: supportAgent,
40+
text: 'Hello, John!\nHow can I assist you today?',
41+
},
42+
{
43+
id: new DevExpress.data.Guid(),
44+
timestamp: getTimestamp(date, -7),
45+
author: currentUser,
46+
text: "Hi, I'm having trouble accessing my account.\nIt says my password is incorrect. I’ve attached some screenshots for you to check.",
47+
attachments: [screenshot1, screenshot2, screenshot3],
48+
},
49+
{
50+
id: new DevExpress.data.Guid(),
51+
timestamp: getTimestamp(date, -7),
52+
author: supportAgent,
53+
text: 'Thanks for the screenshots! I can help you with that. Please refer to the attached file for instructions to restore access.',
54+
attachments: [instructions],
55+
},
56+
];
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE html>
2+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
3+
<head>
4+
<title>DevExtreme Demo</title>
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
8+
<script src="../../../../node_modules/jquery/dist/jquery.min.js"></script>
9+
<link rel="stylesheet" type="text/css" href="../../../../node_modules/devextreme-dist/css/dx.light.css" />
10+
<script src="../../../../node_modules/devextreme-dist/js/dx.all.js"></script>
11+
<link rel="stylesheet" type="text/css" href="styles.css" />
12+
<script src="data.js"></script>
13+
<script src="index.js"></script>
14+
</head>
15+
<body class="dx-viewport">
16+
<div class="demo-container">
17+
<div class="chat-container">
18+
<div id="chat"></div>
19+
</div>
20+
</div>
21+
</body>
22+
</html>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
$(() => {
2+
const customStore = new DevExpress.data.CustomStore({
3+
key: 'id',
4+
load: async () => messages,
5+
insert: async (message) => {
6+
messages.push(message);
7+
return message;
8+
},
9+
});
10+
11+
const dataSource = new DevExpress.data.DataSource({
12+
store: customStore,
13+
paginate: false,
14+
});
15+
16+
const uploadedFilesMap = new Map();
17+
18+
$('#chat').dxChat({
19+
height: 600,
20+
dataSource,
21+
reloadOnChange: false,
22+
user: currentUser,
23+
fileUploaderOptions: {
24+
uploadFile: () => {},
25+
onValueChanged(e) {
26+
e.value.forEach((file) => {
27+
const url = URL.createObjectURL(file);
28+
uploadedFilesMap.set(file.name, url);
29+
});
30+
},
31+
},
32+
onMessageEntered(e) {
33+
const { message } = e;
34+
35+
const attachmentsWithUrls = message.attachments?.map((attachment) => {
36+
const url = uploadedFilesMap.get(attachment.name);
37+
return { ...attachment, url };
38+
});
39+
40+
dataSource.store().push([{
41+
type: 'insert',
42+
data: {
43+
id: new DevExpress.data.Guid(),
44+
...message,
45+
attachments: attachmentsWithUrls,
46+
},
47+
}]);
48+
},
49+
onAttachmentDownloadClick(e) {
50+
const { attachment } = e;
51+
52+
if (!attachment?.url) {
53+
return;
54+
}
55+
56+
const link = document.createElement('a');
57+
link.href = attachment.url;
58+
link.download = attachment.name;
59+
document.body.appendChild(link);
60+
61+
link.click();
62+
63+
document.body.removeChild(link);
64+
},
65+
}).dxChat('instance');
66+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
.demo-container {
2+
min-width: 720px;
3+
}
4+
5+
.chat-container {
6+
display: flex;
7+
flex-grow: 1;
8+
align-items: center;
9+
justify-content: center;
10+
}
11+
12+
.dx-chat {
13+
max-width: 480px;
14+
}
15+
16+
.caption {
17+
font-size: var(--dx-font-size-sm);
18+
font-weight: 500;
19+
}
20+
21+
.dx-avatar {
22+
border: 1px solid var(--dx-color-border);
23+
}

apps/demos/menuMeta.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4111,6 +4111,27 @@
41114111
}
41124112
]
41134113
},
4114+
{
4115+
"Name": "File Attachments",
4116+
"Equivalents": "Files Sending, Messages with files, Files Attached, Message Attachments, Document Attachments",
4117+
"Demos": [
4118+
{
4119+
"Title": "File Attachments",
4120+
"Name": "FileAttachments",
4121+
"Widget": "Chat",
4122+
"DemoType": "Web",
4123+
"DocUrl": "",
4124+
"MvcDescription": "",
4125+
"NetCoreDescription": "",
4126+
"MvcAdditionalFiles": [
4127+
"/Models/SampleData/ChatData.cs",
4128+
"/Models/Chat/User.cs",
4129+
"/Models/Chat/Message.cs",
4130+
"/ViewModels/ChatViewModel.cs"
4131+
]
4132+
}
4133+
]
4134+
},
41144135
{
41154136
"Name": "Customization",
41164137
"Equivalents": "Settings, Options",
59.5 KB
Loading

0 commit comments

Comments
 (0)