@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.1.0 → 5.2.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/CHANGELOG.md +10 -0
- package/README.md +26 -3
- package/dist/alpha.d.ts +37 -0
- package/dist/api/LightspeedApiClient.esm.js +57 -0
- package/dist/api/LightspeedApiClient.esm.js.map +1 -1
- package/dist/api/api.esm.js.map +1 -1
- package/dist/components/DeleteModal.esm.js +2 -0
- package/dist/components/DeleteModal.esm.js.map +1 -1
- package/dist/components/DeleteSavedPromptModal.esm.js +75 -0
- package/dist/components/DeleteSavedPromptModal.esm.js.map +1 -0
- package/dist/components/LightSpeedChat.esm.js +202 -107
- package/dist/components/LightSpeedChat.esm.js.map +1 -1
- package/dist/components/LightspeedChatBoxHeader.esm.js +29 -2
- package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
- package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
- package/dist/components/McpServersSettings.esm.js +9 -22
- package/dist/components/McpServersSettings.esm.js.map +1 -1
- package/dist/components/SavedPromptCard.esm.js +100 -0
- package/dist/components/SavedPromptCard.esm.js.map +1 -0
- package/dist/components/SavedPromptKebabMenu.esm.js +87 -0
- package/dist/components/SavedPromptKebabMenu.esm.js.map +1 -0
- package/dist/components/SavedPromptMenuItems.esm.js +52 -0
- package/dist/components/SavedPromptMenuItems.esm.js.map +1 -0
- package/dist/components/SavedPromptsEmptyState.esm.js +63 -0
- package/dist/components/SavedPromptsEmptyState.esm.js.map +1 -0
- package/dist/components/SavedPromptsList.esm.js +63 -0
- package/dist/components/SavedPromptsList.esm.js.map +1 -0
- package/dist/components/SavedPromptsSettings.esm.js +285 -0
- package/dist/components/SavedPromptsSettings.esm.js.map +1 -0
- package/dist/components/SettingsPanel.esm.js +135 -0
- package/dist/components/SettingsPanel.esm.js.map +1 -0
- package/dist/hooks/useConversationHistoryGroups.esm.js +71 -0
- package/dist/hooks/useConversationHistoryGroups.esm.js.map +1 -0
- package/dist/hooks/useFeedbackActions.esm.js.map +1 -1
- package/dist/hooks/useLightspeedProviderState.esm.js +19 -5
- package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -1
- package/dist/hooks/useSavedPromptActions.esm.js +64 -0
- package/dist/hooks/useSavedPromptActions.esm.js.map +1 -0
- package/dist/hooks/useSavedPrompts.esm.js +75 -0
- package/dist/hooks/useSavedPrompts.esm.js.map +1 -0
- package/dist/hooks/useSavedPromptsSettings.esm.js +65 -0
- package/dist/hooks/useSavedPromptsSettings.esm.js.map +1 -0
- package/dist/hooks/useSettingsPanelUrlState.esm.js +95 -0
- package/dist/hooks/useSettingsPanelUrlState.esm.js.map +1 -0
- package/dist/hooks/useWelcomePrompts.esm.js +16 -5
- package/dist/hooks/useWelcomePrompts.esm.js.map +1 -1
- package/dist/translations/de.esm.js +40 -1
- package/dist/translations/de.esm.js.map +1 -1
- package/dist/translations/es.esm.js +40 -1
- package/dist/translations/es.esm.js.map +1 -1
- package/dist/translations/fr.esm.js +40 -1
- package/dist/translations/fr.esm.js.map +1 -1
- package/dist/translations/it.esm.js +40 -1
- package/dist/translations/it.esm.js.map +1 -1
- package/dist/translations/ja.esm.js +40 -1
- package/dist/translations/ja.esm.js.map +1 -1
- package/dist/translations/ref.esm.js +40 -2
- package/dist/translations/ref.esm.js.map +1 -1
- package/dist/utils/buildConversationHistoryGroups.esm.js +241 -0
- package/dist/utils/buildConversationHistoryGroups.esm.js.map +1 -0
- package/dist/utils/prompt-utils.esm.js +18 -1
- package/dist/utils/prompt-utils.esm.js.map +1 -1
- package/package.json +4 -14
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Title, Button } from '@patternfly/react-core';
|
|
3
|
+
import { TimesIcon } from '@patternfly/react-icons';
|
|
4
|
+
import { makeStyles } from 'tss-react/mui';
|
|
5
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
6
|
+
import { McpServersSettings } from './McpServersSettings.esm.js';
|
|
7
|
+
import { SavedPromptsSettings } from './SavedPromptsSettings.esm.js';
|
|
8
|
+
|
|
9
|
+
const useStyles = makeStyles()((theme) => ({
|
|
10
|
+
root: {
|
|
11
|
+
display: "flex",
|
|
12
|
+
flexDirection: "column",
|
|
13
|
+
height: "100%",
|
|
14
|
+
width: "100%",
|
|
15
|
+
overflow: "hidden",
|
|
16
|
+
backgroundColor: "var(--pf-t--global--background--color--floating--default)"
|
|
17
|
+
},
|
|
18
|
+
headerRow: {
|
|
19
|
+
display: "flex",
|
|
20
|
+
alignItems: "flex-start",
|
|
21
|
+
justifyContent: "space-between",
|
|
22
|
+
padding: `${theme.spacing(2)} ${theme.spacing(2)} ${theme.spacing(1)} ${theme.spacing(3)}`
|
|
23
|
+
},
|
|
24
|
+
tabBar: {
|
|
25
|
+
display: "flex",
|
|
26
|
+
padding: `0 ${theme.spacing(3)}`,
|
|
27
|
+
gap: theme.spacing(1),
|
|
28
|
+
borderBottom: "1px solid var(--pf-t--global--border--color--default)"
|
|
29
|
+
},
|
|
30
|
+
tabButton: {
|
|
31
|
+
background: "none",
|
|
32
|
+
border: "none",
|
|
33
|
+
padding: `${theme.spacing(1)} ${theme.spacing(2)}`,
|
|
34
|
+
fontSize: "0.875rem",
|
|
35
|
+
cursor: "pointer",
|
|
36
|
+
color: theme.palette.text.secondary,
|
|
37
|
+
borderBottom: "2px solid transparent",
|
|
38
|
+
transition: "color 0.15s, border-color 0.15s",
|
|
39
|
+
"&:hover": {
|
|
40
|
+
color: theme.palette.text.primary
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
tabButtonActive: {
|
|
44
|
+
color: theme.palette.text.primary,
|
|
45
|
+
fontWeight: 600,
|
|
46
|
+
borderBottom: `2px solid var(--pf-t--global--color--brand--default, ${theme.palette.primary.main}) !important`,
|
|
47
|
+
borderRadius: "0 !important"
|
|
48
|
+
},
|
|
49
|
+
tabContent: {
|
|
50
|
+
flex: 1,
|
|
51
|
+
minHeight: 0,
|
|
52
|
+
overflow: "auto"
|
|
53
|
+
}
|
|
54
|
+
}));
|
|
55
|
+
const SettingsPanel = ({
|
|
56
|
+
activeTab,
|
|
57
|
+
onTabChange,
|
|
58
|
+
onClose,
|
|
59
|
+
backgroundColor,
|
|
60
|
+
isSavedPromptsEnabled,
|
|
61
|
+
onEnableSavedPrompts,
|
|
62
|
+
onApplySavedPromptToInput,
|
|
63
|
+
onSendSavedPromptDirectly,
|
|
64
|
+
isChatStreaming = false,
|
|
65
|
+
savedPrompts,
|
|
66
|
+
savedPromptsConfig,
|
|
67
|
+
savedPromptsLoading,
|
|
68
|
+
savedPromptsError,
|
|
69
|
+
onCreateSavedPrompt,
|
|
70
|
+
onRequestSavedPromptDelete,
|
|
71
|
+
showMcpSettings = true
|
|
72
|
+
}) => {
|
|
73
|
+
const { t } = useTranslation();
|
|
74
|
+
const { classes } = useStyles();
|
|
75
|
+
const showMcpTab = showMcpSettings;
|
|
76
|
+
const showSavedPromptsTab = true;
|
|
77
|
+
const showTabBar = showMcpTab && showSavedPromptsTab;
|
|
78
|
+
const effectiveTab = showMcpTab ? activeTab : "saved-prompts";
|
|
79
|
+
return /* @__PURE__ */ jsxs("div", { className: classes.root, children: [
|
|
80
|
+
/* @__PURE__ */ jsxs("div", { className: classes.headerRow, children: [
|
|
81
|
+
/* @__PURE__ */ jsx(Title, { headingLevel: "h2", size: "xl", children: t("settings.panel.title") }),
|
|
82
|
+
/* @__PURE__ */ jsx(
|
|
83
|
+
Button,
|
|
84
|
+
{
|
|
85
|
+
"aria-label": t("mcp.settings.closeAriaLabel"),
|
|
86
|
+
icon: /* @__PURE__ */ jsx(TimesIcon, {}),
|
|
87
|
+
variant: "plain",
|
|
88
|
+
onClick: onClose
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
] }),
|
|
92
|
+
showTabBar && /* @__PURE__ */ jsxs("div", { className: classes.tabBar, children: [
|
|
93
|
+
showMcpTab && /* @__PURE__ */ jsx(
|
|
94
|
+
Button,
|
|
95
|
+
{
|
|
96
|
+
variant: "plain",
|
|
97
|
+
className: `${classes.tabButton} ${effectiveTab === "mcp-servers" ? classes.tabButtonActive : ""}`,
|
|
98
|
+
onClick: () => onTabChange("mcp-servers"),
|
|
99
|
+
children: t("mcp.settings.title")
|
|
100
|
+
}
|
|
101
|
+
),
|
|
102
|
+
/* @__PURE__ */ jsx(
|
|
103
|
+
Button,
|
|
104
|
+
{
|
|
105
|
+
variant: "plain",
|
|
106
|
+
className: `${classes.tabButton} ${effectiveTab === "saved-prompts" ? classes.tabButtonActive : ""}`,
|
|
107
|
+
onClick: () => onTabChange("saved-prompts"),
|
|
108
|
+
children: t("savedPrompts.tab.title")
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ jsxs("div", { className: classes.tabContent, children: [
|
|
113
|
+
effectiveTab === "mcp-servers" && showMcpTab && /* @__PURE__ */ jsx(McpServersSettings, { backgroundColor }),
|
|
114
|
+
effectiveTab === "saved-prompts" && /* @__PURE__ */ jsx(
|
|
115
|
+
SavedPromptsSettings,
|
|
116
|
+
{
|
|
117
|
+
isSavedPromptsEnabled,
|
|
118
|
+
onEnableSavedPrompts,
|
|
119
|
+
onApplyToInput: onApplySavedPromptToInput,
|
|
120
|
+
onSendDirectly: onSendSavedPromptDirectly,
|
|
121
|
+
isChatStreaming,
|
|
122
|
+
savedPrompts,
|
|
123
|
+
savedPromptsConfig,
|
|
124
|
+
savedPromptsLoading,
|
|
125
|
+
savedPromptsError,
|
|
126
|
+
onCreateSavedPrompt,
|
|
127
|
+
onRequestDelete: onRequestSavedPromptDelete
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
] })
|
|
131
|
+
] });
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export { SettingsPanel };
|
|
135
|
+
//# sourceMappingURL=SettingsPanel.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsPanel.esm.js","sources":["../../src/components/SettingsPanel.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Button, Title } from '@patternfly/react-core';\nimport { TimesIcon } from '@patternfly/react-icons';\nimport { makeStyles } from 'tss-react/mui';\n\nimport {\n SavedPrompt,\n SavedPromptsConfig,\n} from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport type { SettingsTab } from '../hooks/useSettingsPanelUrlState';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { McpServersSettings } from './McpServersSettings';\nimport { SavedPromptsSettings } from './SavedPromptsSettings';\n\nexport type { SettingsTab };\n\ntype SettingsPanelProps = {\n activeTab: SettingsTab;\n onTabChange: (tab: SettingsTab) => void;\n onClose: () => void;\n backgroundColor?: string;\n isSavedPromptsEnabled: boolean;\n onEnableSavedPrompts: () => void;\n onApplySavedPromptToInput: (content: string) => void;\n onSendSavedPromptDirectly: (content: string) => void;\n isChatStreaming?: boolean;\n savedPrompts?: SavedPrompt[];\n savedPromptsConfig?: SavedPromptsConfig;\n savedPromptsLoading?: boolean;\n savedPromptsError?: string | null;\n onCreateSavedPrompt?: (name: string, content: string) => Promise<void>;\n onRequestSavedPromptDelete?: (prompt: SavedPrompt) => void;\n /** When false, hides the MCP tab and shows saved prompts only. */\n showMcpSettings?: boolean;\n};\n\nconst useStyles = makeStyles()(theme => ({\n root: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n width: '100%',\n overflow: 'hidden',\n backgroundColor:\n 'var(--pf-t--global--background--color--floating--default)',\n },\n headerRow: {\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n padding: `${theme.spacing(2)} ${theme.spacing(2)} ${theme.spacing(1)} ${theme.spacing(3)}`,\n },\n tabBar: {\n display: 'flex',\n padding: `0 ${theme.spacing(3)}`,\n gap: theme.spacing(1),\n borderBottom: '1px solid var(--pf-t--global--border--color--default)',\n },\n tabButton: {\n background: 'none',\n border: 'none',\n padding: `${theme.spacing(1)} ${theme.spacing(2)}`,\n fontSize: '0.875rem',\n cursor: 'pointer',\n color: theme.palette.text.secondary,\n borderBottom: '2px solid transparent',\n transition: 'color 0.15s, border-color 0.15s',\n '&:hover': {\n color: theme.palette.text.primary,\n },\n },\n tabButtonActive: {\n color: theme.palette.text.primary,\n fontWeight: 600,\n borderBottom: `2px solid var(--pf-t--global--color--brand--default, ${theme.palette.primary.main}) !important`,\n borderRadius: '0 !important',\n },\n tabContent: {\n flex: 1,\n minHeight: 0,\n overflow: 'auto',\n },\n}));\n\nexport const SettingsPanel = ({\n activeTab,\n onTabChange,\n onClose,\n backgroundColor,\n isSavedPromptsEnabled,\n onEnableSavedPrompts,\n onApplySavedPromptToInput,\n onSendSavedPromptDirectly,\n isChatStreaming = false,\n savedPrompts,\n savedPromptsConfig,\n savedPromptsLoading,\n savedPromptsError,\n onCreateSavedPrompt,\n onRequestSavedPromptDelete,\n showMcpSettings = true,\n}: SettingsPanelProps) => {\n const { t } = useTranslation();\n const { classes } = useStyles();\n const showMcpTab = showMcpSettings;\n const showSavedPromptsTab = true;\n const showTabBar = showMcpTab && showSavedPromptsTab;\n const effectiveTab = showMcpTab ? activeTab : 'saved-prompts';\n\n return (\n <div className={classes.root}>\n <div className={classes.headerRow}>\n <Title headingLevel=\"h2\" size=\"xl\">\n {t('settings.panel.title')}\n </Title>\n <Button\n aria-label={t('mcp.settings.closeAriaLabel')}\n icon={<TimesIcon />}\n variant=\"plain\"\n onClick={onClose}\n />\n </div>\n\n {showTabBar && (\n <div className={classes.tabBar}>\n {showMcpTab && (\n <Button\n variant=\"plain\"\n className={`${classes.tabButton} ${effectiveTab === 'mcp-servers' ? classes.tabButtonActive : ''}`}\n onClick={() => onTabChange('mcp-servers')}\n >\n {t('mcp.settings.title')}\n </Button>\n )}\n {showSavedPromptsTab && (\n <Button\n variant=\"plain\"\n className={`${classes.tabButton} ${effectiveTab === 'saved-prompts' ? classes.tabButtonActive : ''}`}\n onClick={() => onTabChange('saved-prompts')}\n >\n {t('savedPrompts.tab.title')}\n </Button>\n )}\n </div>\n )}\n\n <div className={classes.tabContent}>\n {effectiveTab === 'mcp-servers' && showMcpTab && (\n <McpServersSettings backgroundColor={backgroundColor} />\n )}\n {effectiveTab === 'saved-prompts' && (\n <SavedPromptsSettings\n isSavedPromptsEnabled={isSavedPromptsEnabled}\n onEnableSavedPrompts={onEnableSavedPrompts}\n onApplyToInput={onApplySavedPromptToInput}\n onSendDirectly={onSendSavedPromptDirectly}\n isChatStreaming={isChatStreaming}\n savedPrompts={savedPrompts}\n savedPromptsConfig={savedPromptsConfig}\n savedPromptsLoading={savedPromptsLoading}\n savedPromptsError={savedPromptsError}\n onCreateSavedPrompt={onCreateSavedPrompt}\n onRequestDelete={onRequestSavedPromptDelete}\n />\n )}\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import { buildConversationHistoryGroups } from '../utils/buildConversationHistoryGroups.esm.js';
|
|
3
|
+
import { useTranslation } from './useTranslation.esm.js';
|
|
4
|
+
|
|
5
|
+
const useConversationHistoryGroups = ({
|
|
6
|
+
savedPrompts,
|
|
7
|
+
categorizedMessages,
|
|
8
|
+
filterValue,
|
|
9
|
+
isSavedPromptsEnabled,
|
|
10
|
+
isPinningChatsEnabled,
|
|
11
|
+
isSettingsOpen,
|
|
12
|
+
activeSettingsTab,
|
|
13
|
+
openSettings,
|
|
14
|
+
getSavedPromptMenuItems
|
|
15
|
+
}) => {
|
|
16
|
+
const { t } = useTranslation();
|
|
17
|
+
const [savedPromptsExpanded, setSavedPromptsExpanded] = useState(true);
|
|
18
|
+
const [pinnedExpanded, setPinnedExpanded] = useState(true);
|
|
19
|
+
const [chatsExpanded, setChatsExpanded] = useState(true);
|
|
20
|
+
const [savedPromptsShowAllExpanded, setSavedPromptsShowAllExpanded] = useState(false);
|
|
21
|
+
const handleOpenSavedPromptsSettings = useCallback(() => {
|
|
22
|
+
if (isSettingsOpen && activeSettingsTab === "saved-prompts") {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
openSettings("saved-prompts");
|
|
26
|
+
}, [activeSettingsTab, isSettingsOpen, openSettings]);
|
|
27
|
+
const { groups: conversationGroups, hasNoSearchResults } = useMemo(
|
|
28
|
+
() => buildConversationHistoryGroups({
|
|
29
|
+
savedPrompts,
|
|
30
|
+
categorizedMessages,
|
|
31
|
+
filterValue,
|
|
32
|
+
isSavedPromptsEnabled,
|
|
33
|
+
isPinningChatsEnabled,
|
|
34
|
+
sectionState: {
|
|
35
|
+
savedPromptsExpanded,
|
|
36
|
+
pinnedExpanded,
|
|
37
|
+
chatsExpanded,
|
|
38
|
+
savedPromptsShowAllExpanded
|
|
39
|
+
},
|
|
40
|
+
onSavedPromptsExpandedChange: setSavedPromptsExpanded,
|
|
41
|
+
onPinnedExpandedChange: setPinnedExpanded,
|
|
42
|
+
onChatsExpandedChange: setChatsExpanded,
|
|
43
|
+
onSavedPromptsShowAllChange: setSavedPromptsShowAllExpanded,
|
|
44
|
+
onOpenSavedPromptsSettings: handleOpenSavedPromptsSettings,
|
|
45
|
+
getSavedPromptMenuItems,
|
|
46
|
+
t
|
|
47
|
+
}),
|
|
48
|
+
[
|
|
49
|
+
savedPrompts,
|
|
50
|
+
categorizedMessages,
|
|
51
|
+
filterValue,
|
|
52
|
+
isSavedPromptsEnabled,
|
|
53
|
+
isPinningChatsEnabled,
|
|
54
|
+
savedPromptsExpanded,
|
|
55
|
+
pinnedExpanded,
|
|
56
|
+
chatsExpanded,
|
|
57
|
+
savedPromptsShowAllExpanded,
|
|
58
|
+
handleOpenSavedPromptsSettings,
|
|
59
|
+
getSavedPromptMenuItems,
|
|
60
|
+
t
|
|
61
|
+
]
|
|
62
|
+
);
|
|
63
|
+
return {
|
|
64
|
+
conversationGroups,
|
|
65
|
+
hasNoSearchResults,
|
|
66
|
+
handleOpenSavedPromptsSettings
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { useConversationHistoryGroups };
|
|
71
|
+
//# sourceMappingURL=useConversationHistoryGroups.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useConversationHistoryGroups.esm.js","sources":["../../src/hooks/useConversationHistoryGroups.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ReactNode, useCallback, useMemo, useState } from 'react';\n\nimport { Conversation } from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { buildConversationHistoryGroups } from '../utils/buildConversationHistoryGroups';\nimport { SettingsTab } from './useSettingsPanelUrlState';\nimport { useTranslation } from './useTranslation';\n\ntype UseConversationHistoryGroupsOptions = {\n savedPrompts: SavedPrompt[];\n categorizedMessages: { [key: string]: Conversation[] };\n filterValue: string;\n isSavedPromptsEnabled: boolean;\n isPinningChatsEnabled: boolean;\n isSettingsOpen: boolean;\n activeSettingsTab: SettingsTab;\n openSettings: (tab: SettingsTab) => void;\n getSavedPromptMenuItems: (prompt: SavedPrompt) => ReactNode;\n};\n\nexport const useConversationHistoryGroups = ({\n savedPrompts,\n categorizedMessages,\n filterValue,\n isSavedPromptsEnabled,\n isPinningChatsEnabled,\n isSettingsOpen,\n activeSettingsTab,\n openSettings,\n getSavedPromptMenuItems,\n}: UseConversationHistoryGroupsOptions) => {\n const { t } = useTranslation();\n\n const [savedPromptsExpanded, setSavedPromptsExpanded] = useState(true);\n const [pinnedExpanded, setPinnedExpanded] = useState(true);\n const [chatsExpanded, setChatsExpanded] = useState(true);\n const [savedPromptsShowAllExpanded, setSavedPromptsShowAllExpanded] =\n useState(false);\n\n const handleOpenSavedPromptsSettings = useCallback(() => {\n if (isSettingsOpen && activeSettingsTab === 'saved-prompts') {\n return;\n }\n openSettings('saved-prompts');\n }, [activeSettingsTab, isSettingsOpen, openSettings]);\n\n const { groups: conversationGroups, hasNoSearchResults } = useMemo(\n () =>\n buildConversationHistoryGroups({\n savedPrompts,\n categorizedMessages,\n filterValue,\n isSavedPromptsEnabled,\n isPinningChatsEnabled,\n sectionState: {\n savedPromptsExpanded,\n pinnedExpanded,\n chatsExpanded,\n savedPromptsShowAllExpanded,\n },\n onSavedPromptsExpandedChange: setSavedPromptsExpanded,\n onPinnedExpandedChange: setPinnedExpanded,\n onChatsExpandedChange: setChatsExpanded,\n onSavedPromptsShowAllChange: setSavedPromptsShowAllExpanded,\n onOpenSavedPromptsSettings: handleOpenSavedPromptsSettings,\n getSavedPromptMenuItems,\n t,\n }),\n [\n savedPrompts,\n categorizedMessages,\n filterValue,\n isSavedPromptsEnabled,\n isPinningChatsEnabled,\n savedPromptsExpanded,\n pinnedExpanded,\n chatsExpanded,\n savedPromptsShowAllExpanded,\n handleOpenSavedPromptsSettings,\n getSavedPromptMenuItems,\n t,\n ],\n );\n\n return {\n conversationGroups,\n hasNoSearchResults,\n handleOpenSavedPromptsSettings,\n };\n};\n"],"names":[],"mappings":";;;;AAqCO,MAAM,+BAA+B,CAAC;AAAA,EAC3C,YAAA;AAAA,EACA,mBAAA;AAAA,EACA,WAAA;AAAA,EACA,qBAAA;AAAA,EACA,qBAAA;AAAA,EACA,cAAA;AAAA,EACA,iBAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,KAA2C;AACzC,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,MAAM,CAAC,oBAAA,EAAsB,uBAAuB,CAAA,GAAI,SAAS,IAAI,CAAA;AACrE,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,SAAS,IAAI,CAAA;AACzD,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,IAAI,CAAA;AACvD,EAAA,MAAM,CAAC,2BAAA,EAA6B,8BAA8B,CAAA,GAChE,SAAS,KAAK,CAAA;AAEhB,EAAA,MAAM,8BAAA,GAAiC,YAAY,MAAM;AACvD,IAAA,IAAI,cAAA,IAAkB,sBAAsB,eAAA,EAAiB;AAC3D,MAAA;AAAA,IACF;AACA,IAAA,YAAA,CAAa,eAAe,CAAA;AAAA,EAC9B,CAAA,EAAG,CAAC,iBAAA,EAAmB,cAAA,EAAgB,YAAY,CAAC,CAAA;AAEpD,EAAA,MAAM,EAAE,MAAA,EAAQ,kBAAA,EAAoB,kBAAA,EAAmB,GAAI,OAAA;AAAA,IACzD,MACE,8BAAA,CAA+B;AAAA,MAC7B,YAAA;AAAA,MACA,mBAAA;AAAA,MACA,WAAA;AAAA,MACA,qBAAA;AAAA,MACA,qBAAA;AAAA,MACA,YAAA,EAAc;AAAA,QACZ,oBAAA;AAAA,QACA,cAAA;AAAA,QACA,aAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,4BAAA,EAA8B,uBAAA;AAAA,MAC9B,sBAAA,EAAwB,iBAAA;AAAA,MACxB,qBAAA,EAAuB,gBAAA;AAAA,MACvB,2BAAA,EAA6B,8BAAA;AAAA,MAC7B,0BAAA,EAA4B,8BAAA;AAAA,MAC5B,uBAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,IACH;AAAA,MACE,YAAA;AAAA,MACA,mBAAA;AAAA,MACA,WAAA;AAAA,MACA,qBAAA;AAAA,MACA,qBAAA;AAAA,MACA,oBAAA;AAAA,MACA,cAAA;AAAA,MACA,aAAA;AAAA,MACA,2BAAA;AAAA,MACA,8BAAA;AAAA,MACA,uBAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,OAAO;AAAA,IACL,kBAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFeedbackActions.esm.js","sources":["../../src/hooks/useFeedbackActions.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\n\nimport {\n MessageProps,\n UserFeedbackCompleteProps,\n UserFeedbackProps,\n} from '@patternfly/chatbot';\n\nimport { useCaptureFeedback } from '../hooks/useCaptureFeedback';\nimport { CaptureFeedback } from '../types';\nimport { Sentiment, useFeedbackState } from './useFeedbackState';\nimport { useFeedbackStatus } from './useFeedbackStatus';\nimport { useTranslation } from './useTranslation';\n\nexport const useFeedbackActions = <T extends MessageProps>(\n messages: T[],\n conversationId: string,\n isStreaming: boolean,\n): T[] => {\n const copyButtonRef = useRef<HTMLButtonElement>(null);\n const speakingButtonRef = useRef<HTMLButtonElement>(null);\n const currentSpeakingIdRef = useRef<string | null>(null);\n\n const { data: feedbackEnabled } = useFeedbackStatus();\n const { state, ...dispatch } = useFeedbackState();\n const { mutateAsync: captureFeedback } = useCaptureFeedback();\n const { t } = useTranslation();\n\n const createQuickResponses = useMemo(\n () => ({\n positive: [\n { id: '1', content: t('feedback.quickResponses.positive.helpful') },\n {\n id: '2',\n content: t('feedback.quickResponses.positive.easyToUnderstand'),\n },\n {\n id: '3',\n content: t('feedback.quickResponses.positive.resolvedIssue'),\n },\n ],\n negative: [\n { id: '1', content: t('feedback.quickResponses.negative.didntAnswer') },\n {\n id: '2',\n content: t('feedback.quickResponses.negative.hardToUnderstand'),\n },\n { id: '3', content: t('feedback.quickResponses.negative.notHelpful') },\n ],\n }),\n [t],\n );\n\n const getFeedbackForm = useCallback(\n (messageId: string, sentiment: 'positive' | 'negative') => ({\n key: `feedback-${sentiment}`,\n id: `feedback-${sentiment}-${messageId}`,\n hasTextArea: true,\n title: t('feedback.form.title'),\n textAreaPlaceholder: t('feedback.form.textAreaPlaceholder'),\n submitWord: t('feedback.form.submitWord'),\n quickResponses: createQuickResponses[sentiment],\n onSubmit: (\n quickResponse: string | undefined = '0',\n additionalFeedback: string | undefined,\n ) => {\n const quickIndex = Number(quickResponse) - 1;\n const quickText =\n quickResponse !== '0'\n ? createQuickResponses[sentiment]?.[quickIndex]?.content\n : undefined;\n\n let user_feedback = '';\n\n if (quickText && additionalFeedback) {\n user_feedback = `${quickText}\\nAdditional feedback: ${additionalFeedback}`;\n } else if (quickText) {\n user_feedback = quickText;\n } else if (additionalFeedback) {\n user_feedback = additionalFeedback;\n }\n\n const botAnswerId = Number(messageId.split('-').pop());\n const userQuestionId = botAnswerId - 1;\n\n const payload: CaptureFeedback = {\n conversation_id: conversationId,\n user_feedback,\n sentiment: sentiment === 'positive' ? 1 : -1,\n user_question: messages[userQuestionId].content || '',\n llm_response: messages[botAnswerId].content || '',\n };\n\n captureFeedback(payload).then(() => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.showCompletionForm(messageId, sentiment);\n dispatch.updateButtonState(messageId, {\n sentiment: sentiment,\n feedbackSubmitted: true,\n });\n\n setTimeout(() => {\n dispatch.hideCompletionForm(messageId, sentiment);\n }, 1000);\n });\n },\n\n // eslint-disable-next-line no-console\n onClose: () => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n dispatch.updateButtonState(messageId, { sentiment: undefined });\n },\n focusOnLoad: true,\n }),\n [\n captureFeedback,\n conversationId,\n dispatch,\n messages,\n createQuickResponses,\n t,\n ],\n );\n\n const feedbackForms = useCallback(\n (messageId: string): { [key in Sentiment]: UserFeedbackProps } => ({\n positive: getFeedbackForm(messageId, 'positive'),\n negative: getFeedbackForm(messageId, 'negative'),\n }),\n [getFeedbackForm],\n );\n\n const getUserFeedbackComplete = useCallback(\n (\n messageId: string,\n sentiment: Sentiment,\n ): UserFeedbackCompleteProps | undefined => {\n const isVisible = state[messageId]?.completionForm?.[sentiment];\n if (!isVisible) return undefined;\n\n return {\n id: `feebback-completion-${sentiment}-${messageId}`,\n title: t('feedback.completion.title'),\n body: t('feedback.completion.body'),\n onClose: () => {\n dispatch.hideCompletionForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n },\n };\n },\n [state, dispatch, t],\n );\n\n const scrollToFeedbackForm = useCallback(\n (messageId: string, sentiment: Sentiment) => {\n setTimeout(() => {\n const el = document.getElementById(\n `feedback-${sentiment}-${messageId}`,\n );\n if (el) {\n el.scrollIntoView({ behavior: 'auto', block: 'start' });\n el.focus();\n }\n }, 0);\n },\n [],\n );\n\n const speakMessage = useCallback(\n (messageId: string, content: string) => {\n if (window.speechSynthesis.speaking || window.speechSynthesis.pending) {\n window.speechSynthesis.cancel();\n\n if (\n currentSpeakingIdRef.current &&\n currentSpeakingIdRef.current !== messageId\n ) {\n dispatch.updateButtonState(currentSpeakingIdRef.current, {\n isSpeaking: false,\n });\n }\n }\n\n // Track the current SpeakingId\n currentSpeakingIdRef.current = messageId;\n\n const utterance = new SpeechSynthesisUtterance(content);\n\n utterance.onstart = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: true });\n };\n\n utterance.onend = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n utterance.onerror = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n window.speechSynthesis.speak(utterance);\n },\n [dispatch],\n );\n\n const cancelSpeaking = useCallback(\n (messageId?: string) => {\n window.speechSynthesis.cancel();\n\n currentSpeakingIdRef.current = null;\n\n if (messageId) {\n // Cancel just this one message\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n } else {\n // Cancel all messages\n Object.keys(state).forEach(id => {\n if (state[id].buttonState?.isSpeaking) {\n dispatch.updateButtonState(id, { isSpeaking: false });\n }\n });\n }\n setTimeout(() => {\n const el = document.getElementById(`listen-${messageId}`);\n if (el) {\n el.blur();\n }\n }, 10);\n },\n [state, dispatch],\n );\n\n useEffect(() => {\n return () => {\n // Stop any ongoing speech when component unmounts\n cancelSpeaking();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversationId]);\n\n return useMemo(() => {\n return feedbackEnabled\n ? messages.map((message, index) => {\n if (\n message.role === 'user' ||\n (isStreaming && messages.length - 1 === index)\n )\n return message;\n\n const messageId = `${conversationId}-${message.role}-${index}`;\n const { sentiment, copied, isSpeaking } =\n state[messageId]?.buttonState || {};\n const showFeedbackForm = state[messageId]?.feedbackForm?.[sentiment];\n const userFeedbackForm =\n showFeedbackForm && feedbackForms(messageId)[sentiment];\n\n const userFeedbackComplete = getUserFeedbackComplete(\n messageId,\n sentiment,\n );\n\n const createSentimentAction = (selected: Sentiment) => ({\n isClicked: sentiment === selected,\n onClick: () => {\n if (sentiment !== selected) {\n dispatch.toggleFeedbackForm(messageId, selected);\n dispatch.updateButtonState(messageId, { sentiment: selected });\n scrollToFeedbackForm(messageId, sentiment);\n }\n },\n tooltipContent:\n selected === 'positive'\n ? t('feedback.tooltips.goodResponse')\n : t('feedback.tooltips.badResponse'),\n 'aria-expanded': sentiment === selected,\n 'aria-controls': showFeedbackForm\n ? `feedback-${sentiment}-${messageId}`\n : `feebback-completion-${sentiment}-${messageId}`,\n });\n\n const copyAction = {\n isClicked: copied,\n ref: copyButtonRef,\n tooltipContent: copied\n ? t('feedback.tooltips.copied')\n : t('feedback.tooltips.copy'),\n onClick: async () => {\n await window.navigator.clipboard.writeText(\n message.content as string,\n );\n dispatch.updateButtonState(messageId, {\n copied: true,\n });\n\n setTimeout(() => {\n dispatch.updateButtonState(messageId, { copied: false });\n copyButtonRef?.current?.blur();\n }, 1000);\n },\n };\n\n const listenAction = {\n isClicked: isSpeaking,\n ref: speakingButtonRef,\n id: `listen-${messageId}`,\n tooltipContent: isSpeaking\n ? t('feedback.tooltips.listening')\n : t('feedback.tooltips.listen'),\n onClick: () => {\n const isCurrentlySpeaking =\n state[messageId]?.buttonState?.isSpeaking;\n\n if (isCurrentlySpeaking) {\n // Stop if it's already speaking this message\n cancelSpeaking(messageId);\n } else {\n cancelSpeaking();\n speakMessage(messageId, message.content as string);\n }\n },\n };\n\n return {\n ...message,\n userFeedbackForm,\n userFeedbackComplete,\n actions: {\n positive: createSentimentAction('positive'),\n negative: createSentimentAction('negative'),\n copy: copyAction,\n listen: listenAction,\n },\n };\n })\n : messages;\n }, [\n t,\n conversationId,\n messages,\n state,\n dispatch,\n isStreaming,\n speakMessage,\n feedbackForms,\n cancelSpeaking,\n feedbackEnabled,\n getUserFeedbackComplete,\n scrollToFeedbackForm,\n ]);\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useFeedbackActions.esm.js","sources":["../../src/hooks/useFeedbackActions.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\n\nimport { MessageProps } from '@patternfly/chatbot';\n\nimport { useCaptureFeedback } from '../hooks/useCaptureFeedback';\nimport { CaptureFeedback } from '../types';\nimport {\n UserFeedbackCompleteProps,\n UserFeedbackProps,\n} from '../types/patternfly-chatbot-feedback';\nimport { Sentiment, useFeedbackState } from './useFeedbackState';\nimport { useFeedbackStatus } from './useFeedbackStatus';\nimport { useTranslation } from './useTranslation';\n\nexport const useFeedbackActions = <T extends MessageProps>(\n messages: T[],\n conversationId: string,\n isStreaming: boolean,\n): T[] => {\n const copyButtonRef = useRef<HTMLButtonElement>(null);\n const speakingButtonRef = useRef<HTMLButtonElement>(null);\n const currentSpeakingIdRef = useRef<string | null>(null);\n\n const { data: feedbackEnabled } = useFeedbackStatus();\n const { state, ...dispatch } = useFeedbackState();\n const { mutateAsync: captureFeedback } = useCaptureFeedback();\n const { t } = useTranslation();\n\n const createQuickResponses = useMemo(\n () => ({\n positive: [\n { id: '1', content: t('feedback.quickResponses.positive.helpful') },\n {\n id: '2',\n content: t('feedback.quickResponses.positive.easyToUnderstand'),\n },\n {\n id: '3',\n content: t('feedback.quickResponses.positive.resolvedIssue'),\n },\n ],\n negative: [\n { id: '1', content: t('feedback.quickResponses.negative.didntAnswer') },\n {\n id: '2',\n content: t('feedback.quickResponses.negative.hardToUnderstand'),\n },\n { id: '3', content: t('feedback.quickResponses.negative.notHelpful') },\n ],\n }),\n [t],\n );\n\n const getFeedbackForm = useCallback(\n (messageId: string, sentiment: 'positive' | 'negative') => ({\n key: `feedback-${sentiment}`,\n id: `feedback-${sentiment}-${messageId}`,\n hasTextArea: true,\n title: t('feedback.form.title'),\n textAreaPlaceholder: t('feedback.form.textAreaPlaceholder'),\n submitWord: t('feedback.form.submitWord'),\n quickResponses: createQuickResponses[sentiment],\n onSubmit: (\n quickResponse: string | undefined = '0',\n additionalFeedback: string | undefined,\n ) => {\n const quickIndex = Number(quickResponse) - 1;\n const quickText =\n quickResponse !== '0'\n ? createQuickResponses[sentiment]?.[quickIndex]?.content\n : undefined;\n\n let user_feedback = '';\n\n if (quickText && additionalFeedback) {\n user_feedback = `${quickText}\\nAdditional feedback: ${additionalFeedback}`;\n } else if (quickText) {\n user_feedback = quickText;\n } else if (additionalFeedback) {\n user_feedback = additionalFeedback;\n }\n\n const botAnswerId = Number(messageId.split('-').pop());\n const userQuestionId = botAnswerId - 1;\n\n const payload: CaptureFeedback = {\n conversation_id: conversationId,\n user_feedback,\n sentiment: sentiment === 'positive' ? 1 : -1,\n user_question: messages[userQuestionId].content || '',\n llm_response: messages[botAnswerId].content || '',\n };\n\n captureFeedback(payload).then(() => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.showCompletionForm(messageId, sentiment);\n dispatch.updateButtonState(messageId, {\n sentiment: sentiment,\n feedbackSubmitted: true,\n });\n\n setTimeout(() => {\n dispatch.hideCompletionForm(messageId, sentiment);\n }, 1000);\n });\n },\n\n // eslint-disable-next-line no-console\n onClose: () => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n dispatch.updateButtonState(messageId, { sentiment: undefined });\n },\n focusOnLoad: true,\n }),\n [\n captureFeedback,\n conversationId,\n dispatch,\n messages,\n createQuickResponses,\n t,\n ],\n );\n\n const feedbackForms = useCallback(\n (messageId: string): { [key in Sentiment]: UserFeedbackProps } => ({\n positive: getFeedbackForm(messageId, 'positive'),\n negative: getFeedbackForm(messageId, 'negative'),\n }),\n [getFeedbackForm],\n );\n\n const getUserFeedbackComplete = useCallback(\n (\n messageId: string,\n sentiment: Sentiment,\n ): UserFeedbackCompleteProps | undefined => {\n const isVisible = state[messageId]?.completionForm?.[sentiment];\n if (!isVisible) return undefined;\n\n return {\n id: `feebback-completion-${sentiment}-${messageId}`,\n title: t('feedback.completion.title'),\n body: t('feedback.completion.body'),\n onClose: () => {\n dispatch.hideCompletionForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n },\n };\n },\n [state, dispatch, t],\n );\n\n const scrollToFeedbackForm = useCallback(\n (messageId: string, sentiment: Sentiment) => {\n setTimeout(() => {\n const el = document.getElementById(\n `feedback-${sentiment}-${messageId}`,\n );\n if (el) {\n el.scrollIntoView({ behavior: 'auto', block: 'start' });\n el.focus();\n }\n }, 0);\n },\n [],\n );\n\n const speakMessage = useCallback(\n (messageId: string, content: string) => {\n if (window.speechSynthesis.speaking || window.speechSynthesis.pending) {\n window.speechSynthesis.cancel();\n\n if (\n currentSpeakingIdRef.current &&\n currentSpeakingIdRef.current !== messageId\n ) {\n dispatch.updateButtonState(currentSpeakingIdRef.current, {\n isSpeaking: false,\n });\n }\n }\n\n // Track the current SpeakingId\n currentSpeakingIdRef.current = messageId;\n\n const utterance = new SpeechSynthesisUtterance(content);\n\n utterance.onstart = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: true });\n };\n\n utterance.onend = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n utterance.onerror = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n window.speechSynthesis.speak(utterance);\n },\n [dispatch],\n );\n\n const cancelSpeaking = useCallback(\n (messageId?: string) => {\n window.speechSynthesis.cancel();\n\n currentSpeakingIdRef.current = null;\n\n if (messageId) {\n // Cancel just this one message\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n } else {\n // Cancel all messages\n Object.keys(state).forEach(id => {\n if (state[id].buttonState?.isSpeaking) {\n dispatch.updateButtonState(id, { isSpeaking: false });\n }\n });\n }\n setTimeout(() => {\n const el = document.getElementById(`listen-${messageId}`);\n if (el) {\n el.blur();\n }\n }, 10);\n },\n [state, dispatch],\n );\n\n useEffect(() => {\n return () => {\n // Stop any ongoing speech when component unmounts\n cancelSpeaking();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversationId]);\n\n return useMemo(() => {\n return feedbackEnabled\n ? messages.map((message, index) => {\n if (\n message.role === 'user' ||\n (isStreaming && messages.length - 1 === index)\n )\n return message;\n\n const messageId = `${conversationId}-${message.role}-${index}`;\n const { sentiment, copied, isSpeaking } =\n state[messageId]?.buttonState || {};\n const showFeedbackForm = state[messageId]?.feedbackForm?.[sentiment];\n const userFeedbackForm =\n showFeedbackForm && feedbackForms(messageId)[sentiment];\n\n const userFeedbackComplete = getUserFeedbackComplete(\n messageId,\n sentiment,\n );\n\n const createSentimentAction = (selected: Sentiment) => ({\n isClicked: sentiment === selected,\n onClick: () => {\n if (sentiment !== selected) {\n dispatch.toggleFeedbackForm(messageId, selected);\n dispatch.updateButtonState(messageId, { sentiment: selected });\n scrollToFeedbackForm(messageId, sentiment);\n }\n },\n tooltipContent:\n selected === 'positive'\n ? t('feedback.tooltips.goodResponse')\n : t('feedback.tooltips.badResponse'),\n 'aria-expanded': sentiment === selected,\n 'aria-controls': showFeedbackForm\n ? `feedback-${sentiment}-${messageId}`\n : `feebback-completion-${sentiment}-${messageId}`,\n });\n\n const copyAction = {\n isClicked: copied,\n ref: copyButtonRef,\n tooltipContent: copied\n ? t('feedback.tooltips.copied')\n : t('feedback.tooltips.copy'),\n onClick: async () => {\n await window.navigator.clipboard.writeText(\n message.content as string,\n );\n dispatch.updateButtonState(messageId, {\n copied: true,\n });\n\n setTimeout(() => {\n dispatch.updateButtonState(messageId, { copied: false });\n copyButtonRef?.current?.blur();\n }, 1000);\n },\n };\n\n const listenAction = {\n isClicked: isSpeaking,\n ref: speakingButtonRef,\n id: `listen-${messageId}`,\n tooltipContent: isSpeaking\n ? t('feedback.tooltips.listening')\n : t('feedback.tooltips.listen'),\n onClick: () => {\n const isCurrentlySpeaking =\n state[messageId]?.buttonState?.isSpeaking;\n\n if (isCurrentlySpeaking) {\n // Stop if it's already speaking this message\n cancelSpeaking(messageId);\n } else {\n cancelSpeaking();\n speakMessage(messageId, message.content as string);\n }\n },\n };\n\n return {\n ...message,\n userFeedbackForm,\n userFeedbackComplete,\n actions: {\n positive: createSentimentAction('positive'),\n negative: createSentimentAction('negative'),\n copy: copyAction,\n listen: listenAction,\n },\n };\n })\n : messages;\n }, [\n t,\n conversationId,\n messages,\n state,\n dispatch,\n isStreaming,\n speakMessage,\n feedbackForms,\n cancelSpeaking,\n feedbackEnabled,\n getUserFeedbackComplete,\n scrollToFeedbackForm,\n ]);\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState,
|
|
1
|
+
import { useState, useCallback, useRef, useEffect, useMemo } from 'react';
|
|
2
2
|
import { useNavigate, useLocation, useMatch } from 'react-router-dom';
|
|
3
3
|
import { ChatbotDisplayMode } from '@patternfly/chatbot';
|
|
4
4
|
import { useAppDrawer } from '@red-hat-developer-hub/backstage-plugin-app-react';
|
|
@@ -28,6 +28,10 @@ function useLightspeedProviderState() {
|
|
|
28
28
|
const [activeNotebookId, setActiveNotebookId] = useState(
|
|
29
29
|
void 0
|
|
30
30
|
);
|
|
31
|
+
const [settingsTab, setSettingsTabState] = useState(null);
|
|
32
|
+
const setSettingsTab = useCallback((tab) => {
|
|
33
|
+
setSettingsTabState(tab);
|
|
34
|
+
}, []);
|
|
31
35
|
const shellViewTabRef = useRef(shellViewTab);
|
|
32
36
|
shellViewTabRef.current = shellViewTab;
|
|
33
37
|
const setShellViewTab = useCallback((tab) => {
|
|
@@ -180,10 +184,16 @@ function useLightspeedProviderState() {
|
|
|
180
184
|
(id) => {
|
|
181
185
|
setCurrentConversationIdState(id);
|
|
182
186
|
if (persistedDisplayModeRef.current === ChatbotDisplayMode.embedded && isLightspeedRouteRef.current && !isOnNotebooksPathRef.current) {
|
|
183
|
-
navigate(
|
|
187
|
+
navigate(
|
|
188
|
+
{
|
|
189
|
+
pathname: lightspeedRoutePath(id),
|
|
190
|
+
search: location.search
|
|
191
|
+
},
|
|
192
|
+
{ replace: true }
|
|
193
|
+
);
|
|
184
194
|
}
|
|
185
195
|
},
|
|
186
|
-
[navigate]
|
|
196
|
+
[navigate, location.search]
|
|
187
197
|
);
|
|
188
198
|
const setDraftMessage = useCallback((message) => {
|
|
189
199
|
setDraftMessageState(message);
|
|
@@ -254,7 +264,9 @@ function useLightspeedProviderState() {
|
|
|
254
264
|
shellViewTab,
|
|
255
265
|
setShellViewTab,
|
|
256
266
|
activeNotebookId,
|
|
257
|
-
setActiveNotebookId
|
|
267
|
+
setActiveNotebookId,
|
|
268
|
+
settingsTab,
|
|
269
|
+
setSettingsTab
|
|
258
270
|
}),
|
|
259
271
|
[
|
|
260
272
|
isOpen,
|
|
@@ -272,7 +284,9 @@ function useLightspeedProviderState() {
|
|
|
272
284
|
shellViewTab,
|
|
273
285
|
setShellViewTab,
|
|
274
286
|
activeNotebookId,
|
|
275
|
-
setActiveNotebookId
|
|
287
|
+
setActiveNotebookId,
|
|
288
|
+
settingsTab,
|
|
289
|
+
setSettingsTab
|
|
276
290
|
]
|
|
277
291
|
);
|
|
278
292
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLightspeedProviderState.esm.js","sources":["../../src/hooks/useLightspeedProviderState.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useLocation, useMatch, useNavigate } from 'react-router-dom';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport { useAppDrawer } from '@red-hat-developer-hub/backstage-plugin-app-react';\n\nimport type {\n LightspeedDrawerContextType,\n LightspeedEmbeddedNotebooksTarget,\n} from '../components/LightspeedDrawerContext';\nimport { LIGHTSPEED_APP_DRAWER_ID, LIGHTSPEED_PATH } from '../const';\nimport type { FileContent } from '../types';\nimport { useBackstageUserIdentity } from './useBackstageUserIdentity';\nimport { useDisplayModeSettings } from './useDisplayModeSettings';\n\nfunction lightspeedRoutePath(conversationId?: string): string {\n return conversationId\n ? `${LIGHTSPEED_PATH}/conversation/${conversationId}`\n : LIGHTSPEED_PATH;\n}\n\n/**\n * Encapsulates LightspeedDrawerProvider state, routing, and ApplicationDrawer sync.\n *\n * @internal\n */\nexport function useLightspeedProviderState(): {\n contextValue: LightspeedDrawerContextType;\n shouldRenderOverlayModal: boolean;\n closeChatbot: () => void;\n} {\n const navigate = useNavigate();\n const location = useLocation();\n const { openDrawer, closeDrawer } = useAppDrawer();\n const user = useBackstageUserIdentity();\n const {\n displayMode: persistedDisplayMode,\n setDisplayMode: setPersistedDisplayMode,\n } = useDisplayModeSettings(user, ChatbotDisplayMode.default);\n\n const [displayModeState, setDisplayModeState] =\n useState<ChatbotDisplayMode>(persistedDisplayMode);\n const [isOpen, setIsOpen] = useState(false);\n const [drawerWidth, setDrawerWidth] = useState(400);\n const [currentConversationIdState, setCurrentConversationIdState] = useState<\n string | undefined\n >(undefined);\n const [draftMessage, setDraftMessageState] = useState('');\n const [draftFileContents, setDraftFileContentsState] = useState<\n FileContent[]\n >([]);\n const [shellViewTab, setShellViewTabState] = useState(0);\n const [activeNotebookId, setActiveNotebookId] = useState<string | undefined>(\n undefined,\n );\n const shellViewTabRef = useRef(shellViewTab);\n shellViewTabRef.current = shellViewTab;\n const setShellViewTab = useCallback((tab: number) => {\n const next = tab === 1 ? 1 : 0;\n shellViewTabRef.current = next;\n setShellViewTabState(next);\n }, []);\n const openedViaFABRef = useRef(false);\n const dockedAfterLeavingFullscreenRef = useRef(false);\n /** True while navigating off /lightspeed after user chose overlay/docked (URL can lag persisted mode). */\n const leavingLightspeedForNonEmbeddedShellRef = useRef(false);\n /** True until overlay/docked LightspeedChat consumes it (new mount after leaving fullscreen route). */\n const pendingOverlayThreadHandoffRef = useRef(false);\n /** Used to detect in-app moves (e.g. Chat ↔ Notebooks) so display mode is not reset to embedded. */\n const lightspeedPathnamePrevRef = useRef<string | null>(null);\n\n const isLightspeedRouteRef = useRef(false);\n const isOnNotebooksPathRef = useRef(false);\n const persistedDisplayModeRef = useRef(persistedDisplayMode);\n\n const isLightspeedRoute = location.pathname.startsWith(LIGHTSPEED_PATH);\n isLightspeedRouteRef.current = isLightspeedRoute;\n isOnNotebooksPathRef.current = location.pathname.startsWith(\n `${LIGHTSPEED_PATH}/notebooks`,\n );\n persistedDisplayModeRef.current = persistedDisplayMode;\n const conversationMatch = useMatch(\n `${LIGHTSPEED_PATH}/conversation/:conversationId`,\n );\n const conversationId = conversationMatch?.params?.conversationId;\n\n const syncShellDrawerForMode = useCallback(\n (mode: ChatbotDisplayMode) => {\n if (mode === ChatbotDisplayMode.docked) {\n if (isLightspeedRoute) {\n dockedAfterLeavingFullscreenRef.current = true;\n } else {\n openDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n } else {\n dockedAfterLeavingFullscreenRef.current = false;\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n },\n [closeDrawer, isLightspeedRoute, openDrawer],\n );\n\n const navigateBackOrGoToCatalog = useCallback(() => {\n if (!openedViaFABRef.current) {\n navigate('/catalog');\n openedViaFABRef.current = true;\n return;\n }\n navigate(-1);\n }, [navigate]);\n\n /**\n * Leaving /lightspeed for overlay/docked must not use navigate(-1): after the first FAB\n * open, navigateBackOrGoToCatalog uses -1 and can land back on /lightspeed (fullscreen).\n */\n const leaveLightspeedRouteForShellDisplayMode = useCallback(() => {\n navigate('/catalog', { replace: true });\n }, [navigate]);\n\n useEffect(() => {\n const pathname = location.pathname;\n const prevPathname = lightspeedPathnamePrevRef.current;\n const isUnderLightspeedPath = (p: string | null) =>\n Boolean(p && p.startsWith(LIGHTSPEED_PATH));\n const isInternalLightspeedRouteChange =\n isUnderLightspeedPath(prevPathname) &&\n isUnderLightspeedPath(pathname) &&\n prevPathname !== pathname;\n\n if (!isLightspeedRoute) {\n leavingLightspeedForNonEmbeddedShellRef.current = false;\n }\n\n if (conversationId) {\n setCurrentConversationIdState(conversationId);\n } else if (isLightspeedRoute) {\n // On `/lightspeed` without a `:conversationId` segment, URL implies a fresh thread.\n // When navigating to another app route (overlay/docked), keep the last id so display\n // mode switches and re-entry to fullscreen stay on the active conversation.\n setCurrentConversationIdState(undefined);\n }\n\n if (isLightspeedRoute) {\n if (!isInternalLightspeedRouteChange) {\n if (\n leavingLightspeedForNonEmbeddedShellRef.current &&\n persistedDisplayMode !== ChatbotDisplayMode.embedded\n ) {\n setDisplayModeState(persistedDisplayMode);\n } else {\n setDisplayModeState(ChatbotDisplayMode.embedded);\n }\n }\n setIsOpen(true);\n if (!dockedAfterLeavingFullscreenRef.current) {\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n } else if (persistedDisplayMode === ChatbotDisplayMode.embedded) {\n // Off /lightspeed there is no fullscreen surface; use overlay so FAB stays available.\n // (Persisted preference remains \"fullscreen\" for the next open.)\n setDisplayModeState(ChatbotDisplayMode.default);\n } else {\n setDisplayModeState(persistedDisplayMode);\n }\n\n lightspeedPathnamePrevRef.current = pathname;\n }, [\n closeDrawer,\n conversationId,\n isLightspeedRoute,\n location.pathname,\n persistedDisplayMode,\n ]);\n\n useEffect(() => {\n if (\n !isLightspeedRoute &&\n isOpen &&\n displayModeState === ChatbotDisplayMode.docked\n ) {\n openDrawer(LIGHTSPEED_APP_DRAWER_ID);\n dockedAfterLeavingFullscreenRef.current = false;\n }\n }, [displayModeState, isLightspeedRoute, isOpen, openDrawer]);\n\n const openChatbot = useCallback(() => {\n openedViaFABRef.current = true;\n const rawMode = persistedDisplayMode || ChatbotDisplayMode.default;\n\n if (rawMode === ChatbotDisplayMode.embedded) {\n if (!isLightspeedRoute) {\n if (shellViewTabRef.current === 1) {\n navigate(`${LIGHTSPEED_PATH}/notebooks`);\n } else {\n navigate(lightspeedRoutePath(currentConversationIdState));\n }\n }\n setDisplayModeState(ChatbotDisplayMode.embedded);\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n setIsOpen(true);\n return;\n }\n\n setDisplayModeState(rawMode);\n\n if (rawMode === ChatbotDisplayMode.docked) {\n openDrawer(LIGHTSPEED_APP_DRAWER_ID);\n } else {\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n\n setIsOpen(true);\n }, [\n closeDrawer,\n currentConversationIdState,\n isLightspeedRoute,\n navigate,\n openDrawer,\n persistedDisplayMode,\n ]);\n\n const closeChatbot = useCallback(() => {\n dockedAfterLeavingFullscreenRef.current = false;\n if (displayModeState === ChatbotDisplayMode.embedded && isLightspeedRoute) {\n navigateBackOrGoToCatalog();\n }\n if (displayModeState === ChatbotDisplayMode.docked) {\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n setIsOpen(false);\n }, [\n closeDrawer,\n displayModeState,\n isLightspeedRoute,\n navigateBackOrGoToCatalog,\n ]);\n\n const toggleChatbot = useCallback(() => {\n if (isOpen) {\n closeChatbot();\n } else {\n openChatbot();\n }\n }, [isOpen, openChatbot, closeChatbot]);\n\n const setCurrentConversationId = useCallback(\n (id: string | undefined) => {\n setCurrentConversationIdState(id);\n // Refs: first-stream completion calls onStart after unmount / mode change; a stale\n // embedded + /lightspeed closure would navigate back to fullscreen without this.\n // Skip navigation when the user is on a notebooks path — conversation route updates\n // must not overwrite the notebooks URL (fixes notebook closing on mode switch).\n if (\n persistedDisplayModeRef.current === ChatbotDisplayMode.embedded &&\n isLightspeedRouteRef.current &&\n !isOnNotebooksPathRef.current\n ) {\n navigate(lightspeedRoutePath(id), { replace: true });\n }\n },\n [navigate],\n );\n\n const setDraftMessage = useCallback((message: string) => {\n setDraftMessageState(message);\n }, []);\n\n const setDraftFileContents = useCallback((files: FileContent[]) => {\n setDraftFileContentsState(files);\n }, []);\n\n const consumePendingOverlayThreadHandoff = useCallback(() => {\n if (!pendingOverlayThreadHandoffRef.current) {\n return false;\n }\n pendingOverlayThreadHandoffRef.current = false;\n return true;\n }, []);\n\n const setDisplayMode = useCallback(\n (\n mode: ChatbotDisplayMode,\n conversationIdParam?: string,\n embeddedNotebooks?: LightspeedEmbeddedNotebooksTarget,\n ) => {\n if (mode === displayModeState) {\n return;\n }\n setPersistedDisplayMode(mode);\n syncShellDrawerForMode(mode);\n\n if (mode === ChatbotDisplayMode.embedded) {\n if (embeddedNotebooks) {\n const path =\n embeddedNotebooks === 'notebooks'\n ? `${LIGHTSPEED_PATH}/notebooks`\n : `${LIGHTSPEED_PATH}/notebooks/${embeddedNotebooks.notebookSessionId}`;\n navigate(path);\n } else if (shellViewTabRef.current === 1) {\n navigate(`${LIGHTSPEED_PATH}/notebooks`);\n } else {\n const convId = conversationIdParam ?? currentConversationIdState;\n navigate(lightspeedRoutePath(convId));\n }\n setIsOpen(true);\n } else {\n if (isLightspeedRoute) {\n leavingLightspeedForNonEmbeddedShellRef.current = true;\n pendingOverlayThreadHandoffRef.current = true;\n leaveLightspeedRouteForShellDisplayMode();\n }\n setIsOpen(true);\n }\n },\n [\n currentConversationIdState,\n displayModeState,\n isLightspeedRoute,\n leaveLightspeedRouteForShellDisplayMode,\n navigate,\n setPersistedDisplayMode,\n syncShellDrawerForMode,\n ],\n );\n\n const shouldRenderOverlayModal =\n isOpen &&\n displayModeState === ChatbotDisplayMode.default &&\n !isLightspeedRoute;\n\n const contextValue = useMemo(\n () => ({\n isChatbotActive: isOpen,\n toggleChatbot,\n displayMode: displayModeState,\n setDisplayMode,\n drawerWidth,\n setDrawerWidth,\n currentConversationId: currentConversationIdState,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n draftFileContents,\n setDraftFileContents,\n consumePendingOverlayThreadHandoff,\n shellViewTab,\n setShellViewTab,\n activeNotebookId,\n setActiveNotebookId,\n }),\n [\n isOpen,\n toggleChatbot,\n displayModeState,\n setDisplayMode,\n drawerWidth,\n currentConversationIdState,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n draftFileContents,\n setDraftFileContents,\n consumePendingOverlayThreadHandoff,\n shellViewTab,\n setShellViewTab,\n activeNotebookId,\n setActiveNotebookId,\n ],\n );\n\n return {\n contextValue,\n shouldRenderOverlayModal,\n closeChatbot,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useLightspeedProviderState.esm.js","sources":["../../src/hooks/useLightspeedProviderState.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useLocation, useMatch, useNavigate } from 'react-router-dom';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport { useAppDrawer } from '@red-hat-developer-hub/backstage-plugin-app-react';\n\nimport type {\n LightspeedDrawerContextType,\n LightspeedEmbeddedNotebooksTarget,\n} from '../components/LightspeedDrawerContext';\nimport { LIGHTSPEED_APP_DRAWER_ID, LIGHTSPEED_PATH } from '../const';\nimport type { FileContent } from '../types';\nimport { useBackstageUserIdentity } from './useBackstageUserIdentity';\nimport { useDisplayModeSettings } from './useDisplayModeSettings';\nimport type { SettingsTab } from './useSettingsPanelUrlState';\n\nfunction lightspeedRoutePath(conversationId?: string): string {\n return conversationId\n ? `${LIGHTSPEED_PATH}/conversation/${conversationId}`\n : LIGHTSPEED_PATH;\n}\n\n/**\n * Encapsulates LightspeedDrawerProvider state, routing, and ApplicationDrawer sync.\n *\n * @internal\n */\nexport function useLightspeedProviderState(): {\n contextValue: LightspeedDrawerContextType;\n shouldRenderOverlayModal: boolean;\n closeChatbot: () => void;\n} {\n const navigate = useNavigate();\n const location = useLocation();\n const { openDrawer, closeDrawer } = useAppDrawer();\n const user = useBackstageUserIdentity();\n const {\n displayMode: persistedDisplayMode,\n setDisplayMode: setPersistedDisplayMode,\n } = useDisplayModeSettings(user, ChatbotDisplayMode.default);\n\n const [displayModeState, setDisplayModeState] =\n useState<ChatbotDisplayMode>(persistedDisplayMode);\n const [isOpen, setIsOpen] = useState(false);\n const [drawerWidth, setDrawerWidth] = useState(400);\n const [currentConversationIdState, setCurrentConversationIdState] = useState<\n string | undefined\n >(undefined);\n const [draftMessage, setDraftMessageState] = useState('');\n const [draftFileContents, setDraftFileContentsState] = useState<\n FileContent[]\n >([]);\n const [shellViewTab, setShellViewTabState] = useState(0);\n const [activeNotebookId, setActiveNotebookId] = useState<string | undefined>(\n undefined,\n );\n const [settingsTab, setSettingsTabState] = useState<SettingsTab | null>(null);\n const setSettingsTab = useCallback((tab: SettingsTab | null) => {\n setSettingsTabState(tab);\n }, []);\n const shellViewTabRef = useRef(shellViewTab);\n shellViewTabRef.current = shellViewTab;\n const setShellViewTab = useCallback((tab: number) => {\n const next = tab === 1 ? 1 : 0;\n shellViewTabRef.current = next;\n setShellViewTabState(next);\n }, []);\n const openedViaFABRef = useRef(false);\n const dockedAfterLeavingFullscreenRef = useRef(false);\n /** True while navigating off /lightspeed after user chose overlay/docked (URL can lag persisted mode). */\n const leavingLightspeedForNonEmbeddedShellRef = useRef(false);\n /** True until overlay/docked LightspeedChat consumes it (new mount after leaving fullscreen route). */\n const pendingOverlayThreadHandoffRef = useRef(false);\n /** Used to detect in-app moves (e.g. Chat ↔ Notebooks) so display mode is not reset to embedded. */\n const lightspeedPathnamePrevRef = useRef<string | null>(null);\n\n const isLightspeedRouteRef = useRef(false);\n const isOnNotebooksPathRef = useRef(false);\n const persistedDisplayModeRef = useRef(persistedDisplayMode);\n\n const isLightspeedRoute = location.pathname.startsWith(LIGHTSPEED_PATH);\n isLightspeedRouteRef.current = isLightspeedRoute;\n isOnNotebooksPathRef.current = location.pathname.startsWith(\n `${LIGHTSPEED_PATH}/notebooks`,\n );\n persistedDisplayModeRef.current = persistedDisplayMode;\n const conversationMatch = useMatch(\n `${LIGHTSPEED_PATH}/conversation/:conversationId`,\n );\n const conversationId = conversationMatch?.params?.conversationId;\n\n const syncShellDrawerForMode = useCallback(\n (mode: ChatbotDisplayMode) => {\n if (mode === ChatbotDisplayMode.docked) {\n if (isLightspeedRoute) {\n dockedAfterLeavingFullscreenRef.current = true;\n } else {\n openDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n } else {\n dockedAfterLeavingFullscreenRef.current = false;\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n },\n [closeDrawer, isLightspeedRoute, openDrawer],\n );\n\n const navigateBackOrGoToCatalog = useCallback(() => {\n if (!openedViaFABRef.current) {\n navigate('/catalog');\n openedViaFABRef.current = true;\n return;\n }\n navigate(-1);\n }, [navigate]);\n\n /**\n * Leaving /lightspeed for overlay/docked must not use navigate(-1): after the first FAB\n * open, navigateBackOrGoToCatalog uses -1 and can land back on /lightspeed (fullscreen).\n */\n const leaveLightspeedRouteForShellDisplayMode = useCallback(() => {\n navigate('/catalog', { replace: true });\n }, [navigate]);\n\n useEffect(() => {\n const pathname = location.pathname;\n const prevPathname = lightspeedPathnamePrevRef.current;\n const isUnderLightspeedPath = (p: string | null) =>\n Boolean(p && p.startsWith(LIGHTSPEED_PATH));\n const isInternalLightspeedRouteChange =\n isUnderLightspeedPath(prevPathname) &&\n isUnderLightspeedPath(pathname) &&\n prevPathname !== pathname;\n\n if (!isLightspeedRoute) {\n leavingLightspeedForNonEmbeddedShellRef.current = false;\n }\n\n if (conversationId) {\n setCurrentConversationIdState(conversationId);\n } else if (isLightspeedRoute) {\n // On `/lightspeed` without a `:conversationId` segment, URL implies a fresh thread.\n // When navigating to another app route (overlay/docked), keep the last id so display\n // mode switches and re-entry to fullscreen stay on the active conversation.\n setCurrentConversationIdState(undefined);\n }\n\n if (isLightspeedRoute) {\n if (!isInternalLightspeedRouteChange) {\n if (\n leavingLightspeedForNonEmbeddedShellRef.current &&\n persistedDisplayMode !== ChatbotDisplayMode.embedded\n ) {\n setDisplayModeState(persistedDisplayMode);\n } else {\n setDisplayModeState(ChatbotDisplayMode.embedded);\n }\n }\n setIsOpen(true);\n if (!dockedAfterLeavingFullscreenRef.current) {\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n } else if (persistedDisplayMode === ChatbotDisplayMode.embedded) {\n // Off /lightspeed there is no fullscreen surface; use overlay so FAB stays available.\n // (Persisted preference remains \"fullscreen\" for the next open.)\n setDisplayModeState(ChatbotDisplayMode.default);\n } else {\n setDisplayModeState(persistedDisplayMode);\n }\n\n lightspeedPathnamePrevRef.current = pathname;\n }, [\n closeDrawer,\n conversationId,\n isLightspeedRoute,\n location.pathname,\n persistedDisplayMode,\n ]);\n\n useEffect(() => {\n if (\n !isLightspeedRoute &&\n isOpen &&\n displayModeState === ChatbotDisplayMode.docked\n ) {\n openDrawer(LIGHTSPEED_APP_DRAWER_ID);\n dockedAfterLeavingFullscreenRef.current = false;\n }\n }, [displayModeState, isLightspeedRoute, isOpen, openDrawer]);\n\n const openChatbot = useCallback(() => {\n openedViaFABRef.current = true;\n const rawMode = persistedDisplayMode || ChatbotDisplayMode.default;\n\n if (rawMode === ChatbotDisplayMode.embedded) {\n if (!isLightspeedRoute) {\n if (shellViewTabRef.current === 1) {\n navigate(`${LIGHTSPEED_PATH}/notebooks`);\n } else {\n navigate(lightspeedRoutePath(currentConversationIdState));\n }\n }\n setDisplayModeState(ChatbotDisplayMode.embedded);\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n setIsOpen(true);\n return;\n }\n\n setDisplayModeState(rawMode);\n\n if (rawMode === ChatbotDisplayMode.docked) {\n openDrawer(LIGHTSPEED_APP_DRAWER_ID);\n } else {\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n\n setIsOpen(true);\n }, [\n closeDrawer,\n currentConversationIdState,\n isLightspeedRoute,\n navigate,\n openDrawer,\n persistedDisplayMode,\n ]);\n\n const closeChatbot = useCallback(() => {\n dockedAfterLeavingFullscreenRef.current = false;\n if (displayModeState === ChatbotDisplayMode.embedded && isLightspeedRoute) {\n navigateBackOrGoToCatalog();\n }\n if (displayModeState === ChatbotDisplayMode.docked) {\n closeDrawer(LIGHTSPEED_APP_DRAWER_ID);\n }\n setIsOpen(false);\n }, [\n closeDrawer,\n displayModeState,\n isLightspeedRoute,\n navigateBackOrGoToCatalog,\n ]);\n\n const toggleChatbot = useCallback(() => {\n if (isOpen) {\n closeChatbot();\n } else {\n openChatbot();\n }\n }, [isOpen, openChatbot, closeChatbot]);\n\n const setCurrentConversationId = useCallback(\n (id: string | undefined) => {\n setCurrentConversationIdState(id);\n // Refs: first-stream completion calls onStart after unmount / mode change; a stale\n // embedded + /lightspeed closure would navigate back to fullscreen without this.\n // Skip navigation when the user is on a notebooks path — conversation route updates\n // must not overwrite the notebooks URL (fixes notebook closing on mode switch).\n if (\n persistedDisplayModeRef.current === ChatbotDisplayMode.embedded &&\n isLightspeedRouteRef.current &&\n !isOnNotebooksPathRef.current\n ) {\n navigate(\n {\n pathname: lightspeedRoutePath(id),\n search: location.search,\n },\n { replace: true },\n );\n }\n },\n [navigate, location.search],\n );\n\n const setDraftMessage = useCallback((message: string) => {\n setDraftMessageState(message);\n }, []);\n\n const setDraftFileContents = useCallback((files: FileContent[]) => {\n setDraftFileContentsState(files);\n }, []);\n\n const consumePendingOverlayThreadHandoff = useCallback(() => {\n if (!pendingOverlayThreadHandoffRef.current) {\n return false;\n }\n pendingOverlayThreadHandoffRef.current = false;\n return true;\n }, []);\n\n const setDisplayMode = useCallback(\n (\n mode: ChatbotDisplayMode,\n conversationIdParam?: string,\n embeddedNotebooks?: LightspeedEmbeddedNotebooksTarget,\n ) => {\n if (mode === displayModeState) {\n return;\n }\n setPersistedDisplayMode(mode);\n syncShellDrawerForMode(mode);\n\n if (mode === ChatbotDisplayMode.embedded) {\n if (embeddedNotebooks) {\n const path =\n embeddedNotebooks === 'notebooks'\n ? `${LIGHTSPEED_PATH}/notebooks`\n : `${LIGHTSPEED_PATH}/notebooks/${embeddedNotebooks.notebookSessionId}`;\n navigate(path);\n } else if (shellViewTabRef.current === 1) {\n navigate(`${LIGHTSPEED_PATH}/notebooks`);\n } else {\n const convId = conversationIdParam ?? currentConversationIdState;\n navigate(lightspeedRoutePath(convId));\n }\n setIsOpen(true);\n } else {\n if (isLightspeedRoute) {\n leavingLightspeedForNonEmbeddedShellRef.current = true;\n pendingOverlayThreadHandoffRef.current = true;\n leaveLightspeedRouteForShellDisplayMode();\n }\n setIsOpen(true);\n }\n },\n [\n currentConversationIdState,\n displayModeState,\n isLightspeedRoute,\n leaveLightspeedRouteForShellDisplayMode,\n navigate,\n setPersistedDisplayMode,\n syncShellDrawerForMode,\n ],\n );\n\n const shouldRenderOverlayModal =\n isOpen &&\n displayModeState === ChatbotDisplayMode.default &&\n !isLightspeedRoute;\n\n const contextValue = useMemo(\n () => ({\n isChatbotActive: isOpen,\n toggleChatbot,\n displayMode: displayModeState,\n setDisplayMode,\n drawerWidth,\n setDrawerWidth,\n currentConversationId: currentConversationIdState,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n draftFileContents,\n setDraftFileContents,\n consumePendingOverlayThreadHandoff,\n shellViewTab,\n setShellViewTab,\n activeNotebookId,\n setActiveNotebookId,\n settingsTab,\n setSettingsTab,\n }),\n [\n isOpen,\n toggleChatbot,\n displayModeState,\n setDisplayMode,\n drawerWidth,\n currentConversationIdState,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n draftFileContents,\n setDraftFileContents,\n consumePendingOverlayThreadHandoff,\n shellViewTab,\n setShellViewTab,\n activeNotebookId,\n setActiveNotebookId,\n settingsTab,\n setSettingsTab,\n ],\n );\n\n return {\n contextValue,\n shouldRenderOverlayModal,\n closeChatbot,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
const useSavedPromptActions = ({
|
|
4
|
+
onApplyToInput,
|
|
5
|
+
onSendDirectly,
|
|
6
|
+
onDelete
|
|
7
|
+
}) => {
|
|
8
|
+
const [promptToDelete, setPromptToDelete] = useState(
|
|
9
|
+
null
|
|
10
|
+
);
|
|
11
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
12
|
+
const [deleteError, setDeleteError] = useState(null);
|
|
13
|
+
const applyToInput = useCallback(
|
|
14
|
+
(content) => {
|
|
15
|
+
onApplyToInput(content);
|
|
16
|
+
},
|
|
17
|
+
[onApplyToInput]
|
|
18
|
+
);
|
|
19
|
+
const sendDirectly = useCallback(
|
|
20
|
+
(content) => {
|
|
21
|
+
onSendDirectly(content);
|
|
22
|
+
},
|
|
23
|
+
[onSendDirectly]
|
|
24
|
+
);
|
|
25
|
+
const requestDelete = useCallback((prompt) => {
|
|
26
|
+
setDeleteError(null);
|
|
27
|
+
setPromptToDelete(prompt);
|
|
28
|
+
}, []);
|
|
29
|
+
const closeDeleteModal = useCallback(() => {
|
|
30
|
+
setPromptToDelete(null);
|
|
31
|
+
setDeleteError(null);
|
|
32
|
+
}, []);
|
|
33
|
+
const confirmDelete = useCallback(async () => {
|
|
34
|
+
if (!promptToDelete) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
setIsDeleting(true);
|
|
38
|
+
setDeleteError(null);
|
|
39
|
+
try {
|
|
40
|
+
await onDelete(promptToDelete.id);
|
|
41
|
+
setPromptToDelete(null);
|
|
42
|
+
} catch (e) {
|
|
43
|
+
setDeleteError(
|
|
44
|
+
e instanceof Error ? e.message : "Failed to delete saved prompt"
|
|
45
|
+
);
|
|
46
|
+
} finally {
|
|
47
|
+
setIsDeleting(false);
|
|
48
|
+
}
|
|
49
|
+
}, [onDelete, promptToDelete]);
|
|
50
|
+
return {
|
|
51
|
+
applyToInput,
|
|
52
|
+
sendDirectly,
|
|
53
|
+
requestDelete,
|
|
54
|
+
promptToDelete,
|
|
55
|
+
closeDeleteModal,
|
|
56
|
+
confirmDelete,
|
|
57
|
+
isDeleting,
|
|
58
|
+
deleteError,
|
|
59
|
+
isDeleteModalOpen: promptToDelete !== null
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export { useSavedPromptActions };
|
|
64
|
+
//# sourceMappingURL=useSavedPromptActions.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSavedPromptActions.esm.js","sources":["../../src/hooks/useSavedPromptActions.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useCallback, useState } from 'react';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\ntype UseSavedPromptActionsOptions = {\n onApplyToInput: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (promptId: string) => Promise<void>;\n};\n\nexport const useSavedPromptActions = ({\n onApplyToInput,\n onSendDirectly,\n onDelete,\n}: UseSavedPromptActionsOptions) => {\n const [promptToDelete, setPromptToDelete] = useState<SavedPrompt | null>(\n null,\n );\n const [isDeleting, setIsDeleting] = useState(false);\n const [deleteError, setDeleteError] = useState<string | null>(null);\n\n const applyToInput = useCallback(\n (content: string) => {\n onApplyToInput(content);\n },\n [onApplyToInput],\n );\n\n const sendDirectly = useCallback(\n (content: string) => {\n onSendDirectly(content);\n },\n [onSendDirectly],\n );\n\n const requestDelete = useCallback((prompt: SavedPrompt) => {\n setDeleteError(null);\n setPromptToDelete(prompt);\n }, []);\n\n const closeDeleteModal = useCallback(() => {\n setPromptToDelete(null);\n setDeleteError(null);\n }, []);\n\n const confirmDelete = useCallback(async () => {\n if (!promptToDelete) {\n return;\n }\n setIsDeleting(true);\n setDeleteError(null);\n try {\n await onDelete(promptToDelete.id);\n setPromptToDelete(null);\n } catch (e) {\n setDeleteError(\n e instanceof Error ? e.message : 'Failed to delete saved prompt',\n );\n } finally {\n setIsDeleting(false);\n }\n }, [onDelete, promptToDelete]);\n\n return {\n applyToInput,\n sendDirectly,\n requestDelete,\n promptToDelete,\n closeDeleteModal,\n confirmDelete,\n isDeleting,\n deleteError,\n isDeleteModalOpen: promptToDelete !== null,\n };\n};\n"],"names":[],"mappings":";;AAyBO,MAAM,wBAAwB,CAAC;AAAA,EACpC,cAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,KAAoC;AAClC,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,QAAA;AAAA,IAC1C;AAAA,GACF;AACA,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,KAAK,CAAA;AAClD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAwB,IAAI,CAAA;AAElE,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,OAAA,KAAoB;AACnB,MAAA,cAAA,CAAe,OAAO,CAAA;AAAA,IACxB,CAAA;AAAA,IACA,CAAC,cAAc;AAAA,GACjB;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,OAAA,KAAoB;AACnB,MAAA,cAAA,CAAe,OAAO,CAAA;AAAA,IACxB,CAAA;AAAA,IACA,CAAC,cAAc;AAAA,GACjB;AAEA,EAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,CAAC,MAAA,KAAwB;AACzD,IAAA,cAAA,CAAe,IAAI,CAAA;AACnB,IAAA,iBAAA,CAAkB,MAAM,CAAA;AAAA,EAC1B,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,gBAAA,GAAmB,YAAY,MAAM;AACzC,IAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,IAAA,cAAA,CAAe,IAAI,CAAA;AAAA,EACrB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAgB,YAAY,YAAY;AAC5C,IAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,MAAA;AAAA,IACF;AACA,IAAA,aAAA,CAAc,IAAI,CAAA;AAClB,IAAA,cAAA,CAAe,IAAI,CAAA;AACnB,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,CAAS,eAAe,EAAE,CAAA;AAChC,MAAA,iBAAA,CAAkB,IAAI,CAAA;AAAA,IACxB,SAAS,CAAA,EAAG;AACV,MAAA,cAAA;AAAA,QACE,CAAA,YAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU;AAAA,OACnC;AAAA,IACF,CAAA,SAAE;AACA,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,IACrB;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,cAAc,CAAC,CAAA;AAE7B,EAAA,OAAO;AAAA,IACL,YAAA;AAAA,IACA,YAAA;AAAA,IACA,aAAA;AAAA,IACA,cAAA;AAAA,IACA,gBAAA;AAAA,IACA,aAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAA;AAAA,IACA,mBAAmB,cAAA,KAAmB;AAAA,GACxC;AACF;;;;"}
|