@droppii-org/chat-sdk 0.6.51 → 0.6.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/group/AdminPermissionModal.d.ts.map +1 -1
- package/dist/components/group/AdminPermissionModal.js +9 -38
- package/dist/components/group/MemberPermissionPanel.d.ts.map +1 -1
- package/dist/components/group/MemberPermissionPanel.js +45 -33
- package/dist/components/search-conversation/SearchAll.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchAll.js +7 -9
- package/dist/components/search-conversation/SearchConversationAsGroups.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchConversationAsGroups.js +3 -0
- package/dist/components/search-conversation/SearchConversationAsMessages.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchConversationAsMessages.js +4 -1
- package/dist/components/search-conversation/SearchConversationAsUsers.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchConversationAsUsers.js +4 -6
- package/dist/components/search-conversation/SearchScopeContext.d.ts +4 -0
- package/dist/components/search-conversation/SearchScopeContext.d.ts.map +1 -0
- package/dist/components/search-conversation/SearchScopeContext.js +5 -0
- package/dist/components/search-conversation/index.d.ts +5 -2
- package/dist/components/search-conversation/index.d.ts.map +1 -1
- package/dist/components/search-conversation/index.js +17 -12
- package/dist/components/search-conversation/item/SearchItemAsGroup.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsGroup.js +9 -0
- package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts +2 -0
- package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsMessage.js +28 -6
- package/dist/components/search-conversation/item/SearchItemAsUser.d.ts +2 -1
- package/dist/components/search-conversation/item/SearchItemAsUser.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsUser.js +9 -2
- package/dist/hooks/group/useGroupMemberActions.d.ts +7 -0
- package/dist/hooks/group/useGroupMemberActions.d.ts.map +1 -1
- package/dist/hooks/group/useGroupMemberActions.js +23 -0
- package/dist/hooks/message/useTypingStatus.d.ts.map +1 -1
- package/dist/hooks/message/useTypingStatus.js +1 -9
- package/dist/hooks/search/useOpenPdpSearchResult.d.ts +8 -0
- package/dist/hooks/search/useOpenPdpSearchResult.d.ts.map +1 -0
- package/dist/hooks/search/useOpenPdpSearchResult.js +31 -0
- package/dist/hooks/search/useSearchGroups.d.ts +3 -1
- package/dist/hooks/search/useSearchGroups.d.ts.map +1 -1
- package/dist/hooks/search/useSearchGroups.js +22 -11
- package/dist/hooks/search/useSearchMessage.d.ts +2 -0
- package/dist/hooks/search/useSearchMessage.d.ts.map +1 -1
- package/dist/hooks/search/useSearchMessage.js +10 -4
- package/dist/hooks/search/useSearchPdpTeamSessions.d.ts +17 -0
- package/dist/hooks/search/useSearchPdpTeamSessions.d.ts.map +1 -0
- package/dist/hooks/search/useSearchPdpTeamSessions.js +38 -0
- package/dist/hooks/search/useSearchUsers.d.ts +14 -0
- package/dist/hooks/search/useSearchUsers.d.ts.map +1 -0
- package/dist/hooks/search/useSearchUsers.js +23 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/locales/vi/common.json +2 -0
- package/dist/services/query.d.ts +1 -0
- package/dist/services/query.d.ts.map +1 -1
- package/dist/services/query.js +1 -0
- package/dist/services/routes.d.ts +3 -0
- package/dist/services/routes.d.ts.map +1 -1
- package/dist/services/routes.js +3 -0
- package/dist/types/search.d.ts +2 -0
- package/dist/types/search.d.ts.map +1 -0
- package/dist/types/search.js +1 -0
- package/dist/utils/conversation.d.ts +2 -1
- package/dist/utils/conversation.d.ts.map +1 -1
- package/dist/utils/conversation.js +8 -1
- package/dist/utils/groupPermissionSwitches.d.ts +9 -0
- package/dist/utils/groupPermissionSwitches.d.ts.map +1 -0
- package/dist/utils/groupPermissionSwitches.js +19 -0
- package/package.json +2 -2
- package/dist/store/groupPermissionOverrides.d.ts +0 -23
- package/dist/store/groupPermissionOverrides.d.ts.map +0 -1
- package/dist/store/groupPermissionOverrides.js +0 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminPermissionModal.d.ts","sourceRoot":"","sources":["../../../src/components/group/AdminPermissionModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AdminPermissionModal.d.ts","sourceRoot":"","sources":["../../../src/components/group/AdminPermissionModal.tsx"],"names":[],"mappings":"AAqBA,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,UAAU,yBAAyB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IAIpB,MAAM,CAAC,EAAE,OAAO,CAAC;IAGjB,MAAM,CAAC,EAAE,0BAA0B,CAAC;IAKpC,wBAAwB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC5E;AAwCD,QAAA,MAAM,oBAAoB,GAAI,uEAO3B,yBAAyB,mDAgK3B,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -5,10 +5,11 @@ import { ConfigProvider, Modal, Switch, message } from "antd";
|
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
6
|
import { GroupMemberRole } from "@droppii-org/wasm-client-sdk";
|
|
7
7
|
import { useGroupMembers } from "../../hooks/group/useGroupMembers";
|
|
8
|
-
import { useSetGroupMemberPermissions } from "../../hooks/group/useGroupMemberActions";
|
|
8
|
+
import { useSetAdminRolePermissions, useSetGroupMemberPermissions, } from "../../hooks/group/useGroupMemberActions";
|
|
9
9
|
import { Icon } from "../../components/icon";
|
|
10
10
|
import { ANTD_PRIMARY_COLOR_VAR } from "../../constants";
|
|
11
11
|
import { GROUP_PERMISSION_KEY } from "../../constants/im";
|
|
12
|
+
import { changedSwitches, commonSwitchStates, toRolePermissionChange, } from "../../utils/groupPermissionSwitches";
|
|
12
13
|
// "Cập nhật thông tin nhóm" is one switch in the UI but bundles 3 BE
|
|
13
14
|
// permission keys (name/avatar/description), so it maps to all three.
|
|
14
15
|
const UPDATE_GROUP_INFO_KEYS = [
|
|
@@ -24,35 +25,21 @@ const SWITCH_PERMISSION_KEYS = {
|
|
|
24
25
|
removeMember: [GROUP_PERMISSION_KEY.removeMember],
|
|
25
26
|
updateGroupInfo: UPDATE_GROUP_INFO_KEYS,
|
|
26
27
|
};
|
|
27
|
-
const SWITCHES = Object.keys(SWITCH_PERMISSION_KEYS);
|
|
28
|
-
// A switch reads on only when every given permission list grants all of its keys.
|
|
29
|
-
const commonOverrides = (permissionLists) => {
|
|
30
|
-
const grants = (name) => permissionLists.length > 0 &&
|
|
31
|
-
permissionLists.every((list) => SWITCH_PERMISSION_KEYS[name].every((key) => list.includes(key)));
|
|
32
|
-
return {
|
|
33
|
-
sendMessage: grants("sendMessage"),
|
|
34
|
-
pinMessage: grants("pinMessage"),
|
|
35
|
-
viewMemberInformation: grants("viewMemberInformation"),
|
|
36
|
-
addMember: grants("addMember"),
|
|
37
|
-
removeMember: grants("removeMember"),
|
|
38
|
-
updateGroupInfo: grants("updateGroupInfo"),
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
28
|
// Rewrites only the switches that changed; every other key in the list stays as is.
|
|
42
29
|
const applySwitchChanges = (permissionList, changes) => Object.entries(changes).reduce((list, [name, enabled]) => {
|
|
43
30
|
const keys = SWITCH_PERMISSION_KEYS[name];
|
|
44
31
|
const without = list.filter((permission) => !keys.includes(permission));
|
|
45
32
|
return enabled ? [...without, ...keys] : without;
|
|
46
33
|
}, permissionList);
|
|
47
|
-
const isSamePermissionSet = (a, b) => a.length === b.length && a.every((permission) => b.includes(permission));
|
|
48
34
|
// "Configure Admin Permissions". With `member` (a member row's … menu) it edits
|
|
49
35
|
// that one Admin. Without it (the group info panel) it edits every current
|
|
50
|
-
// Admin
|
|
51
|
-
//
|
|
36
|
+
// Admin in one setGroupAdminPermissions call: switches start from what the
|
|
37
|
+
// Admins already share, and "Lưu" sends only the switches the user flipped.
|
|
52
38
|
const AdminPermissionModal = ({ open, groupID, onClose, inline = false, member, onMemberPermissionsSaved, }) => {
|
|
53
39
|
const { t } = useTranslation();
|
|
54
40
|
const { members: groupMembers } = useGroupMembers(member ? undefined : groupID);
|
|
55
41
|
const { mutateAsync: setMemberPermissions } = useSetGroupMemberPermissions();
|
|
42
|
+
const { mutateAsync: setAdminRolePermissions } = useSetAdminRolePermissions();
|
|
56
43
|
const [isSaving, setIsSaving] = useState(false);
|
|
57
44
|
const [edits, setEdits] = useState({});
|
|
58
45
|
useEffect(() => {
|
|
@@ -60,19 +47,14 @@ const AdminPermissionModal = ({ open, groupID, onClose, inline = false, member,
|
|
|
60
47
|
setEdits({});
|
|
61
48
|
}, [open, member === null || member === void 0 ? void 0 : member.userID]);
|
|
62
49
|
const admins = groupMembers.filter((groupMember) => groupMember.roleLevel === GroupMemberRole.Admin);
|
|
63
|
-
const baseline = member
|
|
64
|
-
? commonOverrides([member.permissions])
|
|
65
|
-
: commonOverrides(admins.map((admin) => { var _a; return (_a = admin.permissions) !== null && _a !== void 0 ? _a : []; }));
|
|
50
|
+
const baseline = commonSwitchStates(SWITCH_PERMISSION_KEYS, member ? [member.permissions] : admins.map((admin) => { var _a; return (_a = admin.permissions) !== null && _a !== void 0 ? _a : []; }));
|
|
66
51
|
const pending = Object.assign(Object.assign({}, baseline), edits);
|
|
67
|
-
const changes =
|
|
68
|
-
name,
|
|
69
|
-
pending[name],
|
|
70
|
-
]));
|
|
52
|
+
const changes = changedSwitches(baseline, pending);
|
|
71
53
|
const hasChanges = Object.keys(changes).length > 0;
|
|
72
54
|
const setSwitch = (name, checked) => setEdits((prev) => (Object.assign(Object.assign({}, prev), { [name]: checked })));
|
|
73
55
|
const handleSave = async () => {
|
|
74
56
|
var _a, _b;
|
|
75
|
-
if (!groupID)
|
|
57
|
+
if (!groupID || !hasChanges)
|
|
76
58
|
return;
|
|
77
59
|
setIsSaving(true);
|
|
78
60
|
try {
|
|
@@ -86,18 +68,7 @@ const AdminPermissionModal = ({ open, groupID, onClose, inline = false, member,
|
|
|
86
68
|
onMemberPermissionsSaved === null || onMemberPermissionsSaved === void 0 ? void 0 : onMemberPermissionsSaved(member.userID, nextPermissions);
|
|
87
69
|
}
|
|
88
70
|
else {
|
|
89
|
-
await
|
|
90
|
-
var _a;
|
|
91
|
-
const current = (_a = admin.permissions) !== null && _a !== void 0 ? _a : [];
|
|
92
|
-
const nextPermissions = applySwitchChanges(current, changes);
|
|
93
|
-
if (isSamePermissionSet(current, nextPermissions))
|
|
94
|
-
return undefined;
|
|
95
|
-
return setMemberPermissions({
|
|
96
|
-
groupID,
|
|
97
|
-
userID: admin.userID,
|
|
98
|
-
permissions: nextPermissions,
|
|
99
|
-
});
|
|
100
|
-
}));
|
|
71
|
+
await setAdminRolePermissions(Object.assign({ groupID }, toRolePermissionChange(SWITCH_PERMISSION_KEYS, changes)));
|
|
101
72
|
}
|
|
102
73
|
message.success(t("update_admin_permissions_success"));
|
|
103
74
|
onClose();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MemberPermissionPanel.d.ts","sourceRoot":"","sources":["../../../src/components/group/MemberPermissionPanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MemberPermissionPanel.d.ts","sourceRoot":"","sources":["../../../src/components/group/MemberPermissionPanel.tsx"],"names":[],"mappings":"AAkBA,UAAU,0BAA0B;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAuBD,QAAA,MAAM,qBAAqB,GAAI,4BAA4B,0BAA0B,mDA2FpF,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -3,51 +3,63 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
4
|
import { ConfigProvider, Switch, message } from "antd";
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
|
-
import {
|
|
6
|
+
import { GroupMemberRole } from "@droppii-org/wasm-client-sdk";
|
|
7
|
+
import { useGroupMembers } from "../../hooks/group/useGroupMembers";
|
|
8
|
+
import { useSetMemberRolePermissions } from "../../hooks/group/useGroupMemberActions";
|
|
7
9
|
import { Icon } from "../../components/icon";
|
|
8
10
|
import { ANTD_PRIMARY_COLOR_VAR } from "../../constants";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
import { GROUP_PERMISSION_KEY } from "../../constants/im";
|
|
12
|
+
import { changedSwitches, commonSwitchStates, toRolePermissionChange, } from "../../utils/groupPermissionSwitches";
|
|
13
|
+
const SWITCH_PERMISSION_KEYS = {
|
|
14
|
+
sendMessage: [GROUP_PERMISSION_KEY.sendMessage],
|
|
15
|
+
addMember: [GROUP_PERMISSION_KEY.addMember],
|
|
16
|
+
pinMessage: [GROUP_PERMISSION_KEY.pinMessage],
|
|
17
|
+
viewMemberInformation: [GROUP_PERMISSION_KEY.viewMemberInformation],
|
|
18
|
+
};
|
|
19
|
+
const SWITCH_LABELS = {
|
|
20
|
+
sendMessage: "permission_send_message",
|
|
21
|
+
addMember: "permission_add_member",
|
|
22
|
+
pinMessage: "permission_pin_message",
|
|
23
|
+
viewMemberInformation: "permission_view_member_info",
|
|
24
|
+
};
|
|
25
|
+
const SWITCHES = Object.keys(SWITCH_PERMISSION_KEYS);
|
|
26
|
+
// "Configure Member Permissions", inline in the "Thông tin" sidebar. Switches
|
|
27
|
+
// start from what every ordinary member already shares, and "Lưu" sends only
|
|
28
|
+
// the switches the user flipped, in one setGroupMemberPermissions call.
|
|
14
29
|
const MemberPermissionPanel = ({ open, groupID, onClose }) => {
|
|
15
30
|
const { t } = useTranslation();
|
|
16
|
-
const
|
|
17
|
-
const
|
|
31
|
+
const { members: groupMembers, isLoading } = useGroupMembers(open ? groupID : undefined);
|
|
32
|
+
const { mutateAsync: setMemberRolePermissions } = useSetMemberRolePermissions();
|
|
18
33
|
const [isSaving, setIsSaving] = useState(false);
|
|
19
|
-
const [
|
|
20
|
-
sendMessage: permissions.sendMessage,
|
|
21
|
-
addMember: permissions.addMember,
|
|
22
|
-
pinMessage: permissions.pinMessage,
|
|
23
|
-
viewMemberInformation: permissions.viewMemberInformation,
|
|
24
|
-
});
|
|
34
|
+
const [edits, setEdits] = useState({});
|
|
25
35
|
useEffect(() => {
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
setPending({
|
|
29
|
-
sendMessage: permissions.sendMessage,
|
|
30
|
-
addMember: permissions.addMember,
|
|
31
|
-
pinMessage: permissions.pinMessage,
|
|
32
|
-
viewMemberInformation: permissions.viewMemberInformation,
|
|
33
|
-
});
|
|
34
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
36
|
+
if (open)
|
|
37
|
+
setEdits({});
|
|
35
38
|
}, [open]);
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
const members = groupMembers.filter((groupMember) => groupMember.roleLevel === GroupMemberRole.Normal);
|
|
40
|
+
const baseline = commonSwitchStates(SWITCH_PERMISSION_KEYS, members.map((member) => { var _a; return (_a = member.permissions) !== null && _a !== void 0 ? _a : []; }));
|
|
41
|
+
const pending = Object.assign(Object.assign({}, baseline), edits);
|
|
42
|
+
const changes = changedSwitches(baseline, pending);
|
|
43
|
+
const hasChanges = Object.keys(changes).length > 0;
|
|
40
44
|
const handleSave = async () => {
|
|
41
|
-
if (!groupID)
|
|
45
|
+
if (!groupID || !hasChanges)
|
|
42
46
|
return;
|
|
43
47
|
setIsSaving(true);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
try {
|
|
49
|
+
await setMemberRolePermissions(Object.assign({ groupID }, toRolePermissionChange(SWITCH_PERMISSION_KEYS, changes)));
|
|
50
|
+
message.success(t("update_member_permissions_success"));
|
|
51
|
+
onClose();
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error("setGroupMemberPermissions", error);
|
|
55
|
+
message.error(t("update_member_permissions_failed"));
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
setIsSaving(false);
|
|
59
|
+
}
|
|
48
60
|
};
|
|
49
61
|
if (!open)
|
|
50
62
|
return null;
|
|
51
|
-
return (_jsxs("div", { className: "absolute inset-0 bg-white flex flex-col z-10", "data-cp-name": "MemberPermissionPanel", children: [_jsxs("div", { className: "flex w-full items-center border-b border-gray-100 p-2", children: [_jsx("button", { type: "button", className: "flex shrink-0 cursor-pointer items-center justify-center p-2 text-[var(--dc-color-nav-icon)]", onClick: onClose, children: _jsx(Icon, { icon: "arrow-left-o", size: 24 }) }), _jsx("p", { className: "min-w-0 flex-1 truncate px-2 text-[18px] font-bold leading-[1.6] text-gray-900", children: t("member_permission_settings") })] }), _jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx(ConfigProvider, { theme: { token: { colorPrimary: ANTD_PRIMARY_COLOR_VAR } }, children:
|
|
63
|
+
return (_jsxs("div", { className: "absolute inset-0 bg-white flex flex-col z-10", "data-cp-name": "MemberPermissionPanel", children: [_jsxs("div", { className: "flex w-full items-center border-b border-gray-100 p-2", children: [_jsx("button", { type: "button", className: "flex shrink-0 cursor-pointer items-center justify-center p-2 text-[var(--dc-color-nav-icon)]", onClick: onClose, children: _jsx(Icon, { icon: "arrow-left-o", size: 24 }) }), _jsx("p", { className: "min-w-0 flex-1 truncate px-2 text-[18px] font-bold leading-[1.6] text-gray-900", children: t("member_permission_settings") })] }), _jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx(ConfigProvider, { theme: { token: { colorPrimary: ANTD_PRIMARY_COLOR_VAR } }, children: _jsx("div", { className: "flex flex-col py-2", children: SWITCHES.map((name) => (_jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [_jsx("span", { className: "text-sm", children: t(SWITCH_LABELS[name]) }), _jsx(Switch, { checked: pending[name], disabled: isLoading, onChange: (checked) => setEdits((prev) => (Object.assign(Object.assign({}, prev), { [name]: checked }))) })] }, name))) }) }) }), _jsxs("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-gray-100", children: [_jsx("button", { type: "button", className: "px-4 py-1.5 rounded-full border border-gray-300 text-gray-700 text-sm font-medium", onClick: onClose, children: t("cancel") }), _jsx("button", { type: "button", className: "px-4 py-1.5 rounded-full bg-[var(--dc-color-primary)] text-white text-sm font-medium disabled:bg-gray-200 disabled:text-gray-400", disabled: !hasChanges || isSaving || isLoading, onClick: handleSave, children: t("save") })] })] }));
|
|
52
64
|
};
|
|
53
65
|
export default MemberPermissionPanel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchAll.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchAll.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,wBAAwB,EAAE,MAAM,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchAll.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchAll.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,wBAAwB,EAAE,MAAM,GAAG,CAAC;AAI7C,UAAU,0BAA0B;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,GAAG,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACvD;AACD,QAAA,MAAM,qBAAqB,GAAI,+BAG5B,0BAA0B,4CAyJ5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -6,30 +6,28 @@ import { useSearchMessage } from "../../hooks/search/useSearchMessage";
|
|
|
6
6
|
import { MessageType } from "@droppii-org/wasm-client-sdk";
|
|
7
7
|
import { Icon } from "../../components/icon";
|
|
8
8
|
import SearchItemAsMessage from "./item/SearchItemAsMessage";
|
|
9
|
-
import { useGetSession } from "../../hooks/session/useGetSession";
|
|
10
9
|
import SearchItemAsUser from "./item/SearchItemAsUser";
|
|
11
10
|
import SearchItemAsGroup from "./item/SearchItemAsGroup";
|
|
12
11
|
import { useSearchGroups } from "../../hooks/search/useSearchGroups";
|
|
12
|
+
import { useSearchUsers } from "../../hooks/search/useSearchUsers";
|
|
13
13
|
import { SearchConversationTabKey } from ".";
|
|
14
|
+
import { useSearchScope } from "./SearchScopeContext";
|
|
14
15
|
import { PAGE_SIZE } from "../../constants";
|
|
15
16
|
const SearchConversationAll = ({ searchTerm = "", setActiveKey, }) => {
|
|
16
17
|
const { t } = useTranslation();
|
|
18
|
+
const scope = useSearchScope();
|
|
17
19
|
const { dataFlatten: messages, isLoading: isLoadingMessage, hasNextPage: hasNextPageMessage, } = useSearchMessage({
|
|
18
20
|
payload: {
|
|
19
21
|
searchTerm: searchTerm.trim(),
|
|
20
22
|
contentType: MessageType.TextMessage,
|
|
21
23
|
},
|
|
22
|
-
options: { pageSize: PAGE_SIZE.xs },
|
|
23
|
-
});
|
|
24
|
-
const { dataFlatten: sessions, isLoading: isLoadingSession, hasNextPage: hasNextPageSession, } = useGetSession({
|
|
25
|
-
filter: {
|
|
26
|
-
searchTerm: searchTerm.trim(),
|
|
27
|
-
},
|
|
28
|
-
options: { pageSize: PAGE_SIZE.xs },
|
|
24
|
+
options: { pageSize: PAGE_SIZE.xs, scope },
|
|
29
25
|
});
|
|
26
|
+
const { dataFlatten: sessions, isLoading: isLoadingSession, hasNextPage: hasNextPageSession, } = useSearchUsers({ searchTerm, scope, pageSize: PAGE_SIZE.xs });
|
|
30
27
|
const { groups, isLoading: isLoadingGroup, hasNextPage: hasNextPageGroup, } = useSearchGroups({
|
|
31
28
|
searchTerm: searchTerm.trim(),
|
|
32
29
|
pageSize: PAGE_SIZE.xs,
|
|
30
|
+
scope,
|
|
33
31
|
});
|
|
34
32
|
if (searchTerm.trim() === "" ||
|
|
35
33
|
(messages.length === 0 && sessions.length === 0 && groups.length === 0)) {
|
|
@@ -38,6 +36,6 @@ const SearchConversationAll = ({ searchTerm = "", setActiveKey, }) => {
|
|
|
38
36
|
if (isLoadingMessage || isLoadingSession || isLoadingGroup) {
|
|
39
37
|
return (_jsx("div", { className: "h-full overflow-auto flex items-center justify-center", children: _jsx(Spin, {}) }));
|
|
40
38
|
}
|
|
41
|
-
return (_jsxs("div", { className: "h-full overflow-auto", "data-cp-name": "SearchConversationAll", children: [sessions.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("users") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageSession && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Users), children: t("see_more") })] }), _jsx("div", { children: sessions.map((session) => (_jsx(SearchItemAsUser, { session: session, searchTerm: searchTerm }, session.conversationId))) })] })), messages.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("messages") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageMessage && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Messages), children: t("see_more") })] }), _jsx("div", { children: messages.map((message) => (_jsx(SearchItemAsMessage, { message: message.chatLog, searchTerm: searchTerm, displayTag: message.displayTag }, message.chatLog.clientMsgID))) })] })), groups.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("groups") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageGroup && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Groups), children: t("see_more") })] }), _jsx("div", { children: groups.map((group) => (_jsx(SearchItemAsGroup, { group: group, searchTerm: searchTerm }, group.conversationId))) })] }))] }));
|
|
39
|
+
return (_jsxs("div", { className: "h-full overflow-auto", "data-cp-name": "SearchConversationAll", children: [sessions.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("users") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageSession && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Users), children: t("see_more") })] }), _jsx("div", { children: sessions.map((session) => (_jsx(SearchItemAsUser, { session: session, searchTerm: searchTerm }, session.conversationId))) })] })), messages.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("messages") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageMessage && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Messages), children: t("see_more") })] }), _jsx("div", { children: messages.map((message) => (_jsx(SearchItemAsMessage, { message: message.chatLog, searchTerm: searchTerm, displayTag: message.displayTag, tag: message.tag }, message.chatLog.clientMsgID))) })] })), groups.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("groups") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageGroup && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Groups), children: t("see_more") })] }), _jsx("div", { children: groups.map((group) => (_jsx(SearchItemAsGroup, { group: group, searchTerm: searchTerm }, group.conversationId))) })] }))] }));
|
|
42
40
|
};
|
|
43
41
|
export default SearchConversationAll;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchConversationAsGroups.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsGroups.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SearchConversationAsGroups.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsGroups.tsx"],"names":[],"mappings":"AASA,UAAU,+BAA+B;IACvC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,0BAA0B,GAAI,OAAO,+BAA+B,4CA4CzE,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
|
|
@@ -5,11 +5,14 @@ import { useTranslation } from "react-i18next";
|
|
|
5
5
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
6
6
|
import SearchItemAsGroup from "./item/SearchItemAsGroup";
|
|
7
7
|
import { useSearchGroups } from "../../hooks/search/useSearchGroups";
|
|
8
|
+
import { useSearchScope } from "./SearchScopeContext";
|
|
8
9
|
const SearchConversationAsGroups = (props) => {
|
|
9
10
|
const { searchTerm = "" } = props;
|
|
10
11
|
const { t } = useTranslation();
|
|
12
|
+
const scope = useSearchScope();
|
|
11
13
|
const { groups, hasNextPage, fetchNextPage, isLoading } = useSearchGroups({
|
|
12
14
|
searchTerm,
|
|
15
|
+
scope,
|
|
13
16
|
});
|
|
14
17
|
if ((groups.length === 0 && !isLoading) || searchTerm.trim() === "")
|
|
15
18
|
return _jsx(Empty, { description: t("no_conversation") });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchConversationAsMessages.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsMessages.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SearchConversationAsMessages.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsMessages.tsx"],"names":[],"mappings":"AAQA,UAAU,iCAAiC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,4BAA4B,GAChC,OAAO,iCAAiC,4CAmDzC,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
|
|
@@ -5,19 +5,22 @@ import { useSearchMessage } from "../../hooks/search/useSearchMessage";
|
|
|
5
5
|
import { MessageType } from "@droppii-org/wasm-client-sdk";
|
|
6
6
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
7
7
|
import SearchItemAsMessage from "./item/SearchItemAsMessage";
|
|
8
|
+
import { useSearchScope } from "./SearchScopeContext";
|
|
8
9
|
const SearchConversationAsMessages = (props) => {
|
|
9
10
|
const { searchTerm = "" } = props;
|
|
10
11
|
const { t } = useTranslation();
|
|
12
|
+
const scope = useSearchScope();
|
|
11
13
|
const { dataFlatten, hasNextPage, fetchNextPage, isLoading } = useSearchMessage({
|
|
12
14
|
payload: {
|
|
13
15
|
searchTerm: searchTerm.trim(),
|
|
14
16
|
contentType: MessageType.TextMessage,
|
|
15
17
|
},
|
|
18
|
+
options: { scope },
|
|
16
19
|
});
|
|
17
20
|
if ((dataFlatten.length === 0 && !isLoading) || searchTerm.trim() === "")
|
|
18
21
|
return _jsx(Empty, { description: t("no_conversation") });
|
|
19
22
|
if (isLoading)
|
|
20
23
|
return (_jsx("div", { className: "flex items-center justify-center", children: _jsx(Spin, {}) }));
|
|
21
|
-
return (_jsx("div", { id: "scrollableSearchMessagesTab", className: "h-full overflow-auto", "data-cp-name": "SearchConversationAsMessages", children: _jsx(InfiniteScroll, { dataLength: dataFlatten.length, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableSearchMessagesTab", children: dataFlatten.map((item) => (_jsx(SearchItemAsMessage, { message: item.chatLog, searchTerm: searchTerm, displayTag: item.displayTag }, item.chatLog.clientMsgID))) }) }));
|
|
24
|
+
return (_jsx("div", { id: "scrollableSearchMessagesTab", className: "h-full overflow-auto", "data-cp-name": "SearchConversationAsMessages", children: _jsx(InfiniteScroll, { dataLength: dataFlatten.length, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableSearchMessagesTab", children: dataFlatten.map((item) => (_jsx(SearchItemAsMessage, { message: item.chatLog, searchTerm: searchTerm, displayTag: item.displayTag, tag: item.tag }, item.chatLog.clientMsgID))) }) }));
|
|
22
25
|
};
|
|
23
26
|
export default SearchConversationAsMessages;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchConversationAsUsers.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsUsers.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SearchConversationAsUsers.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsUsers.tsx"],"names":[],"mappings":"AAOA,UAAU,8BAA8B;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,yBAAyB,GAAI,OAAO,8BAA8B,4CA0CvE,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
|
|
@@ -3,15 +3,13 @@ import { Empty, Spin } from "antd";
|
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
4
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
5
5
|
import SearchItemAsUser from "./item/SearchItemAsUser";
|
|
6
|
-
import {
|
|
6
|
+
import { useSearchUsers } from "../../hooks/search/useSearchUsers";
|
|
7
|
+
import { useSearchScope } from "./SearchScopeContext";
|
|
7
8
|
const SearchConversationAsUsers = (props) => {
|
|
8
9
|
const { searchTerm = "" } = props;
|
|
9
10
|
const { t } = useTranslation();
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
searchTerm: searchTerm.trim(),
|
|
13
|
-
},
|
|
14
|
-
});
|
|
11
|
+
const scope = useSearchScope();
|
|
12
|
+
const { dataFlatten, hasNextPage, fetchNextPage, isLoading } = useSearchUsers({ searchTerm, scope });
|
|
15
13
|
if ((dataFlatten.length === 0 && !isLoading) || searchTerm.trim() === "")
|
|
16
14
|
return _jsx(Empty, { description: t("no_conversation") });
|
|
17
15
|
if (isLoading)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchScopeContext.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchScopeContext.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,eAAO,MAAM,mBAAmB,uCAA8B,CAAC;AAE/D,eAAO,MAAM,cAAc,mBAAuC,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SearchScope } from "../../types/search";
|
|
1
2
|
export declare enum SearchConversationTabKey {
|
|
2
3
|
All = "all",
|
|
3
4
|
MyInbox = "myInbox",
|
|
@@ -5,9 +6,11 @@ export declare enum SearchConversationTabKey {
|
|
|
5
6
|
Messages = "messages",
|
|
6
7
|
Groups = "groups"
|
|
7
8
|
}
|
|
8
|
-
interface SearchConversationProps {
|
|
9
|
+
export interface SearchConversationProps {
|
|
9
10
|
searchTerm: string;
|
|
11
|
+
/** Data sources + result navigation. Defaults to the CRM desk behavior. */
|
|
12
|
+
scope?: SearchScope;
|
|
10
13
|
}
|
|
11
|
-
declare const SearchConversation: ({ searchTerm }: SearchConversationProps) => import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
declare const SearchConversation: ({ searchTerm, scope, }: SearchConversationProps) => import("react/jsx-runtime").JSX.Element;
|
|
12
15
|
export default SearchConversation;
|
|
13
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/index.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,oBAAY,wBAAwB;IAClC,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AACD,QAAA,MAAM,kBAAkB,GAAI,wBAGzB,uBAAuB,4CAkFzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -8,6 +8,7 @@ import SearchConversationMyInbox from "./SearchConversationMyInbox";
|
|
|
8
8
|
import SearchConversationAsUsers from "./SearchConversationAsUsers";
|
|
9
9
|
import SearchConversationAsMessages from "./SearchConversationAsMessages";
|
|
10
10
|
import SearchConversationAsGroups from "./SearchConversationAsGroups";
|
|
11
|
+
import { SearchScopeProvider } from "./SearchScopeContext";
|
|
11
12
|
export var SearchConversationTabKey;
|
|
12
13
|
(function (SearchConversationTabKey) {
|
|
13
14
|
SearchConversationTabKey["All"] = "all";
|
|
@@ -16,11 +17,11 @@ export var SearchConversationTabKey;
|
|
|
16
17
|
SearchConversationTabKey["Messages"] = "messages";
|
|
17
18
|
SearchConversationTabKey["Groups"] = "groups";
|
|
18
19
|
})(SearchConversationTabKey || (SearchConversationTabKey = {}));
|
|
19
|
-
const SearchConversation = ({ searchTerm }) => {
|
|
20
|
+
const SearchConversation = ({ searchTerm, scope = "crm", }) => {
|
|
20
21
|
const { t } = useTranslation();
|
|
21
22
|
const [activeKey, setActiveKey] = useState(SearchConversationTabKey.All);
|
|
22
23
|
const items = useMemo(() => {
|
|
23
|
-
|
|
24
|
+
const allItems = [
|
|
24
25
|
{
|
|
25
26
|
key: SearchConversationTabKey.All,
|
|
26
27
|
label: t("all"),
|
|
@@ -47,7 +48,11 @@ const SearchConversation = ({ searchTerm }) => {
|
|
|
47
48
|
children: _jsx(SearchConversationAsGroups, { searchTerm: searchTerm }),
|
|
48
49
|
},
|
|
49
50
|
];
|
|
50
|
-
|
|
51
|
+
// PDP spec: the source inbox is never a search category.
|
|
52
|
+
return scope === "pdp-portal"
|
|
53
|
+
? allItems.filter((item) => item.key !== SearchConversationTabKey.MyInbox)
|
|
54
|
+
: allItems;
|
|
55
|
+
}, [t, searchTerm, scope]);
|
|
51
56
|
// Clicking a result row while on "All" switches activeKey without any
|
|
52
57
|
// click/focus on the tab header itself — antd's own scroll-into-view for
|
|
53
58
|
// that path relies on measuring .ant-tabs-nav against its scroll parent,
|
|
@@ -58,14 +63,14 @@ const SearchConversation = ({ searchTerm }) => {
|
|
|
58
63
|
(_a = document
|
|
59
64
|
.querySelector('[data-cp-name="SearchConversation"] .ant-tabs-tab-active')) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ inline: "nearest", block: "nearest" });
|
|
60
65
|
}, [activeKey]);
|
|
61
|
-
return (_jsx("div", { className: "h-full", "data-cp-name": "SearchConversation", children: _jsx(Tabs, { defaultActiveKey: SearchConversationTabKey.All, items: items, className: "h-full", activeKey: activeKey, onChange: (key) => setActiveKey(key), destroyOnHidden: true,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
return (_jsx(SearchScopeProvider, { value: scope, children: _jsx("div", { className: "h-full", "data-cp-name": "SearchConversation", children: _jsx(Tabs, { defaultActiveKey: SearchConversationTabKey.All, items: items, className: "h-full", activeKey: activeKey, onChange: (key) => setActiveKey(key), destroyOnHidden: true,
|
|
67
|
+
// Ant's built-in tab-overflow ("...") dropdown never recovers from
|
|
68
|
+
// its initial off-screen measurement inside this Drawer (rendered
|
|
69
|
+
// with getContainer={false} for unrelated scroll-position reasons —
|
|
70
|
+
// see DeskConversationList) — the last tab (Nhóm) becomes
|
|
71
|
+
// permanently unreachable. A plain horizontally-scrollable strip
|
|
72
|
+
// sidesteps that positioning bug entirely: every tab stays a real,
|
|
73
|
+
// always-clickable element: no hidden dropdown involved.
|
|
74
|
+
renderTabBar: (tabBarProps, DefaultTabBar) => (_jsx("div", { className: "overflow-x-auto", children: _jsx(DefaultTabBar, Object.assign({}, tabBarProps, { className: "!w-max" })) })) }) }) }));
|
|
70
75
|
};
|
|
71
76
|
export default SearchConversation;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchItemAsGroup.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsGroup.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchItemAsGroup.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsGroup.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AASxF,UAAU,sBAAsB;IAC9B,KAAK,EAAE,4BAA4B,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,iBAAiB,GAAI,OAAO,sBAAsB,4CAwEvD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -7,15 +7,24 @@ import { useChatNavigate } from "../../../hooks/conversation/useChatNavigate";
|
|
|
7
7
|
import { highlightSearch, sanitizeHtml } from "../../../utils/common";
|
|
8
8
|
import { Icon } from "../../../components/icon";
|
|
9
9
|
import GroupCompositeAvatar from "../../../components/group/GroupCompositeAvatar";
|
|
10
|
+
import { useOpenPdpSearchResult } from "../../../hooks/search/useOpenPdpSearchResult";
|
|
11
|
+
import { useSearchScope } from "../SearchScopeContext";
|
|
10
12
|
const SearchItemAsGroup = (props) => {
|
|
11
13
|
const { group, searchTerm = "" } = props;
|
|
12
14
|
const { t } = useTranslation();
|
|
13
15
|
const onNavigate = useChatNavigate();
|
|
16
|
+
const scope = useSearchScope();
|
|
17
|
+
const openPdpResult = useOpenPdpSearchResult();
|
|
14
18
|
const setConversationData = useConversationStore((state) => state.setConversationData);
|
|
15
19
|
const setSelectedConversationId = useConversationStore((state) => state.setSelectedConversationId);
|
|
16
20
|
const { conversation } = group;
|
|
17
21
|
const isPublic = group.visibility === GroupVisibility.Public;
|
|
18
22
|
const onPressItem = () => {
|
|
23
|
+
// PDP's inbox opens real groups by ?groupId, same as its group list.
|
|
24
|
+
if (scope === "pdp-portal") {
|
|
25
|
+
openPdpResult({ groupId: group.groupId });
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
19
28
|
// Result can go stale before the click — force a fresh membership check.
|
|
20
29
|
setConversationData(conversation, undefined, { forceRevalidate: true });
|
|
21
30
|
setSelectedConversationId(conversation.conversationID);
|
|
@@ -5,6 +5,8 @@ interface SearchItemAsMessageProps {
|
|
|
5
5
|
};
|
|
6
6
|
searchTerm: string;
|
|
7
7
|
displayTag?: string;
|
|
8
|
+
/** BE source tag (MY_INBOX | CS_TEAM); only PDP Portal renders from it. */
|
|
9
|
+
tag?: string;
|
|
8
10
|
onClick?: () => void;
|
|
9
11
|
}
|
|
10
12
|
declare const SearchItemAsMessage: (props: SearchItemAsMessageProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchItemAsMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsMessage.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAA4B,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchItemAsMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsMessage.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAA4B,MAAM,8BAA8B,CAAC;AAwBrF,UAAU,wBAAwB;IAChC,OAAO,EAAE,WAAW,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,mBAAmB,GAAI,OAAO,wBAAwB,4CAyH3D,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -10,19 +10,41 @@ import { useTranslation } from "react-i18next";
|
|
|
10
10
|
import useConversationStore from "../../../store/conversation";
|
|
11
11
|
import { useMemo } from "react";
|
|
12
12
|
import useAuthStore from "../../../store/auth";
|
|
13
|
+
import { getConversationIdFromMessage } from "../../../utils/conversation";
|
|
14
|
+
import { useOpenPdpSearchResult } from "../../../hooks/search/useOpenPdpSearchResult";
|
|
15
|
+
import { useSearchScope } from "../SearchScopeContext";
|
|
16
|
+
// PDP labels the source by its inbox tab; BE's displayTag carries the CS team name.
|
|
17
|
+
const PDP_TAG_LABEL_KEYS = {
|
|
18
|
+
MY_INBOX: "my_messages",
|
|
19
|
+
CS_TEAM: "pdp_team_inbox_tag",
|
|
20
|
+
};
|
|
13
21
|
const SearchItemAsMessage = (props) => {
|
|
14
|
-
var _a;
|
|
22
|
+
var _a, _b;
|
|
15
23
|
const { t } = useTranslation();
|
|
16
|
-
const { message, searchTerm = "", displayTag, onClick } = props;
|
|
24
|
+
const { message, searchTerm = "", displayTag, tag, onClick } = props;
|
|
17
25
|
const { user } = useChatContext();
|
|
18
26
|
const isCrm = useAuthStore((state) => state.isCrm);
|
|
27
|
+
const scope = useSearchScope();
|
|
28
|
+
const isPdpPortal = scope === "pdp-portal";
|
|
29
|
+
const openPdpResult = useOpenPdpSearchResult();
|
|
19
30
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
20
31
|
const useConversationDisplay = useMemo(() => {
|
|
21
|
-
|
|
32
|
+
// PDP results span many threads, so show the sender like CRM does.
|
|
33
|
+
if (isCrm || isPdpPortal)
|
|
22
34
|
return true;
|
|
23
35
|
return (user === null || user === void 0 ? void 0 : user.userID) === (message === null || message === void 0 ? void 0 : message.sendID);
|
|
24
|
-
}, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, message === null || message === void 0 ? void 0 : message.sendID, isCrm]);
|
|
36
|
+
}, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, message === null || message === void 0 ? void 0 : message.sendID, isCrm, isPdpPortal]);
|
|
37
|
+
const tagLabel = isPdpPortal
|
|
38
|
+
? tag && PDP_TAG_LABEL_KEYS[tag] && t(PDP_TAG_LABEL_KEYS[tag])
|
|
39
|
+
: displayTag;
|
|
25
40
|
const onPressItem = async () => {
|
|
41
|
+
if (isPdpPortal) {
|
|
42
|
+
openPdpResult({
|
|
43
|
+
threadId: getConversationIdFromMessage(message),
|
|
44
|
+
messageId: message.clientMsgID,
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
26
48
|
const { data } = await DChatSDK.getOneConversation({
|
|
27
49
|
sourceID: message.sessionType === SessionType.Group
|
|
28
50
|
? message.groupID
|
|
@@ -63,13 +85,13 @@ const SearchItemAsMessage = (props) => {
|
|
|
63
85
|
: conversationData === null || conversationData === void 0 ? void 0 : conversationData.faceURL, alt: useConversationDisplay
|
|
64
86
|
? message.senderNickname
|
|
65
87
|
: conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName, children: useConversationDisplay
|
|
66
|
-
? message.senderNickname.charAt(0).toUpperCase()
|
|
88
|
+
? (_b = message.senderNickname) === null || _b === void 0 ? void 0 : _b.charAt(0).toUpperCase()
|
|
67
89
|
: conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName.charAt(0).toUpperCase() }) }), _jsxs("div", { className: "flex flex-col flex-1 min-w-0 gap-1", children: [_jsxs("div", { className: "flex flex-1 items-center justify-between", children: [_jsx("span", { className: "text-sm flex-1 font-semibold truncate", children: useConversationDisplay
|
|
68
90
|
? message.senderNickname
|
|
69
91
|
: conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName }), _jsx("span", { className: "text-xs text-gray-500", children: formatTimestamp(message.sendTime, {
|
|
70
92
|
hasTime: true,
|
|
71
93
|
}) })] }), _jsxs("div", { className: "flex flex-col flex-1 min-w-0 gap-1", children: [_jsx("span", { className: "text-xs flex-1 text-gray-500 truncate", dangerouslySetInnerHTML: {
|
|
72
94
|
__html: sanitizeHtml(highlightSearch(msgContent, searchTerm)),
|
|
73
|
-
} }),
|
|
95
|
+
} }), tagLabel && (_jsx("span", { className: "text-[10px] text-[var(--dc-color-primary)] bg-[var(--dc-color-primary-light)] px-1.5 py-0.5 rounded w-fit truncate", children: tagLabel }))] })] })] }, message.clientMsgID));
|
|
74
96
|
};
|
|
75
97
|
export default SearchItemAsMessage;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ISessionByStatus } from "../../../store/type";
|
|
2
|
+
import type { PdpTeamSessionItem } from "../../../hooks/search/useSearchPdpTeamSessions";
|
|
2
3
|
interface SearchItemAsUserProps {
|
|
3
|
-
session: ISessionByStatus
|
|
4
|
+
session: PdpTeamSessionItem & Partial<Pick<ISessionByStatus, "conversation">>;
|
|
4
5
|
searchTerm: string;
|
|
5
6
|
}
|
|
6
7
|
declare const SearchItemAsUser: (props: SearchItemAsUserProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchItemAsUser.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsUser.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchItemAsUser.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsUser.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIhD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAIlF,UAAU,qBAAqB;IAE7B,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC,CAAC;IAC9E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CA+CrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|