@cognizant-ai-lab/ui-common 1.6.0 → 1.8.0
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/Theme/Palettes.d.ts +0 -9
- package/dist/Theme/Palettes.js +0 -18
- package/dist/components/AgentChat/ChatCommon/ChatCommon.d.ts +11 -7
- package/dist/components/AgentChat/ChatCommon/ChatCommon.js +119 -90
- package/dist/components/AgentChat/ChatCommon/Const.d.ts +1 -0
- package/dist/components/AgentChat/ChatCommon/Const.js +2 -0
- package/dist/components/AgentChat/ChatCommon/ControlButtons.d.ts +1 -1
- package/dist/components/AgentChat/ChatCommon/ControlButtons.js +7 -4
- package/dist/components/AgentChat/ChatCommon/FormattedMarkdown.js +3 -0
- package/dist/components/AgentChat/ChatCommon/SendButton.js +7 -6
- package/dist/components/AgentChat/ChatCommon/SyntaxHighlighterThemes.js +1 -1
- package/dist/components/AgentChat/ChatCommon/Thinking.d.ts +1 -0
- package/dist/components/AgentChat/ChatCommon/Thinking.js +10 -7
- package/dist/components/AgentChat/Common/LlmChatButton.d.ts +0 -2
- package/dist/components/AgentChat/Common/LlmChatButton.js +6 -9
- package/dist/components/AgentChat/VoiceChat/MicrophoneButton.js +12 -10
- package/dist/components/ChatBot/ChatBot.d.ts +0 -4
- package/dist/components/ChatBot/ChatBot.js +2 -2
- package/dist/components/Common/Navbar.js +24 -22
- package/dist/components/Common/StatusLight.d.ts +9 -0
- package/dist/components/Common/StatusLight.js +21 -0
- package/dist/components/ErrorPage/ErrorBoundary.js +1 -1
- package/dist/components/ErrorPage/ErrorPage.d.ts +3 -3
- package/dist/components/ErrorPage/ErrorPage.js +4 -3
- package/dist/components/Logo/Common.d.ts +4 -0
- package/dist/components/Logo/Common.js +8 -0
- package/dist/components/Logo/CustomerLogo.d.ts +23 -0
- package/dist/components/Logo/CustomerLogo.js +41 -0
- package/dist/components/MultiAgentAccelerator/AgentConversations.js +0 -1
- package/dist/components/MultiAgentAccelerator/AgentFlow.js +85 -53
- package/dist/components/MultiAgentAccelerator/AgentNode.js +23 -27
- package/dist/components/MultiAgentAccelerator/GraphLayouts.d.ts +17 -10
- package/dist/components/MultiAgentAccelerator/GraphLayouts.js +4 -6
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +3 -9
- package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +102 -47
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.d.ts +0 -5
- package/dist/components/MultiAgentAccelerator/Sidebar/AgentNetworkTreeItem.js +30 -25
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.d.ts +3 -4
- package/dist/components/MultiAgentAccelerator/Sidebar/Sidebar.js +84 -168
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.d.ts +30 -13
- package/dist/components/MultiAgentAccelerator/Sidebar/TreeBuilder.js +157 -100
- package/dist/components/MultiAgentAccelerator/Tour/MainTourSteps.js +10 -8
- package/dist/components/MultiAgentAccelerator/const.d.ts +2 -0
- package/dist/components/MultiAgentAccelerator/const.js +4 -0
- package/dist/components/Settings/ApiKeyInput.d.ts +16 -0
- package/dist/components/Settings/ApiKeyInput.js +69 -0
- package/dist/components/Settings/InfoTip.d.ts +8 -0
- package/dist/components/Settings/InfoTip.js +14 -0
- package/dist/components/Settings/SettingsDialog.js +379 -178
- package/dist/components/Settings/SettingsRow.d.ts +18 -0
- package/dist/components/Settings/SettingsRow.js +35 -0
- package/dist/controller/agent/Agent.d.ts +3 -20
- package/dist/controller/agent/Agent.js +9 -43
- package/dist/controller/agent/IconSuggestions.d.ts +35 -0
- package/dist/controller/agent/IconSuggestions.js +85 -0
- package/dist/controller/llm/Providers.d.ts +2 -0
- package/dist/controller/llm/Providers.js +41 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/state/IconSuggestions.d.ts +27 -0
- package/dist/state/IconSuggestions.js +50 -0
- package/dist/state/Settings.d.ts +19 -3
- package/dist/state/Settings.js +24 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/title.js +1 -1
- package/package.json +5 -1
- package/dist/components/Common/CustomerLogo.d.ts +0 -17
- package/dist/components/Common/CustomerLogo.js +0 -49
- package/dist/components/Common/MUIAccordion.d.ts +0 -17
- package/dist/components/Common/MUIAccordion.js +0 -66
- package/dist/utils/useLocalStorage.d.ts +0 -1
- package/dist/utils/useLocalStorage.js +0 -55
|
@@ -15,14 +15,15 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import SendIcon from "@mui/icons-material/Send";
|
|
18
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
18
19
|
import { LlmChatButton } from "../Common/LlmChatButton.js";
|
|
19
|
-
|
|
20
|
+
//#endregion: Types
|
|
20
21
|
/**
|
|
21
22
|
* Generate the Send Button for a chat window.
|
|
22
23
|
* @returns The Send Button.
|
|
23
24
|
*/
|
|
24
|
-
export const SendButton = ({ enableSendButton, id, onClickCallback }) => (_jsx(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
export const SendButton = ({ enableSendButton, id, onClickCallback }) => (_jsx(Tooltip, { placement: "top", title: enableSendButton ? "Send" : "Enter a message to enable the send button", children: _jsx("span", { style: {
|
|
26
|
+
display: "inline-block",
|
|
27
|
+
cursor: enableSendButton ? "inherit" : "not-allowed",
|
|
28
|
+
}, children: _jsx(LlmChatButton, { "aria-label": "Send", disabled: !enableSendButton, id: id, onClick: onClickCallback, tabIndex: 0, children: _jsx(SendIcon, { fontSize: "small", id: "stop-button-icon" // Could update this but it would impact QA
|
|
29
|
+
}) }) }) }));
|
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|
|
17
17
|
* List of available hljs themes for the syntax highlighter.
|
|
18
18
|
* See: https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/src/styles/hljs/index.js
|
|
19
19
|
*/
|
|
20
|
-
import { a11yDark, a11yLight, atelierDuneDark, docco } from "react-syntax-highlighter/dist/
|
|
20
|
+
import { a11yDark, a11yLight, atelierDuneDark, docco } from "react-syntax-highlighter/dist/esm/styles/hljs";
|
|
21
21
|
// hljs themes
|
|
22
22
|
export const HLJS_THEMES = {
|
|
23
23
|
a11yDark,
|
|
@@ -3,6 +3,7 @@ import { ConversationTurn } from "./ConversationTurn.js";
|
|
|
3
3
|
interface ThinkingProps {
|
|
4
4
|
readonly id: string;
|
|
5
5
|
readonly turns: ConversationTurn[];
|
|
6
|
+
readonly useNativeNames: boolean;
|
|
6
7
|
}
|
|
7
8
|
/**
|
|
8
9
|
* Component to render the "thinking" section of the chat, which includes all messages from the agent that are
|
|
@@ -6,6 +6,7 @@ import ReactMarkdown from "react-markdown";
|
|
|
6
6
|
import { MessageRole } from "./ConversationTurn.js";
|
|
7
7
|
import { ChatMessageType } from "../../../generated/neuro-san/NeuroSanClient.js";
|
|
8
8
|
import { AccordionLite } from "../../Common/AccordionLite.js";
|
|
9
|
+
import { cleanUpAgentName, removeTrailingUuid } from "../Common/Utils.js";
|
|
9
10
|
/**
|
|
10
11
|
* Set of message types that should be included in the "thinking" section.
|
|
11
12
|
*/
|
|
@@ -15,17 +16,19 @@ const THINKING_MESSAGE_TYPES = new Set([
|
|
|
15
16
|
ChatMessageType.AGENT_PROGRESS,
|
|
16
17
|
ChatMessageType.SYSTEM,
|
|
17
18
|
]);
|
|
18
|
-
const DEFAULT_AGENT_NAME = "
|
|
19
|
-
const formatTurn = (turn) => {
|
|
20
|
-
const
|
|
21
|
-
const
|
|
19
|
+
const DEFAULT_AGENT_NAME = "agent";
|
|
20
|
+
const formatTurn = (turn, useNativeNames) => {
|
|
21
|
+
const agentName = turn.agentName ?? DEFAULT_AGENT_NAME;
|
|
22
|
+
const displayName = useNativeNames ? agentName : cleanUpAgentName(removeTrailingUuid(agentName));
|
|
23
|
+
const headerLine = `**${displayName}**: ${turn.text || ""}`;
|
|
24
|
+
const structureLine = turn.structure == null ? "" : `\n\`${JSON.stringify(turn.structure, null, 2)}\``;
|
|
22
25
|
return `${headerLine}${structureLine}`;
|
|
23
26
|
};
|
|
24
27
|
/**
|
|
25
28
|
* Component to render the "thinking" section of the chat, which includes all messages from the agent that are
|
|
26
29
|
* of a type included in THINKING_MESSAGE_TYPES.
|
|
27
30
|
*/
|
|
28
|
-
export const Thinking = ({ id, turns }) => {
|
|
31
|
+
export const Thinking = ({ id, turns, useNativeNames }) => {
|
|
29
32
|
const thinkingText = useMemo(() => {
|
|
30
33
|
// Find start of latest interaction (most recent user prompt)
|
|
31
34
|
const lastUserTurnIndex = turns.map((t) => t.role).lastIndexOf(MessageRole.User);
|
|
@@ -35,9 +38,9 @@ export const Thinking = ({ id, turns }) => {
|
|
|
35
38
|
.slice(lastUserTurnIndex + 1)
|
|
36
39
|
.filter((turn) => THINKING_MESSAGE_TYPES.has(turn.messageType))
|
|
37
40
|
.filter((turn) => turn.text?.trim().length > 0 || !isEmpty(turn.structure))
|
|
38
|
-
.map((turn) => formatTurn(turn))
|
|
41
|
+
.map((turn) => formatTurn(turn, useNativeNames))
|
|
39
42
|
.join("\n\n");
|
|
40
|
-
}, [turns]);
|
|
43
|
+
}, [turns, useNativeNames]);
|
|
41
44
|
return (thinkingText.length > 0 && (_jsx(AccordionLite, { id: `${id}-thinking`, items: _jsx(Box, { sx: {
|
|
42
45
|
marginLeft: "0.5rem",
|
|
43
46
|
fontSize: "smaller",
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
type LLMChatGroupConfigBtnProps = {
|
|
2
2
|
disabled?: boolean;
|
|
3
|
-
posRight?: number;
|
|
4
|
-
posBottom?: number;
|
|
5
3
|
};
|
|
6
4
|
export declare const LlmChatButton: import("@emotion/styled").StyledComponent<import("@mui/material/Button").ButtonOwnProps & Omit<import("@mui/material/ButtonBase").ButtonBaseOwnProps, keyof import("@mui/material/Button").ButtonOwnProps> & Omit<import("@mui/material/ButtonBase").ButtonBaseOwnProps, "tabIndex" | "type" | "action" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "nativeButton" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef" | keyof import("@mui/material/Button").ButtonOwnProps> & import("@mui/material/OverridableComponent").CommonProps & Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "style" | "children" | "sx" | "className" | "tabIndex" | "color" | "href" | "type" | "classes" | "variant" | "action" | "size" | "disabled" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "nativeButton" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple" | "loading" | "loadingIndicator" | "disableElevation" | "endIcon" | "fullWidth" | "loadingPosition" | "startIcon"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme> & LLMChatGroupConfigBtnProps, {}, {}>;
|
|
7
5
|
export declare const SmallLlmChatButton: import("@emotion/styled").StyledComponent<import("@mui/material/Button").ButtonOwnProps & Omit<import("@mui/material/ButtonBase").ButtonBaseOwnProps, keyof import("@mui/material/Button").ButtonOwnProps> & Omit<import("@mui/material/ButtonBase").ButtonBaseOwnProps, "tabIndex" | "type" | "action" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "nativeButton" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef" | keyof import("@mui/material/Button").ButtonOwnProps> & import("@mui/material/OverridableComponent").CommonProps & Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "style" | "children" | "sx" | "className" | "tabIndex" | "color" | "href" | "type" | "classes" | "variant" | "action" | "size" | "disabled" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "nativeButton" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple" | "loading" | "loadingIndicator" | "disableElevation" | "endIcon" | "fullWidth" | "loadingPosition" | "startIcon"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme> & LLMChatGroupConfigBtnProps, {}, {}>;
|
|
@@ -15,17 +15,14 @@ limitations under the License.
|
|
|
15
15
|
*/
|
|
16
16
|
import Button from "@mui/material/Button";
|
|
17
17
|
import { styled } from "@mui/material/styles";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
background: `${theme.palette.primary.main} !important`,
|
|
18
|
+
//#endregion: Types
|
|
19
|
+
// In LlmChatButton.tsx
|
|
20
|
+
export const LlmChatButton = styled(Button)(({ disabled, theme }) => ({
|
|
21
|
+
backgroundColor: theme.palette.background.paper,
|
|
23
22
|
borderRadius: "var(--bs-border-radius)",
|
|
24
|
-
|
|
25
|
-
cursor: disabled ? "default" : "pointer",
|
|
23
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
26
24
|
opacity: disabled ? "50%" : "100%",
|
|
27
|
-
|
|
28
|
-
position: "absolute",
|
|
25
|
+
padding: "0.5rem",
|
|
29
26
|
}));
|
|
30
27
|
export const SmallLlmChatButton = styled(LlmChatButton)({
|
|
31
28
|
minWidth: 0,
|
|
@@ -19,7 +19,7 @@ import MicOffIcon from "@mui/icons-material/MicOff";
|
|
|
19
19
|
import Tooltip from "@mui/material/Tooltip";
|
|
20
20
|
import { checkSpeechSupport, toggleListening } from "./VoiceChat.js";
|
|
21
21
|
import { LlmChatButton } from "../Common/LlmChatButton.js";
|
|
22
|
-
|
|
22
|
+
//#endregion: Types
|
|
23
23
|
/**
|
|
24
24
|
* Microphone button component for voice input functionality.
|
|
25
25
|
* Handles toggling voice recognition on/off and displays appropriate visual feedback.
|
|
@@ -42,14 +42,16 @@ export const MicrophoneButton = ({ isMicOn, onMicToggle, speechRecognitionRef, v
|
|
|
42
42
|
await toggleListening(newMicState, speechRecognitionRef.current);
|
|
43
43
|
};
|
|
44
44
|
const isDisabled = !speechSupported;
|
|
45
|
-
const tooltipText =
|
|
46
|
-
?
|
|
47
|
-
: isMicOn
|
|
45
|
+
const tooltipText = speechSupported
|
|
46
|
+
? isMicOn
|
|
48
47
|
? "Turn microphone off"
|
|
49
|
-
: "Turn microphone on"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
: "Turn microphone on"
|
|
49
|
+
: "Voice input is only supported in Google Chrome on Mac or Windows.";
|
|
50
|
+
const isListeningActive = isMicOn && voiceInputState.isListening;
|
|
51
|
+
return (_jsx(Tooltip, { placement: "top", title: tooltipText, children: _jsx("span", { style: {
|
|
52
|
+
display: "inline-block",
|
|
53
|
+
cursor: isDisabled ? "not-allowed" : "inherit",
|
|
54
|
+
}, children: _jsx(LlmChatButton, { "data-testid": "microphone-button", disabled: isDisabled, id: "microphone-button", onClick: handleClick, sx: {
|
|
55
|
+
backgroundColor: isListeningActive ? "success.main" : "background.paper",
|
|
56
|
+
}, tabIndex: 0, children: voiceInputState.isListening ? (_jsx(MicNoneIcon, { "data-testid": "MicNoneIcon", fontSize: "small" })) : (_jsx(MicOffIcon, { "data-testid": "MicOffIcon", fontSize: "small" })) }) }) }));
|
|
55
57
|
};
|
|
@@ -29,7 +29,7 @@ import { LegacyAgentType } from "../AgentChat/Common/Types.js";
|
|
|
29
29
|
* Site-wide Chatbot component.
|
|
30
30
|
*/
|
|
31
31
|
// Temporarily disabled but will be used once we migrated the backend to use Neuro-san RAG.
|
|
32
|
-
export const ChatBot = ({ id,
|
|
32
|
+
export const ChatBot = ({ id, pageContext }) => {
|
|
33
33
|
const [chatOpen, setChatOpen] = useState(false);
|
|
34
34
|
const [isAwaitingLlm, setIsAwaitingLlm] = useState(false);
|
|
35
35
|
const { user: { name: currentUser }, } = useAuthentication().data;
|
|
@@ -51,7 +51,7 @@ export const ChatBot = ({ id, userAvatar, pageContext }) => {
|
|
|
51
51
|
borderWidth: 1,
|
|
52
52
|
borderColor: darkMode ? "var(--bs-white)" : "var(--bs-gray-light)",
|
|
53
53
|
zIndex: getZIndex(2, theme),
|
|
54
|
-
}, children: _jsx(ChatCommon, { id: "chatbot-window", currentUser: currentUser, setIsAwaitingLlm: setIsAwaitingLlm, isAwaitingLlm: isAwaitingLlm,
|
|
54
|
+
}, children: _jsx(ChatCommon, { id: "chatbot-window", currentUser: currentUser, setIsAwaitingLlm: setIsAwaitingLlm, isAwaitingLlm: isAwaitingLlm, selectedNetwork: LegacyAgentType.ChatBot, legacyAgentEndpoint: CHATBOT_ENDPOINT, extraParams: { pageContext }, backgroundColor: darkMode ? "var(--bs-gray-dark)" : "var(--bs-tertiary-blue)", title: "Cognizant Neuro AI Assistant", onClose: () => setChatOpen(false) }) }) }), !chatOpen && (_jsx(Box, { id: `chatbot-icon-${id}`, sx: {
|
|
55
55
|
display: "flex",
|
|
56
56
|
alignItems: "center",
|
|
57
57
|
backgroundColor: darkMode ? "var(--bs-dark-mode-dim)" : "var(--bs-white)",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
|
|
4
4
|
|
|
@@ -18,6 +18,7 @@ limitations under the License.
|
|
|
18
18
|
* Main navigation bar that appears at the top of each page
|
|
19
19
|
*/
|
|
20
20
|
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
|
21
|
+
import Business from "@mui/icons-material/Business";
|
|
21
22
|
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
|
22
23
|
import SettingsIcon from "@mui/icons-material/Settings";
|
|
23
24
|
import Box from "@mui/material/Box";
|
|
@@ -28,14 +29,14 @@ import MenuItem from "@mui/material/MenuItem";
|
|
|
28
29
|
import { useColorScheme } from "@mui/material/styles";
|
|
29
30
|
import Tooltip from "@mui/material/Tooltip";
|
|
30
31
|
import Typography from "@mui/material/Typography";
|
|
31
|
-
import {
|
|
32
|
+
import { useState } from "react";
|
|
32
33
|
import { ConfirmationModal } from "./ConfirmationModal.js";
|
|
33
|
-
import { CustomerLogo, getCognizantLogoImage } from "./CustomerLogo.js";
|
|
34
|
-
import { LoadingSpinner } from "./LoadingSpinner.js";
|
|
35
34
|
import { authenticationEnabled, DEFAULT_USER_IMAGE, getContactUsConfirmationText, NEURO_SAN_UI_VERSION, } from "../../const.js";
|
|
36
35
|
import { useSettingsStore } from "../../state/Settings.js";
|
|
37
36
|
import { isDarkMode } from "../../Theme/Theme.js";
|
|
38
37
|
import { navigateToUrl } from "../../utils/BrowserNavigation.js";
|
|
38
|
+
import { getCognizantLogoImage } from "../Logo/Common.js";
|
|
39
|
+
import { CustomerLogo } from "../Logo/CustomerLogo.js";
|
|
39
40
|
import { SettingsDialog } from "../Settings/SettingsDialog.js";
|
|
40
41
|
const MENU_ITEM_TEXT_PROPS = {
|
|
41
42
|
color: "var(--bs-white)",
|
|
@@ -58,12 +59,6 @@ export const Navbar = ({ authenticationType, id, logo, logoServiceToken, onStart
|
|
|
58
59
|
// Dark mode
|
|
59
60
|
const { mode, setMode, systemMode } = useColorScheme();
|
|
60
61
|
const darkMode = isDarkMode(mode, systemMode);
|
|
61
|
-
// Gate to make sure we only attempt to render after Next.js has completed its rehydration
|
|
62
|
-
const [hydrated, setHydrated] = useState(false);
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
// Indicate that the component has been hydrated
|
|
65
|
-
setHydrated(true);
|
|
66
|
-
}, []);
|
|
67
62
|
// Help menu wiring
|
|
68
63
|
const [helpMenuAnchorEl, setHelpMenuAnchorEl] = useState(null);
|
|
69
64
|
const helpMenuOpen = Boolean(helpMenuAnchorEl);
|
|
@@ -88,18 +83,25 @@ export const Navbar = ({ authenticationType, id, logo, logoServiceToken, onStart
|
|
|
88
83
|
const customer = useSettingsStore((state) => state.settings.branding.customer);
|
|
89
84
|
const primary = useSettingsStore((state) => state.settings.branding.primary);
|
|
90
85
|
const hasCustomer = customer?.trim().length > 0;
|
|
91
|
-
|
|
86
|
+
// Logo settings
|
|
87
|
+
const iconSuggestion = useSettingsStore((state) => state.settings.branding.iconSuggestion);
|
|
88
|
+
const logoSource = useSettingsStore((state) => state.settings.branding.logoSource);
|
|
89
|
+
return (_jsxs(Grid, { id: "nav-bar-container", container: true, sx: {
|
|
92
90
|
alignItems: "center",
|
|
93
91
|
...MENU_ITEM_TEXT_PROPS,
|
|
94
92
|
padding: "0.5rem",
|
|
95
|
-
}, children: [settingsDialogOpen && (_jsx(SettingsDialog, { id: "settings-dialog", isOpen: settingsDialogOpen, logoServiceToken: logoServiceToken, onClose: () => setSettingsDialogOpen(false) })),
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
}, children: [settingsDialogOpen && (_jsx(SettingsDialog, { id: "settings-dialog", isOpen: settingsDialogOpen, logoServiceToken: logoServiceToken, onClose: () => setSettingsDialogOpen(false) })), _jsx(Box, { sx: {
|
|
94
|
+
alignItems: "center",
|
|
95
|
+
display: "flex",
|
|
96
|
+
gap: 2,
|
|
97
|
+
}, children: hasCustomer ? (_jsxs(_Fragment, { children: [_jsx(CustomerLogo, { customer: customer, fallbackIcon: Business, iconSuggestion: iconSuggestion, logoServiceToken: logoServiceToken, logoSource: logoSource }), _jsx(Typography, { "data-testid": "customer-branding", sx: {
|
|
98
|
+
fontSize: "20px",
|
|
99
|
+
fontWeight: "600",
|
|
100
|
+
paddingLeft: "0.15rem",
|
|
101
|
+
width: "200px",
|
|
102
|
+
display: "flex",
|
|
103
|
+
alignItems: "center",
|
|
104
|
+
}, children: customer })] })) : (getCognizantLogoImage()) }), _jsxs(Grid, { id: id, sx: { display: "flex", alignItems: "center" }, children: [hasCustomer ? getCognizantLogoImage() : null, _jsx(Typography, { id: "nav-bar-brand", sx: {
|
|
103
105
|
...MENU_ITEM_TEXT_PROPS,
|
|
104
106
|
marginLeft: "0.85rem",
|
|
105
107
|
fontSize: "16px",
|
|
@@ -125,13 +127,13 @@ export const Navbar = ({ authenticationType, id, logo, logoServiceToken, onStart
|
|
|
125
127
|
alignItems: "center",
|
|
126
128
|
}, onClick: (event) => {
|
|
127
129
|
setExploreMenuAnchorEl(event.currentTarget);
|
|
128
|
-
}, children: ["Explore", _jsx(ArrowDropDownIcon, { id: "nav-explore-dropdown-arrow", sx: { color: primary || "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "explore-menu", anchorEl: exploreMenuAnchorEl, open: exploreMenuOpen, onClose: handleCloseExploreMenu, children: [_jsx(MenuItem, { id: "explore-neuro-san-studio", component: "a", href: "https://github.com/cognizant-ai-lab/neuro-san-studio",
|
|
130
|
+
}, children: ["Explore", _jsx(ArrowDropDownIcon, { id: "nav-explore-dropdown-arrow", sx: { color: primary || "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "explore-menu", anchorEl: exploreMenuAnchorEl, open: exploreMenuOpen, onClose: handleCloseExploreMenu, children: [_jsx(MenuItem, { id: "explore-neuro-san-studio", component: "a", href: "https://github.com/cognizant-ai-lab/neuro-san-studio", rel: "noopener noreferrer", sx: { ...DISABLE_OUTLINE_PROPS }, target: "_blank", children: "Neuro-san studio (examples)" }, "explore-neuro-san-studio"), _jsx(MenuItem, { id: "explore-neuro-san", component: "a", href: "https://github.com/cognizant-ai-lab/neuro-san", rel: "noopener noreferrer", sx: { ...DISABLE_OUTLINE_PROPS }, target: "_blank", children: "Neuro-san (core)" }, "explore-neuro-san")] })] }), _jsxs(Grid, { id: "help-dropdown", sx: { cursor: "pointer", marginRight: "30px" }, children: [_jsxs(Typography, { id: "help-toggle", sx: {
|
|
129
131
|
...MENU_ITEM_TEXT_PROPS,
|
|
130
132
|
display: "flex",
|
|
131
133
|
alignItems: "center",
|
|
132
134
|
}, onClick: (event) => {
|
|
133
135
|
setHelpMenuAnchorEl(event.currentTarget);
|
|
134
|
-
}, children: ["Help", _jsx(ArrowDropDownIcon, { id: "nav-help-dropdown-arrow", sx: { color: primary || "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "help-menu", anchorEl: helpMenuAnchorEl, open: helpMenuOpen, onClose: handleCloseHelpMenu, children: [_jsx(MenuItem, { id: "user-guide", component: "a", href: "/
|
|
136
|
+
}, children: ["Help", _jsx(ArrowDropDownIcon, { id: "nav-help-dropdown-arrow", sx: { color: primary || "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "help-menu", anchorEl: helpMenuAnchorEl, open: helpMenuOpen, onClose: handleCloseHelpMenu, children: [_jsx(MenuItem, { id: "user-guide", component: "a", href: "/UserGuide", rel: "noopener noreferrer", sx: { ...DISABLE_OUTLINE_PROPS }, target: "_blank", children: "User guide" }, "user-guide"), _jsx(MenuItem, { id: "take-a-tour", onClick: () => {
|
|
135
137
|
handleCloseHelpMenu();
|
|
136
138
|
onStartTour?.();
|
|
137
139
|
}, sx: { ...DISABLE_OUTLINE_PROPS }, children: "Take a tour" }, "take-a-tour"), _jsx(MenuItem, { href: null, id: "contact-us-help", onClick: () => setEmailDialogOpen(true), children: "Contact Us" }, "contact-us-help")] })] }), emailDialogOpen ? (_jsx(ConfirmationModal, { id: "email-dialog", content: getContactUsConfirmationText(supportEmailAddress), handleCancel: () => {
|
|
@@ -163,5 +165,5 @@ export const Navbar = ({ authenticationType, id, logo, logoServiceToken, onStart
|
|
|
163
165
|
cursor: "pointer",
|
|
164
166
|
}, onClick: () => {
|
|
165
167
|
setSettingsDialogOpen(true);
|
|
166
|
-
} }) }))] }))
|
|
168
|
+
} }) }))] }));
|
|
167
169
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC, ReactElement } from "react";
|
|
2
|
+
type Status = "green" | "red" | "unknown";
|
|
3
|
+
interface StatusLightProps {
|
|
4
|
+
readonly id?: string;
|
|
5
|
+
readonly statusValue: Status;
|
|
6
|
+
readonly tooltip?: ReactElement;
|
|
7
|
+
}
|
|
8
|
+
export declare const StatusLight: FC<StatusLightProps>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import Box from "@mui/material/Box";
|
|
3
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
4
|
+
const statusToColor = (statusValue) => {
|
|
5
|
+
switch (statusValue) {
|
|
6
|
+
case "green":
|
|
7
|
+
return "success.main";
|
|
8
|
+
case "red":
|
|
9
|
+
return "error.main";
|
|
10
|
+
case "unknown":
|
|
11
|
+
default:
|
|
12
|
+
return "action.disabled";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const StatusLight = ({ id, statusValue, tooltip }) => (_jsx(Tooltip, { title: tooltip, placement: "top", children: _jsx(Box, { id: id, "data-testid": id, "data-status": statusValue, sx: {
|
|
16
|
+
backgroundColor: statusToColor(statusValue),
|
|
17
|
+
borderRadius: "50%",
|
|
18
|
+
display: "inline-block",
|
|
19
|
+
minWidth: "0.75rem",
|
|
20
|
+
minHeight: "0.75rem",
|
|
21
|
+
} }) }));
|
|
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import { Component } from "react";
|
|
18
|
-
import ErrorPage from "./ErrorPage.js";
|
|
18
|
+
import { default as ErrorPage } from "./ErrorPage.js";
|
|
19
19
|
/**
|
|
20
20
|
* Implements a system-wide error handler for Next.js pages in our app.
|
|
21
21
|
* Taken from here: https://nextjs.org/docs/advanced-features/error-handling
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FC } from "react";
|
|
2
2
|
interface ErrorPageProps {
|
|
3
3
|
id: string;
|
|
4
4
|
errorText: string;
|
|
@@ -8,5 +8,5 @@ interface ErrorPageProps {
|
|
|
8
8
|
* @param id HTML id for the <code>div</code> for this page
|
|
9
9
|
* @param errorText Error text to be displayed
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
export
|
|
11
|
+
declare const ErrorPage: FC<ErrorPageProps>;
|
|
12
|
+
export default ErrorPage;
|
|
@@ -28,9 +28,9 @@ import { Navbar } from "../Common/Navbar.js";
|
|
|
28
28
|
* @param id HTML id for the <code>div</code> for this page
|
|
29
29
|
* @param errorText Error text to be displayed
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
const ErrorPage = ({ id, errorText }) => {
|
|
32
32
|
const { auth0ClientId, auth0Domain, supportEmailAddress, logoServiceToken } = useEnvironmentStore();
|
|
33
|
-
// Access
|
|
33
|
+
// Access Next.js router
|
|
34
34
|
const router = useRouter();
|
|
35
35
|
// Access user info store
|
|
36
36
|
const { currentUser, setCurrentUser, setPicture, oidcProvider } = useUserInfoStore();
|
|
@@ -44,4 +44,5 @@ export default function ErrorPage({ id, errorText }) {
|
|
|
44
44
|
await smartSignOut(currentUser, auth0Domain, auth0ClientId, oidcProvider);
|
|
45
45
|
};
|
|
46
46
|
return (_jsxs(_Fragment, { children: [_jsx(Navbar, { authenticationType: authenticationType, id: "nav-bar", logo: LOGO, logoServiceToken: logoServiceToken, pathname: router.pathname, query: router.query, signOut: handleSignOut, supportEmailAddress: supportEmailAddress, userInfo: userInfo }), _jsxs(Box, { id: id, sx: { marginLeft: "1rem" }, children: [_jsx(NeuroAIBreadcrumbs, {}), _jsx("h4", { id: "error-header", style: { color: "var(--bs-red)", marginTop: "1rem" }, children: "Oops, an internal error occurred on our end." }), _jsxs("div", { id: "error-div-1", children: [_jsxs(Box, { id: "no-need-to-worry", sx: { marginBottom: "1.5rem" }, children: [_jsx("b", { id: "bold-1", children: "There's no need to worry \u2013 you didn't do anything wrong." }), " This is a bug in our server and we'll fix it as soon as possible."] }), _jsx(Box, { id: "try-these-steps", sx: { marginBottom: "1.5rem" }, children: "To attempt to recover from the error, try these steps:" }), _jsx(Box, { id: "refresh-page", sx: { marginBottom: "1.5rem" }, children: _jsxs("ul", { id: "error-boundary-advice-list", className: "list-decimal list-inside", children: [_jsx("li", { id: "error-advice-refresh", children: "Refresh the page to see if the error goes away." }), _jsx("li", { id: "error-advice-reload", children: "Close and re-open your browser, then navigate back to the page where you encountered the error." })] }) }), "If none of that helps, please report the following error to the LEAF team:"] }), _jsx("div", { id: "error-text-div", style: { fontFamily: "monospace", marginTop: "1.5rem", marginBottom: "1.5rem" }, children: errorText }), "More information may be available in the browser console. Please include such information in your report if possible."] }), _jsx(Footer, { supportEmailAddress: supportEmailAddress, logoLinkUrl: "https://www.cognizant.com/", logoUrl: "/cognizant-logo-white.svg" })] }));
|
|
47
|
-
}
|
|
47
|
+
};
|
|
48
|
+
export default ErrorPage;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the Cognizant logo with a link to the corporate website.
|
|
4
|
+
*/
|
|
5
|
+
export const getCognizantLogoImage = () => (_jsx("a", { id: "splash-logo-link", href: "https://www.cognizant.com/us/en", style: {
|
|
6
|
+
display: "flex",
|
|
7
|
+
paddingLeft: "0.15rem",
|
|
8
|
+
}, target: "_blank", rel: "noopener noreferrer", children: _jsx("img", { id: "logo-img", width: "200", height: "45", src: "/cognizant-logo-white.svg", alt: "Cognizant Logo" }) }));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvgIconProps } from "@mui/material/SvgIcon";
|
|
2
|
+
import { FC } from "react";
|
|
3
|
+
import { LogoSource } from "../../state/Settings.js";
|
|
4
|
+
interface CustomerLogoProps {
|
|
5
|
+
readonly customer: string;
|
|
6
|
+
readonly fallbackIcon?: FC<SvgIconProps>;
|
|
7
|
+
readonly iconSuggestion?: string;
|
|
8
|
+
readonly logoServiceToken?: string;
|
|
9
|
+
readonly logoSource: LogoSource;
|
|
10
|
+
}
|
|
11
|
+
export declare const LOGO_DEV_URL = "https://img.logo.dev/name";
|
|
12
|
+
/**
|
|
13
|
+
* Component to display the customer's logo based on the settings.
|
|
14
|
+
* @param customer - Name of the customer, used for fetching the logo from logo.dev when logoSource is "auto"
|
|
15
|
+
* @param fallbackIcon - Optional MUI icon to use as a fallback if other approaches fail
|
|
16
|
+
* @param iconSuggestion - Optional MUI icon name to use when logoSource is "generic"
|
|
17
|
+
* @param logoServiceToken - Optional token for fetching the logo from logo.dev
|
|
18
|
+
* @param logoSource - Source of the logo, determines how the logo is rendered ("none", "generic", or "auto")
|
|
19
|
+
* @returns JSX element representing the customer's logo, MUI icon, or Cognizant fallback, or null if no logo
|
|
20
|
+
* should be displayed or if the logo.dev token is missing/invalid.
|
|
21
|
+
*/
|
|
22
|
+
export declare const CustomerLogo: FC<CustomerLogoProps>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// Have to suppress this lint error to allow dynamic access of MUI icons
|
|
3
|
+
// eslint-disable-next-line no-restricted-imports
|
|
4
|
+
import * as MuiIcons from "@mui/icons-material";
|
|
5
|
+
//#endregion
|
|
6
|
+
export const LOGO_DEV_URL = "https://img.logo.dev/name";
|
|
7
|
+
/**
|
|
8
|
+
* Component to display the customer's logo based on the settings.
|
|
9
|
+
* @param customer - Name of the customer, used for fetching the logo from logo.dev when logoSource is "auto"
|
|
10
|
+
* @param fallbackIcon - Optional MUI icon to use as a fallback if other approaches fail
|
|
11
|
+
* @param iconSuggestion - Optional MUI icon name to use when logoSource is "generic"
|
|
12
|
+
* @param logoServiceToken - Optional token for fetching the logo from logo.dev
|
|
13
|
+
* @param logoSource - Source of the logo, determines how the logo is rendered ("none", "generic", or "auto")
|
|
14
|
+
* @returns JSX element representing the customer's logo, MUI icon, or Cognizant fallback, or null if no logo
|
|
15
|
+
* should be displayed or if the logo.dev token is missing/invalid.
|
|
16
|
+
*/
|
|
17
|
+
export const CustomerLogo = ({ customer, fallbackIcon: FallbackIcon, iconSuggestion, logoServiceToken, logoSource, }) => {
|
|
18
|
+
const hasCustomer = customer?.trim()?.length > 0;
|
|
19
|
+
const fallback = FallbackIcon ? _jsx(FallbackIcon, { sx: { fontSize: "2rem" } }) : null;
|
|
20
|
+
// "generic": check if suggested MUI icon is valid
|
|
21
|
+
switch (logoSource) {
|
|
22
|
+
case "generic": {
|
|
23
|
+
const MuiIcon = MuiIcons[iconSuggestion];
|
|
24
|
+
const LogoIcon = MuiIcon ?? FallbackIcon;
|
|
25
|
+
return LogoIcon ? _jsx(LogoIcon, { sx: { fontSize: "2rem" } }) : null;
|
|
26
|
+
}
|
|
27
|
+
case "auto": {
|
|
28
|
+
if (!hasCustomer || !logoServiceToken || logoServiceToken.trim().length === 0) {
|
|
29
|
+
return fallback;
|
|
30
|
+
}
|
|
31
|
+
// "auto": use logo.dev service
|
|
32
|
+
// eslint-disable-next-line max-len -- better to keep URL together
|
|
33
|
+
const logoUrl = `${LOGO_DEV_URL}/${encodeURIComponent(customer)}?token=${logoServiceToken}&theme=dark&format=png&size=75`;
|
|
34
|
+
return (_jsx("img", { src: logoUrl, alt: `${customer} Logo`, width: 40, height: 40, style: { borderRadius: "50%" } }));
|
|
35
|
+
}
|
|
36
|
+
case "none":
|
|
37
|
+
return null;
|
|
38
|
+
default:
|
|
39
|
+
return fallback;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
@@ -22,7 +22,6 @@ export const isFinalMessage = (chatMessage) => {
|
|
|
22
22
|
export const createConversation = (agents, text, type) => ({
|
|
23
23
|
// Could use crypto.randomUUID, but it's only available under HTTPS, and don't want to use a different
|
|
24
24
|
// solution for HTTP on localhost.
|
|
25
|
-
// eslint-disable-next-line newline-per-chained-call
|
|
26
25
|
id: `conv_${Date.now()}${Math.random().toString(36).slice(2, 10)}`,
|
|
27
26
|
agents: new Set(agents),
|
|
28
27
|
startedAt: new Date(),
|