Skip to content

Commit 3526fdf

Browse files
Chat: implement Message Editing demo (#29780)
1 parent df6f89d commit 3526fdf

File tree

10 files changed

+238
-2
lines changed

10 files changed

+238
-2
lines changed
-32.9 KB
Binary file not shown.
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: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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 messages = [
20+
{
21+
id: new DevExpress.data.Guid(),
22+
timestamp: getTimestamp(date, -9),
23+
author: supportAgent,
24+
text: 'Hello, John!\nHow can I assist you today?',
25+
},
26+
{
27+
id: new DevExpress.data.Guid(),
28+
timestamp: getTimestamp(date, -7),
29+
author: currentUser,
30+
text: "Hi, I'm having trouble accessing my account.",
31+
},
32+
{
33+
id: new DevExpress.data.Guid(),
34+
timestamp: getTimestamp(date, -7),
35+
author: currentUser,
36+
text: 'It says my password is incorrect.',
37+
},
38+
{
39+
id: new DevExpress.data.Guid(),
40+
timestamp: getTimestamp(date, -7),
41+
author: currentUser,
42+
isDeleted: true,
43+
},
44+
{
45+
id: new DevExpress.data.Guid(),
46+
timestamp: getTimestamp(date, -7),
47+
author: supportAgent,
48+
text: 'I can help you with that. Can you please confirm your UserID for security purposes?',
49+
isEdited: true,
50+
},
51+
];
52+
53+
const editingStrategy = {
54+
enabled: true,
55+
disabled: false,
56+
custom: ({ component, message }) => {
57+
const { items, user } = component.option();
58+
59+
const lastMessage = [...items]
60+
.reverse()
61+
.find((m) => m.author?.id === user.id);
62+
63+
return !lastMessage.isDeleted && lastMessage?.id === message.id;
64+
},
65+
};
66+
67+
const editingOptions = [
68+
{ text: 'Enabled', key: 'enabled' },
69+
{ text: 'Disabled', key: 'disabled' },
70+
{ text: 'Only the last message (custom)', key: 'custom' },
71+
];
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
21+
<div class="options">
22+
<div class="caption">Options</div>
23+
24+
<div class="option">
25+
<span>Allow Editing:</span>
26+
<div id="allow-editing"></div>
27+
</div>
28+
29+
<div class="option">
30+
<span>Allow Deleting:</span>
31+
<div id="allow-deleting"></div>
32+
</div>
33+
</div>
34+
</div>
35+
</body>
36+
</html>
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
$(() => {
2+
const customStore = new DevExpress.data.CustomStore({
3+
key: 'id',
4+
load: () => {
5+
const d = $.Deferred();
6+
7+
setTimeout(() => {
8+
d.resolve([...messages]);
9+
});
10+
11+
return d.promise();
12+
},
13+
insert: (message) => {
14+
const d = $.Deferred();
15+
16+
setTimeout(() => {
17+
store.push(message);
18+
d.resolve();
19+
});
20+
21+
return d.promise();
22+
},
23+
});
24+
25+
const dataSource = new DevExpress.data.DataSource({
26+
store: customStore,
27+
paginate: false,
28+
});
29+
30+
const chat = $('#chat').dxChat({
31+
height: 710,
32+
dataSource,
33+
editing: {
34+
allowUpdating: true,
35+
allowDeleting: true,
36+
},
37+
reloadOnChange: false,
38+
user: currentUser,
39+
onMessageEntered(e) {
40+
const { message } = e;
41+
42+
dataSource.store().push([{
43+
type: 'insert',
44+
data: {
45+
id: new DevExpress.data.Guid(),
46+
...message,
47+
},
48+
}]);
49+
},
50+
onMessageDeleted(e) {
51+
const { message } = e;
52+
53+
dataSource.store().push([{
54+
type: 'update',
55+
key: message.id,
56+
data: { isDeleted: true },
57+
}]);
58+
},
59+
onMessageUpdated(e) {
60+
const { message, text } = e;
61+
62+
dataSource.store().push([{
63+
type: 'update',
64+
key: message.id,
65+
data: { text, isEdited: true },
66+
}]);
67+
},
68+
}).dxChat('instance');
69+
70+
$('#allow-editing').dxSelectBox({
71+
items: editingOptions,
72+
value: editingOptions[0].key,
73+
valueExpr: 'key',
74+
displayExpr: 'text',
75+
inputAttr: { 'aria-label': 'Allow Editing' },
76+
onValueChanged(data) {
77+
chat.option('editing.allowUpdating', editingStrategy[data.value]);
78+
},
79+
});
80+
81+
$('#allow-deleting').dxSelectBox({
82+
items: editingOptions,
83+
value: editingOptions[0].key,
84+
valueExpr: 'key',
85+
displayExpr: 'text',
86+
inputAttr: { 'aria-label': 'Allow Deleting' },
87+
onValueChanged(data) {
88+
chat.option('editing.allowDeleting', editingStrategy[data.value]);
89+
},
90+
});
91+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
.demo-container {
2+
min-width: 720px;
3+
display: flex;
4+
gap: 20px;
5+
}
6+
7+
.chat-container {
8+
display: flex;
9+
flex-grow: 1;
10+
align-items: center;
11+
justify-content: center;
12+
}
13+
14+
.options {
15+
padding: 20px;
16+
display: flex;
17+
flex-direction: column;
18+
min-width: 280px;
19+
background-color: rgba(191, 191, 191, 0.15);
20+
gap: 16px;
21+
}
22+
23+
.dx-chat {
24+
max-width: 480px;
25+
}
26+
27+
.caption {
28+
font-size: var(--dx-font-size-sm);
29+
font-weight: 500;
30+
}
31+
32+
.dx-avatar {
33+
border: 1px solid var(--dx-color-border);
34+
}

apps/demos/menuMeta.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,8 +2124,11 @@
21242124
"Name": "MessageEditing",
21252125
"Widget": "Chat",
21262126
"DemoType": "Web",
2127-
"Badge": "Roadmap",
2128-
"RoadmapSurveyUrl": "https://www.devexpress.com/support/surveys/devextreme-roadmap-messages.xml"
2127+
"Badge": "New",
2128+
"DocUrl": "",
2129+
"MvcDescription": "",
2130+
"NetCoreDescription": "",
2131+
"MvcAdditionalFiles": []
21292132
}
21302133
]
21312134
},
62.7 KB
Loading
61.6 KB
Loading
59.9 KB
Loading

0 commit comments

Comments
 (0)