@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.1.0 → 5.3.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 +24 -0
- package/README.md +40 -5
- package/dist/alpha.d.ts +61 -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 +276 -134
- package/dist/components/LightSpeedChat.esm.js.map +1 -1
- package/dist/components/LightspeedChatBoxHeader.esm.js +57 -2
- package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
- package/dist/components/LightspeedChatContainer.esm.js +2 -1
- package/dist/components/LightspeedChatContainer.esm.js.map +1 -1
- package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
- package/dist/components/LightspeedDrawerProvider.esm.js +1 -0
- package/dist/components/LightspeedDrawerProvider.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/MessageBarModelSelector.esm.js +104 -12
- package/dist/components/MessageBarModelSelector.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/ScreenContextChip.esm.js +172 -0
- package/dist/components/ScreenContextChip.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/screenContextLabelSubscription.esm.js +113 -0
- package/dist/hooks/screenContextLabelSubscription.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/useScreenContextLabelRevision.esm.js +13 -0
- package/dist/hooks/useScreenContextLabelRevision.esm.js.map +1 -0
- package/dist/hooks/useScreenContextSettings.esm.js +110 -0
- package/dist/hooks/useScreenContextSettings.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/hooks/useWindowLocation.esm.js +28 -0
- package/dist/hooks/useWindowLocation.esm.js.map +1 -0
- package/dist/translations/de.esm.js +64 -1
- package/dist/translations/de.esm.js.map +1 -1
- package/dist/translations/es.esm.js +64 -1
- package/dist/translations/es.esm.js.map +1 -1
- package/dist/translations/fr.esm.js +64 -1
- package/dist/translations/fr.esm.js.map +1 -1
- package/dist/translations/it.esm.js +64 -1
- package/dist/translations/it.esm.js.map +1 -1
- package/dist/translations/ja.esm.js +64 -1
- package/dist/translations/ja.esm.js.map +1 -1
- package/dist/translations/ref.esm.js +64 -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/dom-selectors.esm.js +22 -2
- package/dist/utils/dom-selectors.esm.js.map +1 -1
- package/dist/utils/prompt-utils.esm.js +18 -1
- package/dist/utils/prompt-utils.esm.js.map +1 -1
- package/dist/utils/screen-capture.esm.js +116 -0
- package/dist/utils/screen-capture.esm.js.map +1 -0
- package/dist/utils/screen-context-utils.esm.js +343 -0
- package/dist/utils/screen-context-utils.esm.js.map +1 -0
- package/dist/utils/sensitive-data-redactor.esm.js +39 -1
- package/dist/utils/sensitive-data-redactor.esm.js.map +1 -1
- package/package.json +5 -15
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useState, useEffect } from 'react';
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect, useMemo, Fragment } from 'react';
|
|
3
3
|
import { styled } from '@mui/material/styles';
|
|
4
4
|
import Typography from '@mui/material/Typography';
|
|
5
5
|
import { MenuToggle, Dropdown, DropdownList, DropdownItem, Tooltip } from '@patternfly/react-core';
|
|
6
|
-
import { AngleDownIcon } from '@patternfly/react-icons';
|
|
6
|
+
import { OutlinedImageIcon, CheckIcon, AngleDownIcon } from '@patternfly/react-icons';
|
|
7
7
|
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
8
8
|
|
|
9
9
|
const SelectorToggle = styled(MenuToggle)(({ theme }) => ({
|
|
@@ -26,10 +26,64 @@ const SelectorToggle = styled(MenuToggle)(({ theme }) => ({
|
|
|
26
26
|
opacity: 0.5
|
|
27
27
|
}
|
|
28
28
|
}));
|
|
29
|
+
const VisionIndicatorIcon = styled(OutlinedImageIcon)(({ theme }) => ({
|
|
30
|
+
width: 16,
|
|
31
|
+
height: 16,
|
|
32
|
+
color: theme.palette.text.secondary,
|
|
33
|
+
flexShrink: 0
|
|
34
|
+
}));
|
|
35
|
+
const VisionIndicatorWrap = styled("span")({
|
|
36
|
+
display: "inline-flex",
|
|
37
|
+
alignItems: "center",
|
|
38
|
+
lineHeight: 1
|
|
39
|
+
});
|
|
40
|
+
const VisionSlot = styled("span")({
|
|
41
|
+
display: "inline-flex",
|
|
42
|
+
alignItems: "center",
|
|
43
|
+
justifyContent: "center",
|
|
44
|
+
flexShrink: 0,
|
|
45
|
+
width: 16,
|
|
46
|
+
height: 16
|
|
47
|
+
});
|
|
48
|
+
const TickSlot = styled("span")(({ theme }) => ({
|
|
49
|
+
display: "inline-flex",
|
|
50
|
+
alignItems: "center",
|
|
51
|
+
justifyContent: "center",
|
|
52
|
+
flexShrink: 0,
|
|
53
|
+
width: "1em",
|
|
54
|
+
height: "1em",
|
|
55
|
+
color: theme.palette.primary.main
|
|
56
|
+
}));
|
|
57
|
+
const ModelLabel = styled("span")({
|
|
58
|
+
flex: "1 1 auto",
|
|
59
|
+
minWidth: 0,
|
|
60
|
+
overflow: "hidden",
|
|
61
|
+
textOverflow: "ellipsis",
|
|
62
|
+
whiteSpace: "nowrap"
|
|
63
|
+
});
|
|
64
|
+
const ModelItemContent = styled("span")({
|
|
65
|
+
display: "flex",
|
|
66
|
+
alignItems: "center",
|
|
67
|
+
gap: 8,
|
|
68
|
+
width: "100%",
|
|
69
|
+
minWidth: 0
|
|
70
|
+
});
|
|
29
71
|
const StyledDropdown = styled(Dropdown)({
|
|
30
72
|
"& ul, & li": {
|
|
31
73
|
padding: 0,
|
|
32
74
|
margin: 0
|
|
75
|
+
},
|
|
76
|
+
"& .pf-v6-c-menu__item-main": {
|
|
77
|
+
width: "100%"
|
|
78
|
+
},
|
|
79
|
+
"& .pf-v6-c-menu__item-text": {
|
|
80
|
+
flex: "1 1 auto",
|
|
81
|
+
minWidth: 0,
|
|
82
|
+
overflow: "hidden"
|
|
83
|
+
},
|
|
84
|
+
// We render our own fixed tick column; hide PF's conditional select icon.
|
|
85
|
+
"& .pf-v6-c-menu__item-select-icon": {
|
|
86
|
+
display: "none"
|
|
33
87
|
}
|
|
34
88
|
});
|
|
35
89
|
const MessageBarModelSelector = ({
|
|
@@ -47,6 +101,14 @@ const MessageBarModelSelector = ({
|
|
|
47
101
|
}
|
|
48
102
|
}, [disabled]);
|
|
49
103
|
const selectedModelLabel = models.find((m) => m.value === selectedModel)?.label ?? selectedModel;
|
|
104
|
+
const visionScreenshotTooltip = useMemo(
|
|
105
|
+
() => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
106
|
+
t("modelSelector.visionScreenshot.line1"),
|
|
107
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
108
|
+
t("modelSelector.visionScreenshot.line2")
|
|
109
|
+
] }),
|
|
110
|
+
[t]
|
|
111
|
+
);
|
|
50
112
|
const toggle = (toggleRef) => /* @__PURE__ */ jsxs(
|
|
51
113
|
SelectorToggle,
|
|
52
114
|
{
|
|
@@ -78,15 +140,45 @@ const MessageBarModelSelector = ({
|
|
|
78
140
|
toggle,
|
|
79
141
|
isScrollable: models.length > 10,
|
|
80
142
|
maxMenuHeight: models.length > 10 ? "240px" : void 0,
|
|
81
|
-
children: /* @__PURE__ */ jsx(DropdownList, { children: models.map((model) =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
143
|
+
children: /* @__PURE__ */ jsx(DropdownList, { children: models.map((model) => {
|
|
144
|
+
const isSelected = selectedModel === model.value;
|
|
145
|
+
return /* @__PURE__ */ jsx(
|
|
146
|
+
DropdownItem,
|
|
147
|
+
{
|
|
148
|
+
value: model.value,
|
|
149
|
+
isSelected,
|
|
150
|
+
children: /* @__PURE__ */ jsxs(ModelItemContent, { children: [
|
|
151
|
+
/* @__PURE__ */ jsx(ModelLabel, { title: model.label, children: model.label }),
|
|
152
|
+
model.supportsVision ? /* @__PURE__ */ jsx(VisionSlot, { className: "lightspeed-model-vision-slot", children: /* @__PURE__ */ jsx(Tooltip, { content: visionScreenshotTooltip, children: /* @__PURE__ */ jsx(
|
|
153
|
+
VisionIndicatorWrap,
|
|
154
|
+
{
|
|
155
|
+
"aria-label": t(
|
|
156
|
+
"modelSelector.visionScreenshot.ariaLabel"
|
|
157
|
+
),
|
|
158
|
+
onClick: (event) => event.stopPropagation(),
|
|
159
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
160
|
+
children: /* @__PURE__ */ jsx(VisionIndicatorIcon, { "aria-hidden": true })
|
|
161
|
+
}
|
|
162
|
+
) }) }) : /* @__PURE__ */ jsx(
|
|
163
|
+
VisionSlot,
|
|
164
|
+
{
|
|
165
|
+
className: "lightspeed-model-vision-slot",
|
|
166
|
+
"aria-hidden": true
|
|
167
|
+
}
|
|
168
|
+
),
|
|
169
|
+
/* @__PURE__ */ jsx(
|
|
170
|
+
TickSlot,
|
|
171
|
+
{
|
|
172
|
+
className: "lightspeed-model-tick-slot",
|
|
173
|
+
"aria-hidden": !isSelected,
|
|
174
|
+
children: isSelected ? /* @__PURE__ */ jsx(CheckIcon, { "aria-hidden": true }) : null
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
] })
|
|
178
|
+
},
|
|
179
|
+
model.value
|
|
180
|
+
);
|
|
181
|
+
}) })
|
|
90
182
|
}
|
|
91
183
|
);
|
|
92
184
|
if (disabled && disabledTooltip) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageBarModelSelector.esm.js","sources":["../../src/components/MessageBarModelSelector.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 */\n\nimport { Ref, useEffect, useState } from 'react';\n\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\nimport {\n Dropdown,\n DropdownItem,\n DropdownList,\n MenuToggle,\n MenuToggleElement,\n Tooltip,\n} from '@patternfly/react-core';\nimport { AngleDownIcon } from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ntype MessageBarModelSelectorProps = {\n selectedModel: string;\n models: { label: string; value: string; provider: string }[];\n onSelect: (model: string) => void;\n disabled?: boolean;\n disabledTooltip?: string;\n};\n\nconst SelectorToggle = styled(MenuToggle)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n color: theme.palette.text.secondary,\n fontSize: 14,\n fontWeight: 500,\n cursor: 'pointer',\n padding: '4px 8px',\n borderRadius: 8,\n border: 'none',\n background: 'transparent',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n '&:disabled': {\n cursor: 'not-allowed',\n opacity: 0.5,\n },\n}));\n\nconst StyledDropdown = styled(Dropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nexport const MessageBarModelSelector = ({\n selectedModel,\n models,\n onSelect,\n disabled = false,\n disabledTooltip,\n}: MessageBarModelSelectorProps) => {\n const [isOpen, setIsOpen] = useState(false);\n const { t } = useTranslation();\n\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n const selectedModelLabel =\n models.find(m => m.value === selectedModel)?.label ?? selectedModel;\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <SelectorToggle\n ref={toggleRef}\n onClick={() => setIsOpen(!isOpen)}\n isExpanded={isOpen}\n isDisabled={disabled}\n variant=\"plain\"\n aria-label={t('aria.chatbotSelector')}\n >\n {selectedModelLabel}\n <AngleDownIcon />\n </SelectorToggle>\n );\n\n const dropdown = (\n <StyledDropdown\n isOpen={isOpen && !disabled}\n onSelect={(_e, value) => {\n if (disabled) return;\n onSelect(value as string);\n setIsOpen(false);\n }}\n onOpenChange={open => setIsOpen(open)}\n popperProps={{ position: 'left' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n isScrollable={models.length > 10}\n maxMenuHeight={models.length > 10 ? '240px' : undefined}\n >\n <DropdownList>\n {models.map(model => (\n <DropdownItem\n value={model.value}\n key={model.value}\n isSelected={selectedModel === model.value}\n >\n {model.label}\n </DropdownItem>\n ))}\n </DropdownList>\n </StyledDropdown>\n );\n\n if (disabled && disabledTooltip) {\n return (\n <Tooltip content={disabledTooltip}>\n <Typography component=\"span\">{dropdown}</Typography>\n </Tooltip>\n );\n }\n\n return dropdown;\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MessageBarModelSelector.esm.js","sources":["../../src/components/MessageBarModelSelector.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 */\n\nimport { Fragment, Ref, useEffect, useMemo, useState } from 'react';\n\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\nimport {\n Dropdown,\n DropdownItem,\n DropdownList,\n MenuToggle,\n MenuToggleElement,\n Tooltip,\n} from '@patternfly/react-core';\nimport {\n AngleDownIcon,\n CheckIcon,\n OutlinedImageIcon,\n} from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ntype MessageBarModelSelectorProps = {\n selectedModel: string;\n models: {\n label: string;\n value: string;\n provider: string;\n supportsVision?: boolean;\n }[];\n onSelect: (model: string) => void;\n disabled?: boolean;\n disabledTooltip?: string;\n};\n\nconst SelectorToggle = styled(MenuToggle)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n color: theme.palette.text.secondary,\n fontSize: 14,\n fontWeight: 500,\n cursor: 'pointer',\n padding: '4px 8px',\n borderRadius: 8,\n border: 'none',\n background: 'transparent',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n '&:disabled': {\n cursor: 'not-allowed',\n opacity: 0.5,\n },\n}));\n\nconst VisionIndicatorIcon = styled(OutlinedImageIcon)(({ theme }) => ({\n width: 16,\n height: 16,\n color: theme.palette.text.secondary,\n flexShrink: 0,\n}));\n\nconst VisionIndicatorWrap = styled('span')({\n display: 'inline-flex',\n alignItems: 'center',\n lineHeight: 1,\n});\n\n/** Fixed-width slot so vision icons align across rows (empty when unsupported). */\nconst VisionSlot = styled('span')({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: 16,\n height: 16,\n});\n\n/** Fixed-width slot so the select tick aligns across rows (empty when not selected). */\nconst TickSlot = styled('span')(({ theme }) => ({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '1em',\n height: '1em',\n color: theme.palette.primary.main,\n}));\n\nconst ModelLabel = styled('span')({\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n});\n\nconst ModelItemContent = styled('span')({\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n width: '100%',\n minWidth: 0,\n});\n\nconst StyledDropdown = styled(Dropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n '& .pf-v6-c-menu__item-main': {\n width: '100%',\n },\n '& .pf-v6-c-menu__item-text': {\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'hidden',\n },\n // We render our own fixed tick column; hide PF's conditional select icon.\n '& .pf-v6-c-menu__item-select-icon': {\n display: 'none',\n },\n});\n\nexport const MessageBarModelSelector = ({\n selectedModel,\n models,\n onSelect,\n disabled = false,\n disabledTooltip,\n}: MessageBarModelSelectorProps) => {\n const [isOpen, setIsOpen] = useState(false);\n const { t } = useTranslation();\n\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n const selectedModelLabel =\n models.find(m => m.value === selectedModel)?.label ?? selectedModel;\n\n const visionScreenshotTooltip = useMemo(\n () => (\n <Fragment>\n {t('modelSelector.visionScreenshot.line1')}\n <br />\n {t('modelSelector.visionScreenshot.line2')}\n </Fragment>\n ),\n [t],\n );\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <SelectorToggle\n ref={toggleRef}\n onClick={() => setIsOpen(!isOpen)}\n isExpanded={isOpen}\n isDisabled={disabled}\n variant=\"plain\"\n aria-label={t('aria.chatbotSelector')}\n >\n {selectedModelLabel}\n <AngleDownIcon />\n </SelectorToggle>\n );\n\n const dropdown = (\n <StyledDropdown\n isOpen={isOpen && !disabled}\n onSelect={(_e, value) => {\n if (disabled) return;\n onSelect(value as string);\n setIsOpen(false);\n }}\n onOpenChange={open => setIsOpen(open)}\n popperProps={{ position: 'left' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n isScrollable={models.length > 10}\n maxMenuHeight={models.length > 10 ? '240px' : undefined}\n >\n <DropdownList>\n {models.map(model => {\n const isSelected = selectedModel === model.value;\n return (\n <DropdownItem\n value={model.value}\n key={model.value}\n isSelected={isSelected}\n >\n <ModelItemContent>\n <ModelLabel title={model.label}>{model.label}</ModelLabel>\n {model.supportsVision ? (\n <VisionSlot className=\"lightspeed-model-vision-slot\">\n <Tooltip content={visionScreenshotTooltip}>\n <VisionIndicatorWrap\n aria-label={t(\n 'modelSelector.visionScreenshot.ariaLabel',\n )}\n onClick={event => event.stopPropagation()}\n onMouseDown={event => event.stopPropagation()}\n >\n <VisionIndicatorIcon aria-hidden />\n </VisionIndicatorWrap>\n </Tooltip>\n </VisionSlot>\n ) : (\n <VisionSlot\n className=\"lightspeed-model-vision-slot\"\n aria-hidden\n />\n )}\n <TickSlot\n className=\"lightspeed-model-tick-slot\"\n aria-hidden={!isSelected}\n >\n {isSelected ? <CheckIcon aria-hidden /> : null}\n </TickSlot>\n </ModelItemContent>\n </DropdownItem>\n );\n })}\n </DropdownList>\n </StyledDropdown>\n );\n\n if (disabled && disabledTooltip) {\n return (\n <Tooltip content={disabledTooltip}>\n <Typography component=\"span\">{dropdown}</Typography>\n </Tooltip>\n );\n }\n\n return dropdown;\n};\n"],"names":[],"mappings":";;;;;;;;AAiDA,MAAM,iBAAiB,MAAA,CAAO,UAAU,EAAE,CAAC,EAAE,OAAM,MAAO;AAAA,EACxD,OAAA,EAAS,MAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,GAAA,EAAK,CAAA;AAAA,EACL,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,EAC1B,QAAA,EAAU,EAAA;AAAA,EACV,UAAA,EAAY,GAAA;AAAA,EACZ,MAAA,EAAQ,SAAA;AAAA,EACR,OAAA,EAAS,SAAA;AAAA,EACT,YAAA,EAAc,CAAA;AAAA,EACd,MAAA,EAAQ,MAAA;AAAA,EACR,UAAA,EAAY,aAAA;AAAA,EACZ,SAAA,EAAW;AAAA,IACT,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO;AAAA,GACxC;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,MAAA,EAAQ,aAAA;AAAA,IACR,OAAA,EAAS;AAAA;AAEb,CAAA,CAAE,CAAA;AAEF,MAAM,sBAAsB,MAAA,CAAO,iBAAiB,EAAE,CAAC,EAAE,OAAM,MAAO;AAAA,EACpE,KAAA,EAAO,EAAA;AAAA,EACP,MAAA,EAAQ,EAAA;AAAA,EACR,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,EAC1B,UAAA,EAAY;AACd,CAAA,CAAE,CAAA;AAEF,MAAM,mBAAA,GAAsB,MAAA,CAAO,MAAM,CAAA,CAAE;AAAA,EACzC,OAAA,EAAS,aAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,UAAA,EAAY;AACd,CAAC,CAAA;AAGD,MAAM,UAAA,GAAa,MAAA,CAAO,MAAM,CAAA,CAAE;AAAA,EAChC,OAAA,EAAS,aAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,cAAA,EAAgB,QAAA;AAAA,EAChB,UAAA,EAAY,CAAA;AAAA,EACZ,KAAA,EAAO,EAAA;AAAA,EACP,MAAA,EAAQ;AACV,CAAC,CAAA;AAGD,MAAM,WAAW,MAAA,CAAO,MAAM,EAAE,CAAC,EAAE,OAAM,MAAO;AAAA,EAC9C,OAAA,EAAS,aAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,cAAA,EAAgB,QAAA;AAAA,EAChB,UAAA,EAAY,CAAA;AAAA,EACZ,KAAA,EAAO,KAAA;AAAA,EACP,MAAA,EAAQ,KAAA;AAAA,EACR,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ;AAC/B,CAAA,CAAE,CAAA;AAEF,MAAM,UAAA,GAAa,MAAA,CAAO,MAAM,CAAA,CAAE;AAAA,EAChC,IAAA,EAAM,UAAA;AAAA,EACN,QAAA,EAAU,CAAA;AAAA,EACV,QAAA,EAAU,QAAA;AAAA,EACV,YAAA,EAAc,UAAA;AAAA,EACd,UAAA,EAAY;AACd,CAAC,CAAA;AAED,MAAM,gBAAA,GAAmB,MAAA,CAAO,MAAM,CAAA,CAAE;AAAA,EACtC,OAAA,EAAS,MAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,GAAA,EAAK,CAAA;AAAA,EACL,KAAA,EAAO,MAAA;AAAA,EACP,QAAA,EAAU;AACZ,CAAC,CAAA;AAED,MAAM,cAAA,GAAiB,MAAA,CAAO,QAAQ,CAAA,CAAE;AAAA,EACtC,YAAA,EAAc;AAAA,IACZ,OAAA,EAAS,CAAA;AAAA,IACT,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,4BAAA,EAA8B;AAAA,IAC5B,KAAA,EAAO;AAAA,GACT;AAAA,EACA,4BAAA,EAA8B;AAAA,IAC5B,IAAA,EAAM,UAAA;AAAA,IACN,QAAA,EAAU,CAAA;AAAA,IACV,QAAA,EAAU;AAAA,GACZ;AAAA;AAAA,EAEA,mCAAA,EAAqC;AAAA,IACnC,OAAA,EAAS;AAAA;AAEb,CAAC,CAAA;AAEM,MAAM,0BAA0B,CAAC;AAAA,EACtC,aAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX;AACF,CAAA,KAAoC;AAClC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAC1C,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,SAAA,CAAU,KAAK,CAAA;AAAA,IACjB;AAAA,EACF,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,MAAM,kBAAA,GACJ,OAAO,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,KAAA,KAAU,aAAa,GAAG,KAAA,IAAS,aAAA;AAExD,EAAA,MAAM,uBAAA,GAA0B,OAAA;AAAA,IAC9B,2BACG,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,MAAA,CAAA,CAAE,sCAAsC,CAAA;AAAA,0BACxC,IAAA,EAAA,EAAG,CAAA;AAAA,MACH,EAAE,sCAAsC;AAAA,KAAA,EAC3C,CAAA;AAAA,IAEF,CAAC,CAAC;AAAA,GACJ;AAEA,EAAA,MAAM,MAAA,GAAS,CAAC,SAAA,qBACd,IAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,SAAA;AAAA,MACL,OAAA,EAAS,MAAM,SAAA,CAAU,CAAC,MAAM,CAAA;AAAA,MAChC,UAAA,EAAY,MAAA;AAAA,MACZ,UAAA,EAAY,QAAA;AAAA,MACZ,OAAA,EAAQ,OAAA;AAAA,MACR,YAAA,EAAY,EAAE,sBAAsB,CAAA;AAAA,MAEnC,QAAA,EAAA;AAAA,QAAA,kBAAA;AAAA,4BACA,aAAA,EAAA,EAAc;AAAA;AAAA;AAAA,GACjB;AAGF,EAAA,MAAM,QAAA,mBACJ,GAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,MAAA,EAAQ,UAAU,CAAC,QAAA;AAAA,MACnB,QAAA,EAAU,CAAC,EAAA,EAAI,KAAA,KAAU;AACvB,QAAA,IAAI,QAAA,EAAU;AACd,QAAA,QAAA,CAAS,KAAe,CAAA;AACxB,QAAA,SAAA,CAAU,KAAK,CAAA;AAAA,MACjB,CAAA;AAAA,MACA,YAAA,EAAc,CAAA,IAAA,KAAQ,SAAA,CAAU,IAAI,CAAA;AAAA,MACpC,WAAA,EAAa,EAAE,QAAA,EAAU,MAAA,EAAO;AAAA,MAChC,yBAAA,EAAyB,IAAA;AAAA,MACzB,0BAAA,EAA4B,KAAA;AAAA,MAC5B,MAAA;AAAA,MACA,YAAA,EAAc,OAAO,MAAA,GAAS,EAAA;AAAA,MAC9B,aAAA,EAAe,MAAA,CAAO,MAAA,GAAS,EAAA,GAAK,OAAA,GAAU,MAAA;AAAA,MAE9C,QAAA,kBAAA,GAAA,CAAC,YAAA,EAAA,EACE,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAA,KAAA,KAAS;AACnB,QAAA,MAAM,UAAA,GAAa,kBAAkB,KAAA,CAAM,KAAA;AAC3C,QAAA,uBACE,GAAA;AAAA,UAAC,YAAA;AAAA,UAAA;AAAA,YACC,OAAO,KAAA,CAAM,KAAA;AAAA,YAEb,UAAA;AAAA,YAEA,+BAAC,gBAAA,EAAA,EACC,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAO,KAAA,CAAM,KAAA,EAAQ,gBAAM,KAAA,EAAM,CAAA;AAAA,cAC5C,KAAA,CAAM,iCACL,GAAA,CAAC,UAAA,EAAA,EAAW,WAAU,8BAAA,EACpB,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,OAAA,EAAS,uBAAA,EAChB,QAAA,kBAAA,GAAA;AAAA,gBAAC,mBAAA;AAAA,gBAAA;AAAA,kBACC,YAAA,EAAY,CAAA;AAAA,oBACV;AAAA,mBACF;AAAA,kBACA,OAAA,EAAS,CAAA,KAAA,KAAS,KAAA,CAAM,eAAA,EAAgB;AAAA,kBACxC,WAAA,EAAa,CAAA,KAAA,KAAS,KAAA,CAAM,eAAA,EAAgB;AAAA,kBAE5C,QAAA,kBAAA,GAAA,CAAC,mBAAA,EAAA,EAAoB,aAAA,EAAW,IAAA,EAAC;AAAA;AAAA,eACnC,EACF,GACF,CAAA,mBAEA,GAAA;AAAA,gBAAC,UAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,8BAAA;AAAA,kBACV,aAAA,EAAW;AAAA;AAAA,eACb;AAAA,8BAEF,GAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,4BAAA;AAAA,kBACV,eAAa,CAAC,UAAA;AAAA,kBAEb,QAAA,EAAA,UAAA,mBAAa,GAAA,CAAC,SAAA,EAAA,EAAU,aAAA,EAAW,MAAC,CAAA,GAAK;AAAA;AAAA;AAC5C,aAAA,EACF;AAAA,WAAA;AAAA,UA/BK,KAAA,CAAM;AAAA,SAgCb;AAAA,MAEJ,CAAC,CAAA,EACH;AAAA;AAAA,GACF;AAGF,EAAA,IAAI,YAAY,eAAA,EAAiB;AAC/B,IAAA,uBACE,GAAA,CAAC,WAAQ,OAAA,EAAS,eAAA,EAChB,8BAAC,UAAA,EAAA,EAAW,SAAA,EAAU,MAAA,EAAQ,QAAA,EAAA,QAAA,EAAS,CAAA,EACzC,CAAA;AAAA,EAEJ;AAEA,EAAA,OAAO,QAAA;AACT;;;;"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { Tooltip, Content, ContentVariants } from '@patternfly/react-core';
|
|
3
|
+
import { makeStyles } from 'tss-react/mui';
|
|
4
|
+
import { SavedPromptKebabMenu } from './SavedPromptKebabMenu.esm.js';
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles()((theme) => ({
|
|
7
|
+
card: {
|
|
8
|
+
padding: `${theme.spacing(1.5)} 0`
|
|
9
|
+
},
|
|
10
|
+
cardDivider: {
|
|
11
|
+
borderBottom: "1px solid var(--pf-t--global--border--color--default)"
|
|
12
|
+
},
|
|
13
|
+
row: {
|
|
14
|
+
display: "flex",
|
|
15
|
+
alignItems: "flex-start"
|
|
16
|
+
},
|
|
17
|
+
content: {
|
|
18
|
+
flex: "1 1 0%",
|
|
19
|
+
minWidth: 0
|
|
20
|
+
},
|
|
21
|
+
title: {
|
|
22
|
+
display: "block",
|
|
23
|
+
minWidth: 0,
|
|
24
|
+
maxWidth: "100%",
|
|
25
|
+
margin: 0,
|
|
26
|
+
marginBottom: theme.spacing(0.5),
|
|
27
|
+
fontWeight: 600,
|
|
28
|
+
overflow: "hidden",
|
|
29
|
+
textOverflow: "ellipsis",
|
|
30
|
+
whiteSpace: "nowrap"
|
|
31
|
+
},
|
|
32
|
+
body: {
|
|
33
|
+
margin: 0,
|
|
34
|
+
marginBottom: theme.spacing(0.5),
|
|
35
|
+
color: "var(--pf-t--global--text--color--subtle) !important",
|
|
36
|
+
overflow: "hidden",
|
|
37
|
+
textOverflow: "ellipsis",
|
|
38
|
+
display: "-webkit-box",
|
|
39
|
+
WebkitLineClamp: 2,
|
|
40
|
+
WebkitBoxOrient: "vertical"
|
|
41
|
+
},
|
|
42
|
+
date: {
|
|
43
|
+
margin: 0,
|
|
44
|
+
color: "var(--pf-t--global--text--color--disabled) !important"
|
|
45
|
+
},
|
|
46
|
+
actions: {
|
|
47
|
+
flexShrink: 0
|
|
48
|
+
}
|
|
49
|
+
}));
|
|
50
|
+
const formatSavedDate = (isoDate) => {
|
|
51
|
+
const date = new Date(isoDate);
|
|
52
|
+
if (Number.isNaN(date.getTime())) {
|
|
53
|
+
return isoDate;
|
|
54
|
+
}
|
|
55
|
+
return date.toLocaleDateString(void 0, {
|
|
56
|
+
month: "numeric",
|
|
57
|
+
day: "numeric",
|
|
58
|
+
year: "numeric"
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
const SavedPromptCard = ({
|
|
62
|
+
prompt,
|
|
63
|
+
variant,
|
|
64
|
+
showDivider = false,
|
|
65
|
+
onApplyToInput,
|
|
66
|
+
onSendDirectly,
|
|
67
|
+
onDelete,
|
|
68
|
+
isSendDirectlyDisabled
|
|
69
|
+
}) => {
|
|
70
|
+
const { classes, cx } = useStyles();
|
|
71
|
+
return /* @__PURE__ */ jsx(
|
|
72
|
+
"div",
|
|
73
|
+
{
|
|
74
|
+
className: cx(classes.card, showDivider && classes.cardDivider),
|
|
75
|
+
"data-testid": `saved-prompt-card-${prompt.id}`,
|
|
76
|
+
"data-has-divider": showDivider ? "true" : "false",
|
|
77
|
+
children: /* @__PURE__ */ jsxs("div", { className: classes.row, children: [
|
|
78
|
+
/* @__PURE__ */ jsxs("div", { className: classes.content, children: [
|
|
79
|
+
/* @__PURE__ */ jsx(Tooltip, { content: prompt.name, children: /* @__PURE__ */ jsx("span", { className: classes.title, children: prompt.name }) }),
|
|
80
|
+
/* @__PURE__ */ jsx(Tooltip, { content: prompt.content, children: /* @__PURE__ */ jsx(Content, { component: ContentVariants.p, className: classes.body, children: prompt.content }) }),
|
|
81
|
+
/* @__PURE__ */ jsx(Content, { component: ContentVariants.small, className: classes.date, children: formatSavedDate(prompt.created_at) })
|
|
82
|
+
] }),
|
|
83
|
+
/* @__PURE__ */ jsx("div", { className: classes.actions, children: /* @__PURE__ */ jsx(
|
|
84
|
+
SavedPromptKebabMenu,
|
|
85
|
+
{
|
|
86
|
+
prompt,
|
|
87
|
+
variant,
|
|
88
|
+
onApplyToInput,
|
|
89
|
+
onSendDirectly,
|
|
90
|
+
onDelete,
|
|
91
|
+
isSendDirectlyDisabled
|
|
92
|
+
}
|
|
93
|
+
) })
|
|
94
|
+
] })
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export { SavedPromptCard };
|
|
100
|
+
//# sourceMappingURL=SavedPromptCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SavedPromptCard.esm.js","sources":["../../src/components/SavedPromptCard.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 { Content, ContentVariants, Tooltip } from '@patternfly/react-core';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport {\n SavedPromptKebabMenu,\n SavedPromptKebabVariant,\n} from './SavedPromptKebabMenu';\n\ntype SavedPromptCardProps = {\n prompt: SavedPrompt;\n variant: SavedPromptKebabVariant;\n showDivider?: boolean;\n onApplyToInput?: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (prompt: SavedPrompt) => void;\n isSendDirectlyDisabled?: boolean;\n};\n\nconst useStyles = makeStyles()(theme => ({\n card: {\n padding: `${theme.spacing(1.5)} 0`,\n },\n cardDivider: {\n borderBottom: '1px solid var(--pf-t--global--border--color--default)',\n },\n row: {\n display: 'flex',\n alignItems: 'flex-start',\n },\n content: {\n flex: '1 1 0%',\n minWidth: 0,\n },\n title: {\n display: 'block',\n minWidth: 0,\n maxWidth: '100%',\n margin: 0,\n marginBottom: theme.spacing(0.5),\n fontWeight: 600,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n body: {\n margin: 0,\n marginBottom: theme.spacing(0.5),\n color: 'var(--pf-t--global--text--color--subtle) !important',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n },\n date: {\n margin: 0,\n color: 'var(--pf-t--global--text--color--disabled) !important',\n },\n actions: {\n flexShrink: 0,\n },\n}));\n\nconst formatSavedDate = (isoDate: string): string => {\n const date = new Date(isoDate);\n if (Number.isNaN(date.getTime())) {\n return isoDate;\n }\n return date.toLocaleDateString(undefined, {\n month: 'numeric',\n day: 'numeric',\n year: 'numeric',\n });\n};\n\nexport const SavedPromptCard = ({\n prompt,\n variant,\n showDivider = false,\n onApplyToInput,\n onSendDirectly,\n onDelete,\n isSendDirectlyDisabled,\n}: SavedPromptCardProps) => {\n const { classes, cx } = useStyles();\n\n return (\n <div\n className={cx(classes.card, showDivider && classes.cardDivider)}\n data-testid={`saved-prompt-card-${prompt.id}`}\n data-has-divider={showDivider ? 'true' : 'false'}\n >\n <div className={classes.row}>\n <div className={classes.content}>\n <Tooltip content={prompt.name}>\n <span className={classes.title}>{prompt.name}</span>\n </Tooltip>\n <Tooltip content={prompt.content}>\n <Content component={ContentVariants.p} className={classes.body}>\n {prompt.content}\n </Content>\n </Tooltip>\n <Content component={ContentVariants.small} className={classes.date}>\n {formatSavedDate(prompt.created_at)}\n </Content>\n </div>\n <div className={classes.actions}>\n <SavedPromptKebabMenu\n prompt={prompt}\n variant={variant}\n onApplyToInput={onApplyToInput}\n onSendDirectly={onSendDirectly}\n onDelete={onDelete}\n isSendDirectlyDisabled={isSendDirectlyDisabled}\n />\n </div>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Dropdown, DropdownList, MenuToggle } from '@patternfly/react-core';
|
|
4
|
+
import { EllipsisHIcon } from '@patternfly/react-icons';
|
|
5
|
+
import { makeStyles } from 'tss-react/mui';
|
|
6
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
7
|
+
import { SavedPromptMenuItems } from './SavedPromptMenuItems.esm.js';
|
|
8
|
+
|
|
9
|
+
const useStyles = makeStyles()(() => ({
|
|
10
|
+
menuButton: {
|
|
11
|
+
padding: 4
|
|
12
|
+
}
|
|
13
|
+
}));
|
|
14
|
+
const SavedPromptMenuToggle = ({
|
|
15
|
+
toggleRef,
|
|
16
|
+
promptName,
|
|
17
|
+
isOpen,
|
|
18
|
+
menuButtonClassName,
|
|
19
|
+
onToggle
|
|
20
|
+
}) => {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
return /* @__PURE__ */ jsx(
|
|
23
|
+
MenuToggle,
|
|
24
|
+
{
|
|
25
|
+
ref: toggleRef,
|
|
26
|
+
variant: "plain",
|
|
27
|
+
className: menuButtonClassName,
|
|
28
|
+
"aria-label": t("savedPrompts.actions.menuAriaLabel", {
|
|
29
|
+
name: promptName
|
|
30
|
+
}),
|
|
31
|
+
isExpanded: isOpen,
|
|
32
|
+
onClick: onToggle,
|
|
33
|
+
children: /* @__PURE__ */ jsx(EllipsisHIcon, {})
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
const SavedPromptKebabMenu = ({
|
|
38
|
+
prompt,
|
|
39
|
+
variant,
|
|
40
|
+
onApplyToInput,
|
|
41
|
+
onSendDirectly,
|
|
42
|
+
onDelete,
|
|
43
|
+
isSendDirectlyDisabled = false
|
|
44
|
+
}) => {
|
|
45
|
+
const { classes } = useStyles();
|
|
46
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
47
|
+
const closeMenu = () => setIsOpen(false);
|
|
48
|
+
return /* @__PURE__ */ jsx(
|
|
49
|
+
Dropdown,
|
|
50
|
+
{
|
|
51
|
+
isOpen,
|
|
52
|
+
popperProps: {
|
|
53
|
+
position: "end",
|
|
54
|
+
preventOverflow: true
|
|
55
|
+
},
|
|
56
|
+
onOpenChange: setIsOpen,
|
|
57
|
+
toggle: (toggleRef) => /* @__PURE__ */ jsx(
|
|
58
|
+
SavedPromptMenuToggle,
|
|
59
|
+
{
|
|
60
|
+
toggleRef,
|
|
61
|
+
promptName: prompt.name,
|
|
62
|
+
isOpen,
|
|
63
|
+
menuButtonClassName: classes.menuButton,
|
|
64
|
+
onToggle: (event) => {
|
|
65
|
+
event.stopPropagation();
|
|
66
|
+
setIsOpen((current) => !current);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
),
|
|
70
|
+
children: /* @__PURE__ */ jsx(DropdownList, { style: { paddingInlineStart: 0 }, children: /* @__PURE__ */ jsx(
|
|
71
|
+
SavedPromptMenuItems,
|
|
72
|
+
{
|
|
73
|
+
prompt,
|
|
74
|
+
variant,
|
|
75
|
+
onApplyToInput,
|
|
76
|
+
onSendDirectly,
|
|
77
|
+
onDelete,
|
|
78
|
+
isSendDirectlyDisabled,
|
|
79
|
+
closeMenu
|
|
80
|
+
}
|
|
81
|
+
) })
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export { SavedPromptKebabMenu };
|
|
87
|
+
//# sourceMappingURL=SavedPromptKebabMenu.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SavedPromptKebabMenu.esm.js","sources":["../../src/components/SavedPromptKebabMenu.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 { useState, type MouseEvent, type Ref } from 'react';\n\nimport {\n Dropdown,\n DropdownList,\n MenuToggle,\n type MenuToggleElement,\n} from '@patternfly/react-core';\nimport { EllipsisHIcon } from '@patternfly/react-icons';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { SavedPromptMenuItems } from './SavedPromptMenuItems';\n\nexport type SavedPromptKebabVariant = 'settings' | 'sidebar';\n\ntype SavedPromptKebabMenuProps = {\n prompt: SavedPrompt;\n variant: SavedPromptKebabVariant;\n onApplyToInput?: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (prompt: SavedPrompt) => void;\n isSendDirectlyDisabled?: boolean;\n};\n\nconst useStyles = makeStyles()(() => ({\n menuButton: {\n padding: 4,\n },\n}));\n\ntype SavedPromptMenuToggleProps = {\n toggleRef: Ref<MenuToggleElement>;\n promptName: string;\n isOpen: boolean;\n menuButtonClassName: string;\n onToggle: (event: MouseEvent) => void;\n};\n\nconst SavedPromptMenuToggle = ({\n toggleRef,\n promptName,\n isOpen,\n menuButtonClassName,\n onToggle,\n}: SavedPromptMenuToggleProps) => {\n const { t } = useTranslation();\n\n return (\n <MenuToggle\n ref={toggleRef}\n variant=\"plain\"\n className={menuButtonClassName}\n aria-label={t('savedPrompts.actions.menuAriaLabel' as any, {\n name: promptName,\n })}\n isExpanded={isOpen}\n onClick={onToggle}\n >\n <EllipsisHIcon />\n </MenuToggle>\n );\n};\n\nexport const SavedPromptKebabMenu = ({\n prompt,\n variant,\n onApplyToInput,\n onSendDirectly,\n onDelete,\n isSendDirectlyDisabled = false,\n}: SavedPromptKebabMenuProps) => {\n const { classes } = useStyles();\n const [isOpen, setIsOpen] = useState(false);\n\n const closeMenu = () => setIsOpen(false);\n\n return (\n <Dropdown\n isOpen={isOpen}\n popperProps={{\n position: 'end',\n preventOverflow: true,\n }}\n onOpenChange={setIsOpen}\n toggle={toggleRef => (\n <SavedPromptMenuToggle\n toggleRef={toggleRef}\n promptName={prompt.name}\n isOpen={isOpen}\n menuButtonClassName={classes.menuButton}\n onToggle={event => {\n event.stopPropagation();\n setIsOpen(current => !current);\n }}\n />\n )}\n >\n <DropdownList style={{ paddingInlineStart: 0 }}>\n <SavedPromptMenuItems\n prompt={prompt}\n variant={variant}\n onApplyToInput={onApplyToInput}\n onSendDirectly={onSendDirectly}\n onDelete={onDelete}\n isSendDirectlyDisabled={isSendDirectlyDisabled}\n closeMenu={closeMenu}\n />\n </DropdownList>\n </Dropdown>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA0CA,MAAM,SAAA,GAAY,UAAA,EAAW,CAAE,OAAO;AAAA,EACpC,UAAA,EAAY;AAAA,IACV,OAAA,EAAS;AAAA;AAEb,CAAA,CAAE,CAAA;AAUF,MAAM,wBAAwB,CAAC;AAAA,EAC7B,SAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,mBAAA;AAAA,EACA;AACF,CAAA,KAAkC;AAChC,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,SAAA;AAAA,MACL,OAAA,EAAQ,OAAA;AAAA,MACR,SAAA,EAAW,mBAAA;AAAA,MACX,YAAA,EAAY,EAAE,oCAAA,EAA6C;AAAA,QACzD,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,MACD,UAAA,EAAY,MAAA;AAAA,MACZ,OAAA,EAAS,QAAA;AAAA,MAET,8BAAC,aAAA,EAAA,EAAc;AAAA;AAAA,GACjB;AAEJ,CAAA;AAEO,MAAM,uBAAuB,CAAC;AAAA,EACnC,MAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,sBAAA,GAAyB;AAC3B,CAAA,KAAiC;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,SAAA,EAAU;AAC9B,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAE1C,EAAA,MAAM,SAAA,GAAY,MAAM,SAAA,CAAU,KAAK,CAAA;AAEvC,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,MAAA;AAAA,MACA,WAAA,EAAa;AAAA,QACX,QAAA,EAAU,KAAA;AAAA,QACV,eAAA,EAAiB;AAAA,OACnB;AAAA,MACA,YAAA,EAAc,SAAA;AAAA,MACd,QAAQ,CAAA,SAAA,qBACN,GAAA;AAAA,QAAC,qBAAA;AAAA,QAAA;AAAA,UACC,SAAA;AAAA,UACA,YAAY,MAAA,CAAO,IAAA;AAAA,UACnB,MAAA;AAAA,UACA,qBAAqB,OAAA,CAAQ,UAAA;AAAA,UAC7B,UAAU,CAAA,KAAA,KAAS;AACjB,YAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,YAAA,SAAA,CAAU,CAAA,OAAA,KAAW,CAAC,OAAO,CAAA;AAAA,UAC/B;AAAA;AAAA,OACF;AAAA,MAGF,8BAAC,YAAA,EAAA,EAAa,KAAA,EAAO,EAAE,kBAAA,EAAoB,GAAE,EAC3C,QAAA,kBAAA,GAAA;AAAA,QAAC,oBAAA;AAAA,QAAA;AAAA,UACC,MAAA;AAAA,UACA,OAAA;AAAA,UACA,cAAA;AAAA,UACA,cAAA;AAAA,UACA,QAAA;AAAA,UACA,sBAAA;AAAA,UACA;AAAA;AAAA,OACF,EACF;AAAA;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { DropdownItem } from '@patternfly/react-core';
|
|
3
|
+
import { ArrowRightIcon, PaperPlaneIcon, TrashIcon } from '@patternfly/react-icons';
|
|
4
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
5
|
+
|
|
6
|
+
const SavedPromptMenuItems = ({
|
|
7
|
+
prompt,
|
|
8
|
+
variant,
|
|
9
|
+
onApplyToInput,
|
|
10
|
+
onSendDirectly,
|
|
11
|
+
onDelete,
|
|
12
|
+
isSendDirectlyDisabled = false,
|
|
13
|
+
closeMenu
|
|
14
|
+
}) => {
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
const handleAction = (action) => (event) => {
|
|
17
|
+
event.stopPropagation();
|
|
18
|
+
action();
|
|
19
|
+
closeMenu?.();
|
|
20
|
+
};
|
|
21
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
22
|
+
variant === "settings" && onApplyToInput && /* @__PURE__ */ jsx(
|
|
23
|
+
DropdownItem,
|
|
24
|
+
{
|
|
25
|
+
icon: /* @__PURE__ */ jsx(ArrowRightIcon, {}),
|
|
26
|
+
onClick: handleAction(() => onApplyToInput(prompt.content)),
|
|
27
|
+
children: t("savedPrompts.actions.apply")
|
|
28
|
+
}
|
|
29
|
+
),
|
|
30
|
+
/* @__PURE__ */ jsx(
|
|
31
|
+
DropdownItem,
|
|
32
|
+
{
|
|
33
|
+
icon: /* @__PURE__ */ jsx(PaperPlaneIcon, {}),
|
|
34
|
+
isDisabled: isSendDirectlyDisabled,
|
|
35
|
+
description: isSendDirectlyDisabled ? t("savedPrompts.actions.sendDisabledStreaming") : void 0,
|
|
36
|
+
onClick: handleAction(() => onSendDirectly(prompt.content)),
|
|
37
|
+
children: t("savedPrompts.actions.send")
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
/* @__PURE__ */ jsx(
|
|
41
|
+
DropdownItem,
|
|
42
|
+
{
|
|
43
|
+
icon: /* @__PURE__ */ jsx(TrashIcon, {}),
|
|
44
|
+
onClick: handleAction(() => onDelete(prompt)),
|
|
45
|
+
children: t("savedPrompts.actions.delete")
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
] });
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { SavedPromptMenuItems };
|
|
52
|
+
//# sourceMappingURL=SavedPromptMenuItems.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SavedPromptMenuItems.esm.js","sources":["../../src/components/SavedPromptMenuItems.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 { MouseEvent } from 'react';\n\nimport { DropdownItem } from '@patternfly/react-core';\nimport {\n ArrowRightIcon,\n PaperPlaneIcon,\n TrashIcon,\n} from '@patternfly/react-icons';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { SavedPromptKebabVariant } from './SavedPromptKebabMenu';\n\ntype SavedPromptMenuItemsProps = {\n prompt: SavedPrompt;\n variant: SavedPromptKebabVariant;\n onApplyToInput?: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (prompt: SavedPrompt) => void;\n isSendDirectlyDisabled?: boolean;\n closeMenu?: () => void;\n};\n\nexport const SavedPromptMenuItems = ({\n prompt,\n variant,\n onApplyToInput,\n onSendDirectly,\n onDelete,\n isSendDirectlyDisabled = false,\n closeMenu,\n}: SavedPromptMenuItemsProps) => {\n const { t } = useTranslation();\n\n const handleAction = (action: () => void) => (event: MouseEvent) => {\n event.stopPropagation();\n action();\n closeMenu?.();\n };\n\n return (\n <>\n {variant === 'settings' && onApplyToInput && (\n <DropdownItem\n icon={<ArrowRightIcon />}\n onClick={handleAction(() => onApplyToInput(prompt.content))}\n >\n {t('savedPrompts.actions.apply')}\n </DropdownItem>\n )}\n <DropdownItem\n icon={<PaperPlaneIcon />}\n isDisabled={isSendDirectlyDisabled}\n description={\n isSendDirectlyDisabled\n ? t('savedPrompts.actions.sendDisabledStreaming')\n : undefined\n }\n onClick={handleAction(() => onSendDirectly(prompt.content))}\n >\n {t('savedPrompts.actions.send')}\n </DropdownItem>\n <DropdownItem\n icon={<TrashIcon />}\n onClick={handleAction(() => onDelete(prompt))}\n >\n {t('savedPrompts.actions.delete')}\n </DropdownItem>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;AAuCO,MAAM,uBAAuB,CAAC;AAAA,EACnC,MAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,sBAAA,GAAyB,KAAA;AAAA,EACzB;AACF,CAAA,KAAiC;AAC/B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,MAAM,YAAA,GAAe,CAAC,MAAA,KAAuB,CAAC,KAAA,KAAsB;AAClE,IAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,IAAA,MAAA,EAAO;AACP,IAAA,SAAA,IAAY;AAAA,EACd,CAAA;AAEA,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,OAAA,KAAY,cAAc,cAAA,oBACzB,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,IAAA,sBAAO,cAAA,EAAA,EAAe,CAAA;AAAA,QACtB,SAAS,YAAA,CAAa,MAAM,cAAA,CAAe,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,QAEzD,YAAE,4BAA4B;AAAA;AAAA,KACjC;AAAA,oBAEF,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,IAAA,sBAAO,cAAA,EAAA,EAAe,CAAA;AAAA,QACtB,UAAA,EAAY,sBAAA;AAAA,QACZ,WAAA,EACE,sBAAA,GACI,CAAA,CAAE,4CAA4C,CAAA,GAC9C,MAAA;AAAA,QAEN,SAAS,YAAA,CAAa,MAAM,cAAA,CAAe,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,QAEzD,YAAE,2BAA2B;AAAA;AAAA,KAChC;AAAA,oBACA,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,IAAA,sBAAO,SAAA,EAAA,EAAU,CAAA;AAAA,QACjB,OAAA,EAAS,YAAA,CAAa,MAAM,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,QAE3C,YAAE,6BAA6B;AAAA;AAAA;AAClC,GAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { Content, ContentVariants, Button } from '@patternfly/react-core';
|
|
3
|
+
import { FileAltIcon } from '@patternfly/react-icons';
|
|
4
|
+
import { makeStyles } from 'tss-react/mui';
|
|
5
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
6
|
+
|
|
7
|
+
const useStyles = makeStyles()((theme) => ({
|
|
8
|
+
root: {
|
|
9
|
+
flex: 1,
|
|
10
|
+
display: "flex",
|
|
11
|
+
flexDirection: "column",
|
|
12
|
+
alignItems: "center",
|
|
13
|
+
textAlign: "center",
|
|
14
|
+
padding: theme.spacing(3, 2)
|
|
15
|
+
},
|
|
16
|
+
inner: {
|
|
17
|
+
display: "flex",
|
|
18
|
+
flexDirection: "column",
|
|
19
|
+
alignItems: "center",
|
|
20
|
+
maxWidth: 420
|
|
21
|
+
},
|
|
22
|
+
icon: {
|
|
23
|
+
fontSize: 48,
|
|
24
|
+
color: "var(--pf-t--global--icon--color--subtle)",
|
|
25
|
+
marginBottom: theme.spacing(1.5)
|
|
26
|
+
},
|
|
27
|
+
title: {
|
|
28
|
+
margin: 0,
|
|
29
|
+
marginBottom: theme.spacing(1),
|
|
30
|
+
fontWeight: 600
|
|
31
|
+
},
|
|
32
|
+
description: {
|
|
33
|
+
margin: 0,
|
|
34
|
+
marginBottom: theme.spacing(3),
|
|
35
|
+
color: "var(--pf-t--global--text--color--subtle)"
|
|
36
|
+
},
|
|
37
|
+
action: {
|
|
38
|
+
borderRadius: 999
|
|
39
|
+
}
|
|
40
|
+
}));
|
|
41
|
+
const SavedPromptsEmptyState = ({
|
|
42
|
+
onNewPrompt
|
|
43
|
+
}) => {
|
|
44
|
+
const { classes } = useStyles();
|
|
45
|
+
const { t } = useTranslation();
|
|
46
|
+
return /* @__PURE__ */ jsx("div", { className: classes.root, "data-testid": "saved-prompts-empty-state", children: /* @__PURE__ */ jsxs("div", { className: classes.inner, children: [
|
|
47
|
+
/* @__PURE__ */ jsx(FileAltIcon, { className: classes.icon, "aria-hidden": true }),
|
|
48
|
+
/* @__PURE__ */ jsx(Content, { component: ContentVariants.p, className: classes.title, children: t("savedPrompts.count.zero") }),
|
|
49
|
+
/* @__PURE__ */ jsx(Content, { component: ContentVariants.p, className: classes.description, children: t("savedPrompts.empty.description") }),
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
Button,
|
|
52
|
+
{
|
|
53
|
+
variant: "secondary",
|
|
54
|
+
className: classes.action,
|
|
55
|
+
onClick: onNewPrompt,
|
|
56
|
+
children: t("savedPrompts.newPrompt")
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
] }) });
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export { SavedPromptsEmptyState };
|
|
63
|
+
//# sourceMappingURL=SavedPromptsEmptyState.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SavedPromptsEmptyState.esm.js","sources":["../../src/components/SavedPromptsEmptyState.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, Content, ContentVariants } from '@patternfly/react-core';\nimport { FileAltIcon } from '@patternfly/react-icons';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ntype SavedPromptsEmptyStateProps = {\n onNewPrompt: () => void;\n};\n\nconst useStyles = makeStyles()(theme => ({\n root: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n padding: theme.spacing(3, 2),\n },\n inner: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n maxWidth: 420,\n },\n icon: {\n fontSize: 48,\n color: 'var(--pf-t--global--icon--color--subtle)',\n marginBottom: theme.spacing(1.5),\n },\n title: {\n margin: 0,\n marginBottom: theme.spacing(1),\n fontWeight: 600,\n },\n description: {\n margin: 0,\n marginBottom: theme.spacing(3),\n color: 'var(--pf-t--global--text--color--subtle)',\n },\n action: {\n borderRadius: 999,\n },\n}));\n\nexport const SavedPromptsEmptyState = ({\n onNewPrompt,\n}: SavedPromptsEmptyStateProps) => {\n const { classes } = useStyles();\n const { t } = useTranslation();\n\n return (\n <div className={classes.root} data-testid=\"saved-prompts-empty-state\">\n <div className={classes.inner}>\n <FileAltIcon className={classes.icon} aria-hidden />\n <Content component={ContentVariants.p} className={classes.title}>\n {t('savedPrompts.count.zero')}\n </Content>\n <Content component={ContentVariants.p} className={classes.description}>\n {t('savedPrompts.empty.description')}\n </Content>\n <Button\n variant=\"secondary\"\n className={classes.action}\n onClick={onNewPrompt}\n >\n {t('savedPrompts.newPrompt')}\n </Button>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;AAyBA,MAAM,SAAA,GAAY,UAAA,EAAW,CAAE,CAAA,KAAA,MAAU;AAAA,EACvC,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,CAAA;AAAA,IACN,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,SAAA,EAAW,QAAA;AAAA,IACX,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAA,EAAG,CAAC;AAAA,GAC7B;AAAA,EACA,KAAA,EAAO;AAAA,IACL,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,QAAA,EAAU,EAAA;AAAA,IACV,KAAA,EAAO,0CAAA;AAAA,IACP,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,GAAG;AAAA,GACjC;AAAA,EACA,KAAA,EAAO;AAAA,IACL,MAAA,EAAQ,CAAA;AAAA,IACR,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,UAAA,EAAY;AAAA,GACd;AAAA,EACA,WAAA,EAAa;AAAA,IACX,MAAA,EAAQ,CAAA;AAAA,IACR,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,KAAA,EAAO;AAAA,GACT;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,YAAA,EAAc;AAAA;AAElB,CAAA,CAAE,CAAA;AAEK,MAAM,yBAAyB,CAAC;AAAA,EACrC;AACF,CAAA,KAAmC;AACjC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,SAAA,EAAU;AAC9B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,IAAA,EAAM,aAAA,EAAY,2BAAA,EACxC,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,KAAA,EACtB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAW,OAAA,CAAQ,IAAA,EAAM,eAAW,IAAA,EAAC,CAAA;AAAA,oBAClD,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAW,eAAA,CAAgB,CAAA,EAAG,WAAW,OAAA,CAAQ,KAAA,EACvD,QAAA,EAAA,CAAA,CAAE,yBAAyB,CAAA,EAC9B,CAAA;AAAA,oBACA,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAW,eAAA,CAAgB,CAAA,EAAG,WAAW,OAAA,CAAQ,WAAA,EACvD,QAAA,EAAA,CAAA,CAAE,gCAAgC,CAAA,EACrC,CAAA;AAAA,oBACA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,WAAA;AAAA,QACR,WAAW,OAAA,CAAQ,MAAA;AAAA,QACnB,OAAA,EAAS,WAAA;AAAA,QAER,YAAE,wBAAwB;AAAA;AAAA;AAC7B,GAAA,EACF,CAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Spinner, Alert } from '@patternfly/react-core';
|
|
3
|
+
import { makeStyles } from 'tss-react/mui';
|
|
4
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
5
|
+
import { SavedPromptCard } from './SavedPromptCard.esm.js';
|
|
6
|
+
|
|
7
|
+
const useStyles = makeStyles()((theme) => ({
|
|
8
|
+
root: {
|
|
9
|
+
display: "flex",
|
|
10
|
+
flexDirection: "column"
|
|
11
|
+
},
|
|
12
|
+
loading: {
|
|
13
|
+
display: "flex",
|
|
14
|
+
justifyContent: "center",
|
|
15
|
+
padding: theme.spacing(3)
|
|
16
|
+
}
|
|
17
|
+
}));
|
|
18
|
+
const SavedPromptsList = ({
|
|
19
|
+
prompts,
|
|
20
|
+
loading,
|
|
21
|
+
error,
|
|
22
|
+
variant = "settings",
|
|
23
|
+
onApplyToInput,
|
|
24
|
+
onSendDirectly,
|
|
25
|
+
onDelete,
|
|
26
|
+
isSendDirectlyDisabled
|
|
27
|
+
}) => {
|
|
28
|
+
const { classes } = useStyles();
|
|
29
|
+
const { t } = useTranslation();
|
|
30
|
+
if (loading) {
|
|
31
|
+
return /* @__PURE__ */ jsx("div", { className: classes.loading, "data-testid": "saved-prompts-list-loading", children: /* @__PURE__ */ jsx(Spinner, { size: "lg", "aria-label": t("common.loading") }) });
|
|
32
|
+
}
|
|
33
|
+
if (error) {
|
|
34
|
+
return /* @__PURE__ */ jsx(
|
|
35
|
+
Alert,
|
|
36
|
+
{
|
|
37
|
+
variant: "danger",
|
|
38
|
+
isInline: true,
|
|
39
|
+
title: error,
|
|
40
|
+
"data-testid": "saved-prompts-list-error"
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
if (prompts.length === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return /* @__PURE__ */ jsx("div", { className: classes.root, "data-testid": "saved-prompts-list", children: prompts.map((prompt, index) => /* @__PURE__ */ jsx(
|
|
48
|
+
SavedPromptCard,
|
|
49
|
+
{
|
|
50
|
+
prompt,
|
|
51
|
+
variant,
|
|
52
|
+
showDivider: index < prompts.length - 1,
|
|
53
|
+
onApplyToInput,
|
|
54
|
+
onSendDirectly,
|
|
55
|
+
onDelete,
|
|
56
|
+
isSendDirectlyDisabled
|
|
57
|
+
},
|
|
58
|
+
prompt.id
|
|
59
|
+
)) });
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export { SavedPromptsList };
|
|
63
|
+
//# sourceMappingURL=SavedPromptsList.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SavedPromptsList.esm.js","sources":["../../src/components/SavedPromptsList.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 { Alert, Spinner } from '@patternfly/react-core';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { SavedPromptCard } from './SavedPromptCard';\nimport { SavedPromptKebabVariant } from './SavedPromptKebabMenu';\n\ntype SavedPromptsListProps = {\n prompts: SavedPrompt[];\n loading: boolean;\n error: string | null;\n variant?: SavedPromptKebabVariant;\n onApplyToInput?: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (prompt: SavedPrompt) => void;\n isSendDirectlyDisabled?: boolean;\n};\n\nconst useStyles = makeStyles()(theme => ({\n root: {\n display: 'flex',\n flexDirection: 'column',\n },\n loading: {\n display: 'flex',\n justifyContent: 'center',\n padding: theme.spacing(3),\n },\n}));\n\nexport const SavedPromptsList = ({\n prompts,\n loading,\n error,\n variant = 'settings',\n onApplyToInput,\n onSendDirectly,\n onDelete,\n isSendDirectlyDisabled,\n}: SavedPromptsListProps) => {\n const { classes } = useStyles();\n const { t } = useTranslation();\n\n if (loading) {\n return (\n <div className={classes.loading} data-testid=\"saved-prompts-list-loading\">\n <Spinner size=\"lg\" aria-label={t('common.loading')} />\n </div>\n );\n }\n\n if (error) {\n return (\n <Alert\n variant=\"danger\"\n isInline\n title={error}\n data-testid=\"saved-prompts-list-error\"\n />\n );\n }\n\n if (prompts.length === 0) {\n return null;\n }\n\n return (\n <div className={classes.root} data-testid=\"saved-prompts-list\">\n {prompts.map((prompt, index) => (\n <SavedPromptCard\n key={prompt.id}\n prompt={prompt}\n variant={variant}\n showDivider={index < prompts.length - 1}\n onApplyToInput={onApplyToInput}\n onSendDirectly={onSendDirectly}\n onDelete={onDelete}\n isSendDirectlyDisabled={isSendDirectlyDisabled}\n />\n ))}\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;AAmCA,MAAM,SAAA,GAAY,UAAA,EAAW,CAAE,CAAA,KAAA,MAAU;AAAA,EACvC,IAAA,EAAM;AAAA,IACJ,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,MAAA;AAAA,IACT,cAAA,EAAgB,QAAA;AAAA,IAChB,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA;AAE5B,CAAA,CAAE,CAAA;AAEK,MAAM,mBAAmB,CAAC;AAAA,EAC/B,OAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA,GAAU,UAAA;AAAA,EACV,cAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,KAA6B;AAC3B,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,SAAA,EAAU;AAC9B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,SAAS,aAAA,EAAY,4BAAA,EAC3C,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,MAAK,IAAA,EAAK,YAAA,EAAY,CAAA,CAAE,gBAAgB,GAAG,CAAA,EACtD,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,QAAA;AAAA,QACR,QAAA,EAAQ,IAAA;AAAA,QACR,KAAA,EAAO,KAAA;AAAA,QACP,aAAA,EAAY;AAAA;AAAA,KACd;AAAA,EAEJ;AAEA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,IAAA,EAAM,aAAA,EAAY,oBAAA,EACvC,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,EAAQ,KAAA,qBACpB,GAAA;AAAA,IAAC,eAAA;AAAA,IAAA;AAAA,MAEC,MAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA,EAAa,KAAA,GAAQ,OAAA,CAAQ,MAAA,GAAS,CAAA;AAAA,MACtC,cAAA;AAAA,MACA,cAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KAAA;AAAA,IAPK,MAAA,CAAO;AAAA,GASf,CAAA,EACH,CAAA;AAEJ;;;;"}
|