impact-chatbot 2.3.47 → 2.3.49
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/message-template/components/message-content/tabular-content/index.d.ts +4 -1
- package/dist/index.cjs.css +116 -0
- package/dist/index.cjs.js +341 -64
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.css +116 -0
- package/dist/index.esm.js +341 -64
- package/dist/index.esm.js.map +1 -1
- package/dist/tabNotification.d.ts +19 -0
- package/dist/utlis.d.ts +11 -0
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -789,6 +789,55 @@ const generateConversationObject = (conversationId) => {
|
|
|
789
789
|
};
|
|
790
790
|
}
|
|
791
791
|
};
|
|
792
|
+
/**
|
|
793
|
+
* Extracts userExplicitInput and textWithColumnNames from a saved filter set.
|
|
794
|
+
* @param {object} selectedFilterSet - The selected saved filter set object
|
|
795
|
+
* @param {string} userText - The user's input text (used to build textWithColumnNames)
|
|
796
|
+
* @param {object} existingExplicitInput - Optional existing userExplicitInput to merge with (e.g. from @ mentions)
|
|
797
|
+
* @returns {{ userExplicitInput: object, textWithColumnNames: string }}
|
|
798
|
+
*/
|
|
799
|
+
const extractSavedFilterData = (selectedFilterSet, userText = "", existingExplicitInput = {}) => {
|
|
800
|
+
let userExplicitInput = { ...existingExplicitInput };
|
|
801
|
+
let textWithColumnNames = "";
|
|
802
|
+
if (!selectedFilterSet?.saved_filter_preference) {
|
|
803
|
+
return { userExplicitInput: existingExplicitInput, textWithColumnNames };
|
|
804
|
+
}
|
|
805
|
+
selectedFilterSet.saved_filter_preference.forEach((filter) => {
|
|
806
|
+
const attrName = filter.attribute_name;
|
|
807
|
+
if (!attrName)
|
|
808
|
+
return;
|
|
809
|
+
let filterValues = [];
|
|
810
|
+
if (Array.isArray(filter.values)) {
|
|
811
|
+
filter.values.forEach((v) => {
|
|
812
|
+
if (v && Array.isArray(v.values)) {
|
|
813
|
+
filterValues.push(...v.values.map(String));
|
|
814
|
+
}
|
|
815
|
+
else if (typeof v === "string" || typeof v === "number") {
|
|
816
|
+
filterValues.push(String(v));
|
|
817
|
+
}
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
if (filterValues.length > 0) {
|
|
821
|
+
if (userExplicitInput[attrName]) {
|
|
822
|
+
userExplicitInput[attrName] = [
|
|
823
|
+
...new Set([...userExplicitInput[attrName], ...filterValues]),
|
|
824
|
+
];
|
|
825
|
+
}
|
|
826
|
+
else {
|
|
827
|
+
userExplicitInput[attrName] = [...new Set(filterValues)];
|
|
828
|
+
}
|
|
829
|
+
const filterText = `${attrName}: ${filterValues.join(", ")}`;
|
|
830
|
+
textWithColumnNames = textWithColumnNames
|
|
831
|
+
? `${filterText} ${textWithColumnNames}`
|
|
832
|
+
: `${filterText} ${userText}`;
|
|
833
|
+
}
|
|
834
|
+
});
|
|
835
|
+
// Ensure textWithColumnNames ends with the user's text
|
|
836
|
+
if (textWithColumnNames && !textWithColumnNames.includes(userText) && userText.trim()) {
|
|
837
|
+
textWithColumnNames = `${textWithColumnNames} ${userText}`.trim();
|
|
838
|
+
}
|
|
839
|
+
return { userExplicitInput, textWithColumnNames };
|
|
840
|
+
};
|
|
792
841
|
|
|
793
842
|
// Special character mapping for text replacement
|
|
794
843
|
const SPECIAL_CHARACTER_MAPPING = {
|
|
@@ -1880,6 +1929,7 @@ const useAgentFlow = (dateFormat, chatDataRef, currentMode, setShowChatPlacehold
|
|
|
1880
1929
|
chat_input: data?.chatInput,
|
|
1881
1930
|
delay: 0.3,
|
|
1882
1931
|
chat_id: utilityObjectData?.uniqueChatId ? utilityObjectData?.uniqueChatId : utilityObjectData?.currentAgentChatId,
|
|
1932
|
+
answer_mode: data?.answerMode || "auto",
|
|
1883
1933
|
...(!isEmpty(utilityObjectData?.additionalArgs) ? utilityObjectData.additionalArgs : {}),
|
|
1884
1934
|
};
|
|
1885
1935
|
// Handle @ filter mentions - user_explicit_input contains filter values
|
|
@@ -4645,7 +4695,7 @@ const Rectangle = ({ type, icon, title, description, onClick, hoverable }) => {
|
|
|
4645
4695
|
return (jsxRuntime.jsx("div", { className: `${classes.rectangle} ${classes[type]} ${hoverable ? classes.rectangleHoverable : ''}`, onClick: onClick, title: isTruncated ? title : null, children: jsxRuntime.jsxs("div", { className: classes.textContainer, children: [jsxRuntime.jsx(material.Typography, { className: classes.title, ref: titleRef, children: title }), jsxRuntime.jsx(material.Typography, { className: classes.description, children: description })] }) }));
|
|
4646
4696
|
};
|
|
4647
4697
|
const ChatPlaceholder = (props) => {
|
|
4648
|
-
const { dateFormat, chatDataRef, currentMode, setShowChatPlaceholder, setLoader, setCurrentAgentId, baseUrl, setBaseUrl, setCurrentSessionId, customChatConfig, chatDataInfoRef, setChatDataState, userInput, legacyAgentScreen, activeConversationId, chatBodyRef, chatbotContext, setInitValue, setSessionId, thinkingContent, setThinkingContent, isThinking, setIsThinking, chatId, setChatId, isStop, setIsStop, functionsRef, functionsState, setFunctionsState, thinkingHeaderMessage, setThinkingHeaderMessage, uniqueChatId, setUniqueChatId, fieldNumber, setFieldNumber, setAdditionalArgs, questions, displayQuestions, setActiveConversationId } = props;
|
|
4698
|
+
const { dateFormat, chatDataRef, currentMode, setShowChatPlaceholder, setLoader, setCurrentAgentId, baseUrl, setBaseUrl, setCurrentSessionId, customChatConfig, chatDataInfoRef, setChatDataState, userInput, legacyAgentScreen, activeConversationId, chatBodyRef, chatbotContext, setInitValue, setSessionId, thinkingContent, setThinkingContent, isThinking, setIsThinking, chatId, setChatId, isStop, setIsStop, functionsRef, functionsState, setFunctionsState, thinkingHeaderMessage, setThinkingHeaderMessage, uniqueChatId, setUniqueChatId, fieldNumber, setFieldNumber, setAdditionalArgs, questions, displayQuestions, setActiveConversationId, selectedFilterSet, answerMode, } = props;
|
|
4649
4699
|
const classes = useStyles$6();
|
|
4650
4700
|
globalStyles();
|
|
4651
4701
|
const [cardList, setCardList] = React.useState([]);
|
|
@@ -4729,7 +4779,17 @@ const ChatPlaceholder = (props) => {
|
|
|
4729
4779
|
user_input: title,
|
|
4730
4780
|
init: true,
|
|
4731
4781
|
delay: 0.3,
|
|
4782
|
+
answer_mode: answerMode || "auto",
|
|
4732
4783
|
};
|
|
4784
|
+
// If a saved filter set is selected, merge its filters into the payload
|
|
4785
|
+
if (selectedFilterSet?.saved_filter_preference) {
|
|
4786
|
+
const { userExplicitInput, textWithColumnNames } = extractSavedFilterData(selectedFilterSet, title);
|
|
4787
|
+
if (!lodash.isEmpty(userExplicitInput)) {
|
|
4788
|
+
initiateAgentPayload.user_explicit_input = userExplicitInput;
|
|
4789
|
+
initiateAgentPayload.chat_input = title;
|
|
4790
|
+
initiateAgentPayload.user_input = textWithColumnNames || title;
|
|
4791
|
+
}
|
|
4792
|
+
}
|
|
4733
4793
|
setAgentFlow(initiateAgentPayload, "", baseUrl);
|
|
4734
4794
|
}
|
|
4735
4795
|
// setAgentFlow(initiateAgentPayload, "", baseUrl);
|
|
@@ -5108,6 +5168,15 @@ const sseevent = (message, messageToStoreRef) => {
|
|
|
5108
5168
|
}
|
|
5109
5169
|
return new MessageEvent(type, { data: data });
|
|
5110
5170
|
}
|
|
5171
|
+
if (parsedData?.status === "notification") {
|
|
5172
|
+
messageToStoreRef.current.notificationData = {
|
|
5173
|
+
message: parsedData?.message || "",
|
|
5174
|
+
chat_id: parsedData?.chat_id || "",
|
|
5175
|
+
session_id: parsedData?.session_id || "",
|
|
5176
|
+
};
|
|
5177
|
+
// Do NOT append notification messages to chatData.response — return early
|
|
5178
|
+
return new MessageEvent(type, { data: data });
|
|
5179
|
+
}
|
|
5111
5180
|
if (parsedData?.status === "thinking") {
|
|
5112
5181
|
messageToStoreRef.current.chatData.thinkingResponse.thinkingStream =
|
|
5113
5182
|
messageToStoreRef.current.chatData.thinkingResponse.thinkingStream +
|
|
@@ -5144,13 +5213,6 @@ const sseevent = (message, messageToStoreRef) => {
|
|
|
5144
5213
|
? parsedData.additional_args
|
|
5145
5214
|
: {};
|
|
5146
5215
|
}
|
|
5147
|
-
if (parsedData?.status === "notification") {
|
|
5148
|
-
messageToStoreRef.current.notificationData = {
|
|
5149
|
-
message: parsedData?.message || "",
|
|
5150
|
-
chat_id: parsedData?.chat_id || "",
|
|
5151
|
-
session_id: parsedData?.session_id || "",
|
|
5152
|
-
};
|
|
5153
|
-
}
|
|
5154
5216
|
if (parsedData?.status === "completed" ||
|
|
5155
5217
|
parsedData?.status === "follow-up") {
|
|
5156
5218
|
messageToStoreRef.current.initValue = true;
|
|
@@ -5413,10 +5475,10 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5413
5475
|
if (sessionId) {
|
|
5414
5476
|
chatbotServices.stopAgentFlow({ session_id: sessionId }, baseUrl);
|
|
5415
5477
|
}
|
|
5416
|
-
dispatch(smartBotActions.setStepFormStreamData({ status: "error", chunks: [...chunksRef] }));
|
|
5478
|
+
dispatch(smartBotActions.setStepFormStreamData({ status: "error", chunks: [...chunksRef], sessionId }));
|
|
5417
5479
|
};
|
|
5418
5480
|
// Signal that streaming has started (after setting stepFormStreamControl so useEffect sees the flag)
|
|
5419
|
-
dispatch(smartBotActions.setStepFormStreamData({ status: "streaming_start", chunks: [] }));
|
|
5481
|
+
dispatch(smartBotActions.setStepFormStreamData({ status: "streaming_start", chunks: [], sessionId }));
|
|
5420
5482
|
// Fire DOM event so SmartBot can show stop icon (Redux gets cleared by TabularContent before parent effects run)
|
|
5421
5483
|
window.dispatchEvent(new CustomEvent("stepFormStreamStart"));
|
|
5422
5484
|
sourceRef.current = AxiosSource(endPoint, {
|
|
@@ -5438,14 +5500,14 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5438
5500
|
chunksRef.push(data);
|
|
5439
5501
|
// Dispatch widget chunks immediately for real-time rendering
|
|
5440
5502
|
if (data?.status === "widget") {
|
|
5441
|
-
dispatch(smartBotActions.setStepFormStreamData({ status: "widget_chunk", chunks: [data] }));
|
|
5503
|
+
dispatch(smartBotActions.setStepFormStreamData({ status: "widget_chunk", chunks: [data], sessionId }));
|
|
5442
5504
|
}
|
|
5443
5505
|
// If this chunk also carries [DONE], dispatch collected chunks now
|
|
5444
5506
|
if (data?.message === "[DONE]") {
|
|
5445
5507
|
stepFormStreamControl.isStreaming = false;
|
|
5446
5508
|
stepFormStreamControl.abort = null;
|
|
5447
5509
|
window.dispatchEvent(new CustomEvent("stepFormStreamEnd"));
|
|
5448
|
-
dispatch(smartBotActions.setStepFormStreamData({ status: "done", chunks: [...chunksRef] }));
|
|
5510
|
+
dispatch(smartBotActions.setStepFormStreamData({ status: "done", chunks: [...chunksRef], sessionId }));
|
|
5449
5511
|
}
|
|
5450
5512
|
}
|
|
5451
5513
|
else if (data?.status === "completed" || data?.status === "follow-up" || data?.message === "[DONE]") {
|
|
@@ -5469,7 +5531,7 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5469
5531
|
if (data?.status === "completed" && !hasStepForm) {
|
|
5470
5532
|
window.dispatchEvent(new CustomEvent("stepFormStreamCompleted"));
|
|
5471
5533
|
}
|
|
5472
|
-
dispatch(smartBotActions.setStepFormStreamData({ status: "done", chunks: [...chunksRef] }));
|
|
5534
|
+
dispatch(smartBotActions.setStepFormStreamData({ status: "done", chunks: [...chunksRef], sessionId }));
|
|
5473
5535
|
}
|
|
5474
5536
|
else if (data?.message) {
|
|
5475
5537
|
chunksRef.push({ status: "content", message: data.message });
|
|
@@ -5484,7 +5546,7 @@ const ButtonContent = ({ bodyText, isFormDisabled = false, isStepFormSubmit = fa
|
|
|
5484
5546
|
stepFormStreamControl.isStreaming = false;
|
|
5485
5547
|
stepFormStreamControl.abort = null;
|
|
5486
5548
|
window.dispatchEvent(new CustomEvent("stepFormStreamEnd"));
|
|
5487
|
-
dispatch(smartBotActions.setStepFormStreamData({ status: "error", chunks: chunksRef }));
|
|
5549
|
+
dispatch(smartBotActions.setStepFormStreamData({ status: "error", chunks: chunksRef, sessionId }));
|
|
5488
5550
|
});
|
|
5489
5551
|
};
|
|
5490
5552
|
const renderButtons = () => {
|
|
@@ -6756,6 +6818,165 @@ const StepsResponseTab = (props) => {
|
|
|
6756
6818
|
], value: tabValue }) }));
|
|
6757
6819
|
};
|
|
6758
6820
|
|
|
6821
|
+
/**
|
|
6822
|
+
* Tab Notification Utility
|
|
6823
|
+
* Shows a red badge on the browser tab favicon and updates the document title
|
|
6824
|
+
* when new step_form chunks arrive while the user is on a different tab.
|
|
6825
|
+
* Similar to Facebook's unread message count badge.
|
|
6826
|
+
*/
|
|
6827
|
+
const ORIGINAL_TITLE = " Impact Smart ";
|
|
6828
|
+
const FAVICON_SELECTOR = 'link[rel="icon"]';
|
|
6829
|
+
let notificationCount = 0;
|
|
6830
|
+
let originalFaviconHref = null;
|
|
6831
|
+
let faviconCanvas = null;
|
|
6832
|
+
let faviconCtx = null;
|
|
6833
|
+
let faviconImg = null;
|
|
6834
|
+
let isInitialized = false;
|
|
6835
|
+
let visibilityListenerAttached = false;
|
|
6836
|
+
let titleBlinkInterval = null;
|
|
6837
|
+
/**
|
|
6838
|
+
* Initialize the canvas and load the original favicon image.
|
|
6839
|
+
* Called lazily on first notification.
|
|
6840
|
+
*/
|
|
6841
|
+
function init() {
|
|
6842
|
+
if (isInitialized)
|
|
6843
|
+
return;
|
|
6844
|
+
isInitialized = true;
|
|
6845
|
+
const faviconEl = document.querySelector(FAVICON_SELECTOR);
|
|
6846
|
+
originalFaviconHref = faviconEl ? faviconEl.href : "/assets/IA.svg";
|
|
6847
|
+
faviconCanvas = document.createElement("canvas");
|
|
6848
|
+
faviconCanvas.width = 64;
|
|
6849
|
+
faviconCanvas.height = 64;
|
|
6850
|
+
faviconCtx = faviconCanvas.getContext("2d");
|
|
6851
|
+
faviconImg = new Image();
|
|
6852
|
+
faviconImg.crossOrigin = "anonymous";
|
|
6853
|
+
faviconImg.src = originalFaviconHref;
|
|
6854
|
+
if (!visibilityListenerAttached) {
|
|
6855
|
+
visibilityListenerAttached = true;
|
|
6856
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6859
|
+
/**
|
|
6860
|
+
* When the user returns to the tab, clear all notifications.
|
|
6861
|
+
*/
|
|
6862
|
+
function handleVisibilityChange() {
|
|
6863
|
+
if (!document.hidden && notificationCount > 0) {
|
|
6864
|
+
clearTabNotification();
|
|
6865
|
+
}
|
|
6866
|
+
}
|
|
6867
|
+
/**
|
|
6868
|
+
* Draw the favicon with a red notification badge showing the count.
|
|
6869
|
+
*/
|
|
6870
|
+
function drawBadge(count) {
|
|
6871
|
+
if (!faviconCtx || !faviconCanvas)
|
|
6872
|
+
return;
|
|
6873
|
+
const size = faviconCanvas.width;
|
|
6874
|
+
faviconCtx.clearRect(0, 0, size, size);
|
|
6875
|
+
// Draw original favicon
|
|
6876
|
+
if (faviconImg && faviconImg.complete && faviconImg.naturalWidth > 0) {
|
|
6877
|
+
faviconCtx.drawImage(faviconImg, 0, 0, size, size);
|
|
6878
|
+
}
|
|
6879
|
+
if (count <= 0)
|
|
6880
|
+
return;
|
|
6881
|
+
const text = count > 99 ? "99+" : String(count);
|
|
6882
|
+
// Badge dimensions
|
|
6883
|
+
const badgeRadius = 14;
|
|
6884
|
+
const badgeX = size - badgeRadius - 1;
|
|
6885
|
+
const badgeY = badgeRadius + 1;
|
|
6886
|
+
// Draw red circle
|
|
6887
|
+
faviconCtx.beginPath();
|
|
6888
|
+
faviconCtx.arc(badgeX, badgeY, badgeRadius, 0, 2 * Math.PI);
|
|
6889
|
+
faviconCtx.fillStyle = "#e53e3e";
|
|
6890
|
+
faviconCtx.fill();
|
|
6891
|
+
// White border
|
|
6892
|
+
faviconCtx.lineWidth = 2;
|
|
6893
|
+
faviconCtx.strokeStyle = "#ffffff";
|
|
6894
|
+
faviconCtx.stroke();
|
|
6895
|
+
// Draw count text
|
|
6896
|
+
faviconCtx.fillStyle = "#ffffff";
|
|
6897
|
+
faviconCtx.font = `bold ${count > 9 ? 14 : 18}px sans-serif`;
|
|
6898
|
+
faviconCtx.textAlign = "center";
|
|
6899
|
+
faviconCtx.textBaseline = "middle";
|
|
6900
|
+
faviconCtx.fillText(text, badgeX, badgeY + 1);
|
|
6901
|
+
}
|
|
6902
|
+
/**
|
|
6903
|
+
* Update the favicon element in the DOM.
|
|
6904
|
+
*/
|
|
6905
|
+
function applyFavicon(dataUrl) {
|
|
6906
|
+
let faviconEl = document.querySelector(FAVICON_SELECTOR);
|
|
6907
|
+
if (!faviconEl) {
|
|
6908
|
+
faviconEl = document.createElement("link");
|
|
6909
|
+
faviconEl.rel = "icon";
|
|
6910
|
+
document.head.appendChild(faviconEl);
|
|
6911
|
+
}
|
|
6912
|
+
faviconEl.href = dataUrl;
|
|
6913
|
+
}
|
|
6914
|
+
/**
|
|
6915
|
+
* Increment the tab notification count.
|
|
6916
|
+
* Only shows badge when the tab is not visible (user is on another tab).
|
|
6917
|
+
*/
|
|
6918
|
+
function showTabNotification() {
|
|
6919
|
+
// Only notify when user is NOT looking at this tab
|
|
6920
|
+
if (!document.hidden)
|
|
6921
|
+
return;
|
|
6922
|
+
init();
|
|
6923
|
+
notificationCount += 1;
|
|
6924
|
+
// Start blinking title to grab attention
|
|
6925
|
+
startTitleBlink();
|
|
6926
|
+
// Draw and apply badge favicon
|
|
6927
|
+
const renderBadge = () => {
|
|
6928
|
+
drawBadge(notificationCount);
|
|
6929
|
+
applyFavicon(faviconCanvas.toDataURL("image/png"));
|
|
6930
|
+
};
|
|
6931
|
+
if (faviconImg && faviconImg.complete) {
|
|
6932
|
+
renderBadge();
|
|
6933
|
+
}
|
|
6934
|
+
else if (faviconImg) {
|
|
6935
|
+
faviconImg.onload = renderBadge;
|
|
6936
|
+
}
|
|
6937
|
+
}
|
|
6938
|
+
/**
|
|
6939
|
+
* Alternates the document title between notification message and a blank/attention string
|
|
6940
|
+
* to create a blinking effect that catches the user's eye (like WhatsApp Web / Facebook).
|
|
6941
|
+
*/
|
|
6942
|
+
function startTitleBlink() {
|
|
6943
|
+
if (titleBlinkInterval)
|
|
6944
|
+
clearInterval(titleBlinkInterval);
|
|
6945
|
+
let showNotification = true;
|
|
6946
|
+
const notificationTitle = `(${notificationCount}) New form awaiting input`;
|
|
6947
|
+
// Set immediately
|
|
6948
|
+
document.title = notificationTitle;
|
|
6949
|
+
titleBlinkInterval = setInterval(() => {
|
|
6950
|
+
if (showNotification) {
|
|
6951
|
+
document.title = ORIGINAL_TITLE.trim();
|
|
6952
|
+
}
|
|
6953
|
+
else {
|
|
6954
|
+
document.title = `(${notificationCount}) New form awaiting input`;
|
|
6955
|
+
}
|
|
6956
|
+
showNotification = !showNotification;
|
|
6957
|
+
}, 1000);
|
|
6958
|
+
}
|
|
6959
|
+
/**
|
|
6960
|
+
* Stop the title blink interval.
|
|
6961
|
+
*/
|
|
6962
|
+
function stopTitleBlink() {
|
|
6963
|
+
if (titleBlinkInterval) {
|
|
6964
|
+
clearInterval(titleBlinkInterval);
|
|
6965
|
+
titleBlinkInterval = null;
|
|
6966
|
+
}
|
|
6967
|
+
}
|
|
6968
|
+
/**
|
|
6969
|
+
* Clear all tab notifications — restore original title and favicon.
|
|
6970
|
+
*/
|
|
6971
|
+
function clearTabNotification() {
|
|
6972
|
+
notificationCount = 0;
|
|
6973
|
+
stopTitleBlink();
|
|
6974
|
+
document.title = ORIGINAL_TITLE;
|
|
6975
|
+
if (originalFaviconHref) {
|
|
6976
|
+
applyFavicon(originalFaviconHref);
|
|
6977
|
+
}
|
|
6978
|
+
}
|
|
6979
|
+
|
|
6759
6980
|
/**
|
|
6760
6981
|
* Module-level Map to persist streaming state across component remounts (tab switches).
|
|
6761
6982
|
* Keyed by a stable identifier derived from input payload + mode + conversation ID.
|
|
@@ -7085,6 +7306,7 @@ const StreamedContent = ({ botData }) => {
|
|
|
7085
7306
|
setStepChange((prev) => !prev);
|
|
7086
7307
|
}
|
|
7087
7308
|
else if (data.status === "step_form") {
|
|
7309
|
+
showTabNotification();
|
|
7088
7310
|
const formWidgetData = isArray(data.widget_data)
|
|
7089
7311
|
? data.widget_data
|
|
7090
7312
|
: [data.widget_data];
|
|
@@ -7369,6 +7591,7 @@ const StreamedContent = ({ botData }) => {
|
|
|
7369
7591
|
data: isEmpty(dummyButton)
|
|
7370
7592
|
? [textResponseTobeParsed, ...finalData]
|
|
7371
7593
|
: [textResponseTobeParsed, ...finalData, dummyButton],
|
|
7594
|
+
session_id: messageToStoreRef.current.sessionId || "",
|
|
7372
7595
|
},
|
|
7373
7596
|
},
|
|
7374
7597
|
};
|
|
@@ -7453,6 +7676,7 @@ const StreamedContent = ({ botData }) => {
|
|
|
7453
7676
|
data: {
|
|
7454
7677
|
data: {
|
|
7455
7678
|
data: [textResponseTobeParsed, ...finalData],
|
|
7679
|
+
session_id: messageToStoreRef.current.sessionId || "",
|
|
7456
7680
|
},
|
|
7457
7681
|
},
|
|
7458
7682
|
};
|
|
@@ -7873,7 +8097,11 @@ const AgentResponse = ({ children }) => {
|
|
|
7873
8097
|
return (jsxRuntime.jsx("div", { className: classes.agentResponseContainer, children: children }));
|
|
7874
8098
|
};
|
|
7875
8099
|
|
|
7876
|
-
|
|
8100
|
+
// Module-level counter and active instance tracker.
|
|
8101
|
+
// Only the active instance should process stepFormStreamData from Redux.
|
|
8102
|
+
let instanceCounter = 0;
|
|
8103
|
+
let activeTabularInstanceId = null;
|
|
8104
|
+
const TabularContent = ({ steps: initialSteps, currentTabValue, children, questions: initialQuestions = [], questionsStepsMap: initialQuestionsStepsMap = {}, stepFormDataMap: initialStepFormDataMap = {}, isFormDisabled = false, sessionId: propSessionId = "" }) => {
|
|
7877
8105
|
const dispatch = reactRedux.useDispatch();
|
|
7878
8106
|
const stepFormStreamData = reactRedux.useSelector((state) => state.smartBotReducer.stepFormStreamData);
|
|
7879
8107
|
const [tabValue, setTabValue] = React.useState(currentTabValue);
|
|
@@ -7897,6 +8125,12 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
|
|
|
7897
8125
|
const [stepFormSubmitted, setStepFormSubmitted] = React.useState(false);
|
|
7898
8126
|
const [hasNewStepFormFromRestream, setHasNewStepFormFromRestream] = React.useState(false);
|
|
7899
8127
|
const [activeFormIntent, setActiveFormIntent] = React.useState(null);
|
|
8128
|
+
// Stable unique instance ID for this TabularContent mount
|
|
8129
|
+
const instanceIdRef = React.useRef(null);
|
|
8130
|
+
if (instanceIdRef.current === null) {
|
|
8131
|
+
instanceCounter += 1;
|
|
8132
|
+
instanceIdRef.current = instanceCounter;
|
|
8133
|
+
}
|
|
7900
8134
|
// Refs for accumulating state during streaming (avoids stale closures)
|
|
7901
8135
|
const stepsRef = React.useRef(stepsState);
|
|
7902
8136
|
const questionsRef = React.useRef(questionsState);
|
|
@@ -7938,10 +8172,21 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
|
|
|
7938
8172
|
return null;
|
|
7939
8173
|
}
|
|
7940
8174
|
};
|
|
8175
|
+
// Register as active instance when this TabularContent has an active step form
|
|
8176
|
+
React.useEffect(() => {
|
|
8177
|
+
const hasActiveForm = Object.keys(initialStepFormDataMap).length > 0;
|
|
8178
|
+
if (hasActiveForm) {
|
|
8179
|
+
activeTabularInstanceId = instanceIdRef.current;
|
|
8180
|
+
}
|
|
8181
|
+
}, [initialStepFormDataMap]);
|
|
7941
8182
|
// Watch Redux for batched SSE chunks dispatched by ButtonContent
|
|
7942
8183
|
React.useEffect(() => {
|
|
7943
8184
|
if (!stepFormStreamData)
|
|
7944
8185
|
return;
|
|
8186
|
+
// Only the active instance should process stepFormStreamData
|
|
8187
|
+
if (activeTabularInstanceId !== null && activeTabularInstanceId !== instanceIdRef.current) {
|
|
8188
|
+
return;
|
|
8189
|
+
}
|
|
7945
8190
|
const payload = stepFormStreamData;
|
|
7946
8191
|
// Clear Redux immediately
|
|
7947
8192
|
dispatch(smartBotActions.setStepFormStreamData(null));
|
|
@@ -8095,6 +8340,8 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
|
|
|
8095
8340
|
setStepFormSubmitted(false);
|
|
8096
8341
|
setHasNewStepFormFromRestream(true);
|
|
8097
8342
|
setActiveFormIntent(latestIntent || null);
|
|
8343
|
+
// Re-register as active instance since this TabularContent now owns the new form
|
|
8344
|
+
activeTabularInstanceId = instanceIdRef.current;
|
|
8098
8345
|
// Clear stale persisted form values and context so the new form starts fresh
|
|
8099
8346
|
dispatch(smartBotActions.clearPersistedFormValues());
|
|
8100
8347
|
dispatch(smartBotActions.setChatbotContext({}));
|
|
@@ -8119,6 +8366,10 @@ const TabularContent = ({ steps: initialSteps, currentTabValue, children, questi
|
|
|
8119
8366
|
jsxRuntime.jsxs(AgentResponse, { children: [children, renderedWidgets.length > 0 && (jsxRuntime.jsx("div", { className: "restream-widget-content", children: renderedWidgets }))] }),
|
|
8120
8367
|
], value: tabValue }) }));
|
|
8121
8368
|
};
|
|
8369
|
+
/** Reset the active instance tracker (call when a new conversation starts from the input field) */
|
|
8370
|
+
const resetActiveTabularInstance = () => {
|
|
8371
|
+
activeTabularInstanceId = null;
|
|
8372
|
+
};
|
|
8122
8373
|
|
|
8123
8374
|
const CombinedContent = ({ botData, props }) => {
|
|
8124
8375
|
const isFormDisabled = botData?.isFormDisabled || false;
|
|
@@ -8187,7 +8438,7 @@ const CombinedContent = ({ botData, props }) => {
|
|
|
8187
8438
|
const validContent = renderedContent.filter(content => content !== null);
|
|
8188
8439
|
const renderCombinedContent = () => (jsxRuntime.jsx("div", { className: "combined-content-container", children: validContent.length > 0 ? (validContent.map((content, index) => (jsxRuntime.jsx("div", { className: "combined-content-item", children: content }, `wrapper-${index}`)))) : (jsxRuntime.jsx("div", { children: "No valid content to display" })) }));
|
|
8189
8440
|
if (isTabEnabled) {
|
|
8190
|
-
return (jsxRuntime.jsx(TabularContent, { steps: botData?.utilityData?.steps || [], currentTabValue: botData?.utilityData?.currentTabValue || "steps", questions: botData?.utilityData?.questions || [], questionsStepsMap: botData?.utilityData?.questionsStepsMap || {}, stepFormDataMap: botData?.utilityData?.stepFormDataMap || {}, isFormDisabled: isFormDisabled, children: renderCombinedContent() }));
|
|
8441
|
+
return (jsxRuntime.jsx(TabularContent, { steps: botData?.utilityData?.steps || [], currentTabValue: botData?.utilityData?.currentTabValue || "steps", questions: botData?.utilityData?.questions || [], questionsStepsMap: botData?.utilityData?.questionsStepsMap || {}, stepFormDataMap: botData?.utilityData?.stepFormDataMap || {}, isFormDisabled: isFormDisabled, sessionId: botData?.sessionId || "", children: renderCombinedContent() }));
|
|
8191
8442
|
}
|
|
8192
8443
|
return renderCombinedContent();
|
|
8193
8444
|
};
|
|
@@ -9602,7 +9853,7 @@ const useMentionState = () => {
|
|
|
9602
9853
|
};
|
|
9603
9854
|
|
|
9604
9855
|
const ChatbotInput = (props) => {
|
|
9605
|
-
const { newChatScreen, inputValue, setInputValue, isStopIcon, handleMicClick, handleRefresh, onSendIconClick, onStopIconClick, currentMode, filterOptions, onSaveClick, savedFilterSets, onFilterSetSelect, onTriggerRefresh, selectedFilterSet, onClearFilterSet, } = props;
|
|
9856
|
+
const { newChatScreen, inputValue, setInputValue, isStopIcon, handleMicClick, handleRefresh, onSendIconClick, onStopIconClick, currentMode, filterOptions, onSaveClick, savedFilterSets, onFilterSetSelect, onTriggerRefresh, selectedFilterSet, onClearFilterSet, answerMode, setAnswerMode, } = props;
|
|
9606
9857
|
const editorRef = React.useRef(null);
|
|
9607
9858
|
const selectRef = React.useRef(null);
|
|
9608
9859
|
const filterSetSelectRef = React.useRef(null);
|
|
@@ -9612,6 +9863,8 @@ const ChatbotInput = (props) => {
|
|
|
9612
9863
|
const chatInputContainerRef = React.useRef(null);
|
|
9613
9864
|
const [isFixed, setIsFixed] = React.useState(false);
|
|
9614
9865
|
const [height, setHeight] = React.useState("auto");
|
|
9866
|
+
const [showAnswerModeMenu, setShowAnswerModeMenu] = React.useState(false);
|
|
9867
|
+
const answerModeRef = React.useRef(null);
|
|
9615
9868
|
const [hasMentionsInEditor, setHasMentionsInEditor] = React.useState(false);
|
|
9616
9869
|
const isInsertingMentionRef = React.useRef(false);
|
|
9617
9870
|
const isTransitioningStageRef = React.useRef(false);
|
|
@@ -10612,44 +10865,9 @@ const ChatbotInput = (props) => {
|
|
|
10612
10865
|
// If a saved filter set is selected, merge its filters into userExplicitInput
|
|
10613
10866
|
// and textWithColumnNames in the same format as @ mentions
|
|
10614
10867
|
if (selectedFilterSet?.saved_filter_preference) {
|
|
10615
|
-
selectedFilterSet
|
|
10616
|
-
|
|
10617
|
-
|
|
10618
|
-
return;
|
|
10619
|
-
// Extract all values from the filter's values array
|
|
10620
|
-
let filterValues = [];
|
|
10621
|
-
if (Array.isArray(filter.values)) {
|
|
10622
|
-
filter.values.forEach((v) => {
|
|
10623
|
-
if (v && Array.isArray(v.values)) {
|
|
10624
|
-
filterValues.push(...v.values.map(String));
|
|
10625
|
-
}
|
|
10626
|
-
else if (typeof v === "string" || typeof v === "number") {
|
|
10627
|
-
filterValues.push(String(v));
|
|
10628
|
-
}
|
|
10629
|
-
});
|
|
10630
|
-
}
|
|
10631
|
-
if (filterValues.length > 0) {
|
|
10632
|
-
// Merge into userExplicitInput (combine with existing @ mention values if any)
|
|
10633
|
-
if (userExplicitInput[attrName]) {
|
|
10634
|
-
userExplicitInput[attrName] = [
|
|
10635
|
-
...new Set([...userExplicitInput[attrName], ...filterValues]),
|
|
10636
|
-
];
|
|
10637
|
-
}
|
|
10638
|
-
else {
|
|
10639
|
-
userExplicitInput[attrName] = [...new Set(filterValues)];
|
|
10640
|
-
}
|
|
10641
|
-
// Build textWithColumnNames prefix from saved filter data
|
|
10642
|
-
const filterText = `${attrName}: ${filterValues.join(", ")}`;
|
|
10643
|
-
textWithColumnNames = textWithColumnNames
|
|
10644
|
-
? `${filterText} ${textWithColumnNames}`
|
|
10645
|
-
: `${filterText} ${formattedText}`;
|
|
10646
|
-
}
|
|
10647
|
-
});
|
|
10648
|
-
// If textWithColumnNames was not set by mentions but was set by saved filters,
|
|
10649
|
-
// ensure it ends with the user's text
|
|
10650
|
-
if (!textWithColumnNames.includes(formattedText) && formattedText.trim()) {
|
|
10651
|
-
textWithColumnNames = `${textWithColumnNames} ${formattedText}`.trim();
|
|
10652
|
-
}
|
|
10868
|
+
const filterData = extractSavedFilterData(selectedFilterSet, formattedText, userExplicitInput);
|
|
10869
|
+
Object.assign(userExplicitInput, filterData.userExplicitInput);
|
|
10870
|
+
textWithColumnNames = filterData.textWithColumnNames || textWithColumnNames;
|
|
10653
10871
|
}
|
|
10654
10872
|
setInputValue("");
|
|
10655
10873
|
if (editorRef.current) {
|
|
@@ -10909,6 +11127,25 @@ const ChatbotInput = (props) => {
|
|
|
10909
11127
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
10910
11128
|
};
|
|
10911
11129
|
}, [showFilterSetMenu]);
|
|
11130
|
+
// Click outside handler for answer mode dropdown
|
|
11131
|
+
React.useEffect(() => {
|
|
11132
|
+
const handleClickOutside = (event) => {
|
|
11133
|
+
if (answerModeRef.current && !answerModeRef.current.contains(event.target)) {
|
|
11134
|
+
setShowAnswerModeMenu(false);
|
|
11135
|
+
}
|
|
11136
|
+
};
|
|
11137
|
+
if (showAnswerModeMenu) {
|
|
11138
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
11139
|
+
}
|
|
11140
|
+
return () => {
|
|
11141
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
11142
|
+
};
|
|
11143
|
+
}, [showAnswerModeMenu]);
|
|
11144
|
+
const ANSWER_MODE_OPTIONS = [
|
|
11145
|
+
{ value: "fast", label: "Fast", description: "Speed over depth" },
|
|
11146
|
+
{ value: "auto", label: "Auto", description: "Adapts depth, detail, and visuals" },
|
|
11147
|
+
];
|
|
11148
|
+
const selectedModeOption = ANSWER_MODE_OPTIONS.find((opt) => opt.value === answerMode) || ANSWER_MODE_OPTIONS[1];
|
|
10912
11149
|
return (jsxRuntime.jsx("div", { className: "chat-input-container", ref: chatInputContainerRef, onClick: (e) => {
|
|
10913
11150
|
// Focus editor when clicking anywhere in the input container
|
|
10914
11151
|
// unless clicking on a button or interactive element
|
|
@@ -10919,7 +11156,8 @@ const ChatbotInput = (props) => {
|
|
|
10919
11156
|
!target.closest(".chat-actions") &&
|
|
10920
11157
|
!target.closest(".filter-set-trigger-wrapper") &&
|
|
10921
11158
|
!target.closest(".filter-set-chip-clear") &&
|
|
10922
|
-
!target.closest(".mention-select-wrapper")
|
|
11159
|
+
!target.closest(".mention-select-wrapper") &&
|
|
11160
|
+
!target.closest(".answer-mode-wrapper")) {
|
|
10923
11161
|
editorRef.current.focus();
|
|
10924
11162
|
}
|
|
10925
11163
|
}, children: jsxRuntime.jsxs("div", { className: `chat-input-wrapper ${isFixed ? "stacked" : ""} ${selectedFilterSet ? "has-filter-selected" : ""} ${(!isFixed || inputValue === "") && !newChatScreen && !selectedFilterSet ? "empty" : ""} ${!newChatScreen && !isFixed && !selectedFilterSet ? "single-line-textarea" : ""}`, style: { height }, children: [jsxRuntime.jsxs("div", { className: "chat-input-left-actions", children: [jsxRuntime.jsxs("div", { className: "filter-set-trigger-wrapper", ref: filterSetSelectRef, children: [jsxRuntime.jsx(impactUiV3.Tooltip, { title: hasMentionsInEditor || showMentionSelect ? "Cannot use filter set while @ mentions are active" : "Add filter set", children: jsxRuntime.jsx("button", { type: "button", className: `filter-set-plus-btn${hasMentionsInEditor || showMentionSelect ? " disabled" : ""}`, onClick: () => {
|
|
@@ -10949,7 +11187,10 @@ const ChatbotInput = (props) => {
|
|
|
10949
11187
|
handleSendMessage();
|
|
10950
11188
|
}
|
|
10951
11189
|
}
|
|
10952
|
-
}, onClick: detectMention, onKeyUp: detectMention, suppressContentEditableWarning: true }), jsxRuntime.jsxs("div", { className: `chat-actions ${isFixed ? "fixed" : ""}`, children: [handleRefresh && (jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SvgChatBotRefreshIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "url", onClick: handleRefresh })), handleMicClick && (jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SvgChatBotMicIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: handleMicClick })), onSaveClick && (jsxRuntime.jsx(impactUiV3.Tooltip, { title: "Save Chat", children: jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SaveOutlinedIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: onSaveClick, id: "chat-input-save-button" }) })), jsxRuntime.
|
|
11190
|
+
}, onClick: detectMention, onKeyUp: detectMention, suppressContentEditableWarning: true }), jsxRuntime.jsxs("div", { className: `chat-actions ${isFixed ? "fixed" : ""}`, children: [handleRefresh && (jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SvgChatBotRefreshIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "url", onClick: handleRefresh })), handleMicClick && (jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SvgChatBotMicIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: handleMicClick })), onSaveClick && (jsxRuntime.jsx(impactUiV3.Tooltip, { title: "Save Chat", children: jsxRuntime.jsx(impactUiV3.Button, { icon: jsxRuntime.jsx(SaveOutlinedIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "tertiary", onClick: onSaveClick, id: "chat-input-save-button" }) })), jsxRuntime.jsxs("div", { className: "answer-mode-wrapper", ref: answerModeRef, children: [jsxRuntime.jsxs("button", { type: "button", className: "answer-mode-trigger", onClick: () => setShowAnswerModeMenu(!showAnswerModeMenu), children: [jsxRuntime.jsx("span", { className: "answer-mode-trigger-label", children: selectedModeOption.label }), jsxRuntime.jsx("svg", { className: `answer-mode-trigger-chevron ${showAnswerModeMenu ? "open" : ""}`, width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: jsxRuntime.jsx("path", { d: "M3 7.5L6 4.5L9 7.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), showAnswerModeMenu && (jsxRuntime.jsx("div", { className: "answer-mode-dropdown", children: ANSWER_MODE_OPTIONS.map((option) => (jsxRuntime.jsxs("button", { type: "button", className: `answer-mode-option ${answerMode === option.value ? "selected" : ""}`, onClick: () => {
|
|
11191
|
+
setAnswerMode(option.value);
|
|
11192
|
+
setShowAnswerModeMenu(false);
|
|
11193
|
+
}, children: [jsxRuntime.jsx("div", { className: "answer-mode-option-check", children: answerMode === option.value && (jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: jsxRuntime.jsx("path", { d: "M2.5 7L5.5 10L11.5 4", stroke: "#5C6BC0", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })) }), jsxRuntime.jsxs("div", { className: "answer-mode-option-content", children: [jsxRuntime.jsx("span", { className: "answer-mode-option-label", children: option.label }), jsxRuntime.jsx("span", { className: "answer-mode-option-desc", children: option.description })] })] }, option.value))) }))] }), jsxRuntime.jsx(impactUiV3.Button, { icon: !isStopIcon ? jsxRuntime.jsx(SvgChatBotSendIcon, {}) : jsxRuntime.jsx(SvgChatbotStopIcon, {}), iconPlacement: "left", size: "large", type: "default", variant: "primary", onClick: () => {
|
|
10953
11194
|
!isStopIcon ? handleSendMessage() : onStopIconClick();
|
|
10954
11195
|
}, id: "chat-input-send-button", className: isStopIcon ? "stop-icon-button" : "" })] }), showMentionSelect && (jsxRuntime.jsx("div", { className: "mention-select-wrapper", ref: selectRef, style: {
|
|
10955
11196
|
position: "fixed",
|
|
@@ -11714,7 +11955,7 @@ const useStyles = styles.makeStyles({
|
|
|
11714
11955
|
});
|
|
11715
11956
|
const ChatbotSaveFilterComponent = (props) => {
|
|
11716
11957
|
const classes = useStyles();
|
|
11717
|
-
const { savedFilterSets, partialClose } = props;
|
|
11958
|
+
const { savedFilterSets, partialClose, chatBotWidth } = props;
|
|
11718
11959
|
const [showFilter, setShowFilter] = React.useState(!lodash.isEmpty(savedFilterSets));
|
|
11719
11960
|
/**
|
|
11720
11961
|
* onFilterDashboardClick function is called when we click the apply filter
|
|
@@ -11787,11 +12028,13 @@ const ChatbotSaveFilterComponent = (props) => {
|
|
|
11787
12028
|
}
|
|
11788
12029
|
const filterContainer = document.querySelector(".impact_drawer_filter_container.impact_drawer_filter_container_large");
|
|
11789
12030
|
if (filterContainer) {
|
|
11790
|
-
|
|
12031
|
+
const computedWidth = chatBotWidth ? `${chatBotWidth - 86}px` : "616px";
|
|
12032
|
+
filterContainer.style.setProperty("width", computedWidth);
|
|
11791
12033
|
}
|
|
11792
12034
|
const rightPanel = document.querySelector(".impact_drawer_filter_container .impact_drawer_filter_container_right_panel");
|
|
11793
12035
|
if (rightPanel) {
|
|
11794
12036
|
rightPanel.style.setProperty("height", "600px");
|
|
12037
|
+
rightPanel.style.setProperty("width", "100%");
|
|
11795
12038
|
}
|
|
11796
12039
|
const backdrop = document.querySelector(".MuiBackdrop-root.MuiModal-backdrop");
|
|
11797
12040
|
if (backdrop) {
|
|
@@ -11825,7 +12068,7 @@ const ChatbotSaveFilterComponent = (props) => {
|
|
|
11825
12068
|
const observer = new MutationObserver(patchDrawer);
|
|
11826
12069
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
11827
12070
|
return () => observer.disconnect();
|
|
11828
|
-
}, [showFilter]);
|
|
12071
|
+
}, [showFilter, chatBotWidth]);
|
|
11829
12072
|
return (jsxRuntime.jsx("div", { className: partialClose ? classes.hidden : undefined, children: !showFilter ?
|
|
11830
12073
|
jsxRuntime.jsxs("div", { className: classes.container, children: [jsxRuntime.jsx(NoFilterSetSavedIcon, { width: "189px", height: "126px", className: classes.icon }), jsxRuntime.jsx("p", { className: classes.title, children: "No filter set saved!" }), jsxRuntime.jsx("p", { className: classes.subtitle, children: "Create and save a filter set to use as your default scope or apply it anytime during a conversation" }), jsxRuntime.jsx("div", { className: classes.buttonWrapper, children: jsxRuntime.jsx(impactUiV3.Button, { variant: "primary", onClick: () => setShowFilter(true), children: "Create A Filter Set" }) })] }) :
|
|
11831
12074
|
jsxRuntime.jsx("div", { children: jsxRuntime.jsx(CoreComponentScreen, { showPageHeader: false,
|
|
@@ -11859,6 +12102,7 @@ const SmartBot = (props) => {
|
|
|
11859
12102
|
// Per-mode conversation ID tracking — prevents cross-mode contamination when
|
|
11860
12103
|
// switching tabs while streams are pending.
|
|
11861
12104
|
React.useRef({});
|
|
12105
|
+
const activeConversationIdRef = React.useRef(activeConversationId);
|
|
11862
12106
|
const activeTab = React.useRef({
|
|
11863
12107
|
activeTab: "dashboard",
|
|
11864
12108
|
});
|
|
@@ -11877,6 +12121,8 @@ const SmartBot = (props) => {
|
|
|
11877
12121
|
const [filterOptions, setFilterOptions] = React.useState([]);
|
|
11878
12122
|
const [savedFilterSets, setSavedFilterSets] = React.useState([]);
|
|
11879
12123
|
const [selectedFilterSet, setSelectedFilterSet] = React.useState(null);
|
|
12124
|
+
const [answerMode, setAnswerMode] = React.useState("auto");
|
|
12125
|
+
const [chatBotWidth, setChatBotWidth] = React.useState(null);
|
|
11880
12126
|
React.useRef(0);
|
|
11881
12127
|
const { setUserFlow, setUserScreenAndFlow, fetchUserResultsFromQuery, getCurrentDateTimeString, setLink, } = useChatFlow(chatDataRef, setLoader, setFlowType, setScreenName, setUserInput, setQuestionIndex, setCurrentAppLink, flowType, screenName, questionIndex, userInput, dateFormat, currentMode, activeConversationId, setIsModuleChanged, chatBodyRef, filterReducerState, dispatch, navigate, setShowChatPlaceholder, baseUrl, setChatDataState, setCurrentSessionId, customChatConfig, chatDataInfoRef, chatbotContext, setInitValue, setSessionId, thinkingContent, setThinkingContent, isThinking, setIsThinking, chatId, setChatId, isStop, setIsStop, functionsRef, functionsState, setFunctionsState, thinkingHeaderMessage, setThinkingHeaderMessage, uniqueChatId, initValue, sessionId, fieldNumber, setFieldNumber, additionalArgs, setActiveConversationId, navSessionId, setNavSessionId);
|
|
11882
12128
|
const { parseSavedFlow, saveCurrentChanges, endCurrentSession, clearChatSession, initiateNewChat, hasUnsavedChanges, } = useChatSession(chatDataRef, setFlowType, setScreenName, setUserInput, setTemplateData, chatDataScreenLinkRef, setShowModal, setMinimizedMode, setSelectedModule, setChatDataState, currentMode, setUserFlow, getCurrentDateTimeString, setCurrentAppLink, selectedModule, fetchUserResultsFromQuery, props.closeBot, activeConversationId, setActiveConversationId, setShowChatPlaceholder);
|
|
@@ -11909,6 +12155,10 @@ const SmartBot = (props) => {
|
|
|
11909
12155
|
setFieldNumber,
|
|
11910
12156
|
setAdditionalArgs,
|
|
11911
12157
|
});
|
|
12158
|
+
// Keep activeConversationIdRef in sync so event handlers with [] deps can access the latest value
|
|
12159
|
+
React.useEffect(() => {
|
|
12160
|
+
activeConversationIdRef.current = activeConversationId;
|
|
12161
|
+
}, [activeConversationId]);
|
|
11912
12162
|
// Show/hide stop icon when step-form restream (second init API from ButtonContent) starts/ends.
|
|
11913
12163
|
// Must live here (SmartBot) because StreamedContent unmounts after the first stream completes.
|
|
11914
12164
|
React.useEffect(() => {
|
|
@@ -11930,6 +12180,23 @@ const SmartBot = (props) => {
|
|
|
11930
12180
|
};
|
|
11931
12181
|
const handleStepFormStreamEnd = () => {
|
|
11932
12182
|
setIsStop(false);
|
|
12183
|
+
// Update the timestamp on the last bot message to reflect when the restream completed
|
|
12184
|
+
try {
|
|
12185
|
+
const mode = localStorage.getItem("currentModeData") || "agent";
|
|
12186
|
+
const convId = activeConversationIdRef.current;
|
|
12187
|
+
const messages = chatDataInfoRef?.current?.[mode]?.conversations?.[convId]?.messages;
|
|
12188
|
+
if (messages && messages.length > 0) {
|
|
12189
|
+
const lastBotIdx = messages.reduce((lastIdx, msg, idx) => msg.userType === "bot" ? idx : lastIdx, -1);
|
|
12190
|
+
if (lastBotIdx !== -1) {
|
|
12191
|
+
messages[lastBotIdx].timeStamp = moment().format(dateFormat);
|
|
12192
|
+
// Trigger re-render so the UI reflects the updated timestamp
|
|
12193
|
+
setChatDataState((prev) => ({ ...prev }));
|
|
12194
|
+
}
|
|
12195
|
+
}
|
|
12196
|
+
}
|
|
12197
|
+
catch (e) {
|
|
12198
|
+
console.error("Error updating timestamp after step form stream:", e);
|
|
12199
|
+
}
|
|
11933
12200
|
};
|
|
11934
12201
|
window.addEventListener("stepFormStreamStart", handleStepFormStreamStart);
|
|
11935
12202
|
window.addEventListener("stepFormStreamEnd", handleStepFormStreamEnd);
|
|
@@ -12336,6 +12603,7 @@ const SmartBot = (props) => {
|
|
|
12336
12603
|
baseUrl: baseUrl,
|
|
12337
12604
|
userExplicitInput: userExplicitInput,
|
|
12338
12605
|
textWithColumnNames: textWithColumnNames,
|
|
12606
|
+
answerMode: answerMode,
|
|
12339
12607
|
};
|
|
12340
12608
|
// if(!isEmpty(userInput)) {
|
|
12341
12609
|
dispatch(smartBotActions.setThinkingContext({
|
|
@@ -12366,6 +12634,9 @@ const SmartBot = (props) => {
|
|
|
12366
12634
|
};
|
|
12367
12635
|
const onSendIconClick = (params, params2) => {
|
|
12368
12636
|
try {
|
|
12637
|
+
// Reset step form stream state so old TabularContent instances don't process new data
|
|
12638
|
+
dispatch(smartBotActions.setStepFormStreamData(null));
|
|
12639
|
+
resetActiveTabularInstance();
|
|
12369
12640
|
// dispatch(setChatbotContext({}));
|
|
12370
12641
|
setUserInput(params?.text);
|
|
12371
12642
|
handleSendMessage(params?.text, params?.userExplicitInput, params?.textWithColumnNames);
|
|
@@ -12515,7 +12786,9 @@ const SmartBot = (props) => {
|
|
|
12515
12786
|
}
|
|
12516
12787
|
fetchConversations(null, "agent");
|
|
12517
12788
|
}, [renameConversation, deleteConversation, fetchConversations]);
|
|
12518
|
-
return (jsxRuntime.jsxs("div", { className: `${classes.agentStyleOverride} ${partialClose ? classes.hideBotStyle : ""} `, children: [jsxRuntime.jsx(MemoryModal, { isModalOpen: isModalOpen, setIsModalOpen: setIsModalOpen, displaySnackMessages: displaySnackMessages }), jsxRuntime.jsx(UploadModal, { isUploadModalOpen: isUploadModalOpen, setIsUploadModalOpen: setIsUploadModalOpen, displaySnackMessages: displaySnackMessages }), jsxRuntime.jsx(impactUiV3.ChatBotComponent, { isFullWidth: forceOpen, userName: userName, showHistoryPanel: false, customInputComponent: currentMode === "agent" && !showSavedFilters ? (jsxRuntime.jsx(ChatbotInput, { newChatScreen: newChatScreen, inputValue: userInput, setInputValue: setUserInput, isStopIcon: isStop, onSendIconClick: onSendIconClick, onStopIconClick: onStopIconClick, currentMode: currentMode, filterOptions: filterOptions,
|
|
12789
|
+
return (jsxRuntime.jsxs("div", { className: `${classes.agentStyleOverride} ${partialClose ? classes.hideBotStyle : ""} `, children: [jsxRuntime.jsx(MemoryModal, { isModalOpen: isModalOpen, setIsModalOpen: setIsModalOpen, displaySnackMessages: displaySnackMessages }), jsxRuntime.jsx(UploadModal, { isUploadModalOpen: isUploadModalOpen, setIsUploadModalOpen: setIsUploadModalOpen, displaySnackMessages: displaySnackMessages }), jsxRuntime.jsx(impactUiV3.ChatBotComponent, { isFullWidth: forceOpen, userName: userName, showHistoryPanel: false, customInputComponent: currentMode === "agent" && !showSavedFilters ? (jsxRuntime.jsx(ChatbotInput, { newChatScreen: newChatScreen, inputValue: userInput, setInputValue: setUserInput, isStopIcon: isStop, onSendIconClick: onSendIconClick, onStopIconClick: onStopIconClick, currentMode: currentMode, filterOptions: filterOptions,
|
|
12790
|
+
// onSaveClick={saveCurrentChat}
|
|
12791
|
+
savedFilterSets: savedFilterSets, selectedFilterSet: selectedFilterSet, onFilterSetSelect: (filterSet) => setSelectedFilterSet(filterSet), onClearFilterSet: () => setSelectedFilterSet(null), onTriggerRefresh: triggerRefreshAction, answerMode: answerMode, setAnswerMode: setAnswerMode })) : showSavedFilters ? jsxRuntime.jsx(jsxRuntime.Fragment, {}) : null, isChatBotOpen: showModal || forceOpen, historyPanelData: historyPanelData, onHistorySearchChange: (params) => { console.log("History Search Change", params); }, onHistorySelectConversation: (params) => {
|
|
12519
12792
|
console.log("History Select Conversation", params);
|
|
12520
12793
|
setNewChatScreen(false);
|
|
12521
12794
|
setShowChatPlaceholder(false);
|
|
@@ -12532,6 +12805,8 @@ const SmartBot = (props) => {
|
|
|
12532
12805
|
localStorage.setItem("isStreaming", "false");
|
|
12533
12806
|
dispatch(smartBotActions.setChatbotContext({}));
|
|
12534
12807
|
dispatch(smartBotActions.clearPersistedFormValues());
|
|
12808
|
+
dispatch(smartBotActions.setStepFormStreamData(null));
|
|
12809
|
+
resetActiveTabularInstance();
|
|
12535
12810
|
setConversation([]);
|
|
12536
12811
|
chatDataInfoRef.current[currentMode] = {
|
|
12537
12812
|
conversations: {},
|
|
@@ -12722,9 +12997,9 @@ const SmartBot = (props) => {
|
|
|
12722
12997
|
icon: jsxRuntime.jsx(SvgSaveFilterTab, {}),
|
|
12723
12998
|
},
|
|
12724
12999
|
], utilityList: utilityList, isAssistantThinking: false, isCustomScreen: showChatPlaceholder ? showChatPlaceholder : showSavedFilters, customScreenJsx: showChatPlaceholder ?
|
|
12725
|
-
jsxRuntime.jsx(ChatPlaceholder, { dateFormat: dateFormat, chatDataRef: chatDataRef, currentMode: currentMode, setShowChatPlaceholder: setShowChatPlaceholder, setLoader: setLoader, setCurrentAgentId: setCurrentAgentId, baseUrl: baseUrl, setBaseUrl: setBaseUrl, setCurrentSessionId: setCurrentSessionId, customChatConfig: customChatConfig, chatDataInfoRef: chatDataInfoRef, setChatDataState: setChatDataState, userInput: userInput, legacyAgentScreen: legacyAgentScreen, activeConversationId: activeConversationId, chatBodyRef: chatBodyRef, chatbotContext: chatbotContext, setInitValue: setInitValue, setSessionId: setSessionId, thinkingContent: thinkingContext?.thinkingContent, setThinkingContent: setThinkingContent, isThinking: isThinking, setIsThinking: setIsThinking, chatId: chatId, setChatId: setChatId, isStop: isStop, setIsStop: setIsStop, functionsRef: functionsRef, functionsState: functionsState, setFunctionsState: setFunctionsState, thinkingHeaderMessage: thinkingContext?.thinkingHeaderMessage, setThinkingHeaderMessage: setThinkingHeaderMessage, uniqueChatId: uniqueChatId, setUniqueChatId: setUniqueChatId, fieldNumber: fieldNumber, setFieldNumber: setFieldNumber, setAdditionalArgs: setAdditionalArgs, displayQuestions: displayQuestions, questions: questions, setActiveConversationId: setActiveConversationId })
|
|
13000
|
+
jsxRuntime.jsx(ChatPlaceholder, { dateFormat: dateFormat, chatDataRef: chatDataRef, currentMode: currentMode, setShowChatPlaceholder: setShowChatPlaceholder, setLoader: setLoader, setCurrentAgentId: setCurrentAgentId, baseUrl: baseUrl, setBaseUrl: setBaseUrl, setCurrentSessionId: setCurrentSessionId, customChatConfig: customChatConfig, chatDataInfoRef: chatDataInfoRef, setChatDataState: setChatDataState, userInput: userInput, legacyAgentScreen: legacyAgentScreen, activeConversationId: activeConversationId, chatBodyRef: chatBodyRef, chatbotContext: chatbotContext, setInitValue: setInitValue, setSessionId: setSessionId, thinkingContent: thinkingContext?.thinkingContent, setThinkingContent: setThinkingContent, isThinking: isThinking, setIsThinking: setIsThinking, chatId: chatId, setChatId: setChatId, isStop: isStop, setIsStop: setIsStop, functionsRef: functionsRef, functionsState: functionsState, setFunctionsState: setFunctionsState, thinkingHeaderMessage: thinkingContext?.thinkingHeaderMessage, setThinkingHeaderMessage: setThinkingHeaderMessage, uniqueChatId: uniqueChatId, setUniqueChatId: setUniqueChatId, fieldNumber: fieldNumber, setFieldNumber: setFieldNumber, setAdditionalArgs: setAdditionalArgs, displayQuestions: displayQuestions, questions: questions, setActiveConversationId: setActiveConversationId, selectedFilterSet: selectedFilterSet, answerMode: answerMode })
|
|
12726
13001
|
:
|
|
12727
|
-
jsxRuntime.jsx(ChatbotSaveFilterComponent$1, { savedFilterSets: savedFilterSets, partialClose: partialClose }), inputText: userInput, threadList: ["Home"], hideMenuArrow: hideMenu, newChatScreen: newChatScreen, isModuleListLoading: modulesLoading, suggestionBanner: {
|
|
13002
|
+
jsxRuntime.jsx(ChatbotSaveFilterComponent$1, { savedFilterSets: savedFilterSets, partialClose: partialClose, chatBotWidth: chatBotWidth }), inputText: userInput, threadList: ["Home"], hideMenuArrow: hideMenu, newChatScreen: newChatScreen, isModuleListLoading: modulesLoading, suggestionBanner: {
|
|
12728
13003
|
freeTextHeading: "Try adding more details :",
|
|
12729
13004
|
freeTextContent: "Alan works better when you provide more context and pointed questions",
|
|
12730
13005
|
}, isStopIcon: isStop, onStopIconClick: onStopIconClick, footerText: "AI-generated responses may contain errors\u2014please verify important information", showSuggestionBanner: showSavedFilters ? false : showSuggestionBanner, onCloseSuggestionBanner: () => {
|
|
@@ -12744,7 +13019,9 @@ const SmartBot = (props) => {
|
|
|
12744
13019
|
}, handleSaveChat: () => {
|
|
12745
13020
|
// Handle save chat logic here
|
|
12746
13021
|
saveCurrentChat();
|
|
12747
|
-
}
|
|
13022
|
+
}, onChatBotResize: (params) => {
|
|
13023
|
+
setChatBotWidth(params);
|
|
13024
|
+
}, onMinimiseChatBot: null })] }));
|
|
12748
13025
|
};
|
|
12749
13026
|
|
|
12750
13027
|
exports.default = SmartBot;
|