@red-hat-developer-hub/backstage-plugin-lightspeed 0.5.7 → 0.6.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 +14 -0
- package/dist/components/Attachment.esm.js +71 -61
- package/dist/components/Attachment.esm.js.map +1 -1
- package/dist/components/AttachmentContext.esm.js +32 -23
- package/dist/components/AttachmentContext.esm.js.map +1 -1
- package/dist/components/DeleteModal.esm.js +24 -15
- package/dist/components/DeleteModal.esm.js.map +1 -1
- package/dist/components/FilePreview.esm.js +16 -13
- package/dist/components/FilePreview.esm.js.map +1 -1
- package/dist/components/LightSpeedChat.esm.js +172 -129
- package/dist/components/LightSpeedChat.esm.js.map +1 -1
- package/dist/components/LightspeedChatBox.esm.js +43 -34
- package/dist/components/LightspeedChatBox.esm.js.map +1 -1
- package/dist/components/LightspeedChatBoxHeader.esm.js +15 -12
- package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
- package/dist/components/LightspeedIcon.esm.js +11 -2
- package/dist/components/LightspeedIcon.esm.js.map +1 -1
- package/dist/components/LightspeedPage.esm.js +32 -26
- package/dist/components/LightspeedPage.esm.js.map +1 -1
- package/dist/components/PermissionRequiredIcon.esm.js +10 -2
- package/dist/components/PermissionRequiredIcon.esm.js.map +1 -1
- package/dist/components/PermissionRequiredState.esm.js +25 -11
- package/dist/components/PermissionRequiredState.esm.js.map +1 -1
- package/dist/components/Trans.esm.js +33 -0
- package/dist/components/Trans.esm.js.map +1 -0
- package/dist/const.esm.js +20 -43
- package/dist/const.esm.js.map +1 -1
- package/dist/hooks/useAutoScroll.esm.js +11 -11
- package/dist/hooks/useAutoScroll.esm.js.map +1 -1
- package/dist/hooks/useBufferedMessages.esm.js +5 -5
- package/dist/hooks/useBufferedMessages.esm.js.map +1 -1
- package/dist/hooks/useConversationMessages.esm.js +8 -8
- package/dist/hooks/useConversationMessages.esm.js.map +1 -1
- package/dist/hooks/useFeedbackActions.esm.js +47 -18
- package/dist/hooks/useFeedbackActions.esm.js.map +1 -1
- package/dist/hooks/useIsMobile.esm.js +3 -3
- package/dist/hooks/useIsMobile.esm.js.map +1 -1
- package/dist/hooks/useLastOpenedConversation.esm.js.map +1 -1
- package/dist/hooks/useTranslation.esm.js +7 -0
- package/dist/hooks/useTranslation.esm.js.map +1 -0
- package/dist/hooks/useWelcomePrompts.esm.js +21 -6
- package/dist/hooks/useWelcomePrompts.esm.js.map +1 -1
- package/dist/index.d.ts +11 -5
- package/dist/index.esm.js +1 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/translations/de.esm.js +128 -0
- package/dist/translations/de.esm.js.map +1 -0
- package/dist/translations/es.esm.js +128 -0
- package/dist/translations/es.esm.js.map +1 -0
- package/dist/translations/fr.esm.js +128 -0
- package/dist/translations/fr.esm.js.map +1 -0
- package/dist/translations/index.esm.js +14 -0
- package/dist/translations/index.esm.js.map +1 -0
- package/dist/translations/translationRef.esm.js +128 -0
- package/dist/translations/translationRef.esm.js.map +1 -0
- package/dist/types.esm.js.map +1 -1
- package/dist/utils/lightspeed-chatbox-utils.esm.js +24 -21
- package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -1
- package/package.json +12 -12
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef, useRef, useImperativeHandle, useEffect, Fragment } from 'react';
|
|
2
3
|
import { useApi, configApiRef } from '@backstage/core-plugin-api';
|
|
3
4
|
import { makeStyles } from '@material-ui/core';
|
|
4
5
|
import { MessageBox, ChatbotWelcomePrompt, Message } from '@patternfly/chatbot';
|
|
5
6
|
import { Alert } from '@patternfly/react-core';
|
|
6
|
-
import { FUNCTION_DISCLAIMER, FUNCTION_DISCLAIMER_WITHOUT_QUESTION_VALIDATION } from '../const.esm.js';
|
|
7
7
|
import { useAutoScroll } from '../hooks/useAutoScroll.esm.js';
|
|
8
8
|
import { useBufferedMessages } from '../hooks/useBufferedMessages.esm.js';
|
|
9
9
|
import { useFeedbackActions } from '../hooks/useFeedbackActions.esm.js';
|
|
10
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
10
11
|
|
|
11
12
|
const useStyles = makeStyles((theme) => ({
|
|
12
13
|
prompt: {
|
|
@@ -28,7 +29,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
}));
|
|
31
|
-
const LightspeedChatBox =
|
|
32
|
+
const LightspeedChatBox = forwardRef(
|
|
32
33
|
({
|
|
33
34
|
userName,
|
|
34
35
|
messages,
|
|
@@ -39,8 +40,9 @@ const LightspeedChatBox = React__default.forwardRef(
|
|
|
39
40
|
isStreaming
|
|
40
41
|
}, ref) => {
|
|
41
42
|
const classes = useStyles();
|
|
42
|
-
const scrollQueued =
|
|
43
|
-
const containerRef =
|
|
43
|
+
const scrollQueued = useRef(false);
|
|
44
|
+
const containerRef = useRef(null);
|
|
45
|
+
const { t } = useTranslation();
|
|
44
46
|
const configApi = useApi(configApiRef);
|
|
45
47
|
const questionValidationEnabled = configApi.getOptionalBoolean("lightspeed.questionValidation") ?? true;
|
|
46
48
|
const cmessages = useBufferedMessages(messages, 30);
|
|
@@ -50,7 +52,7 @@ const LightspeedChatBox = React__default.forwardRef(
|
|
|
50
52
|
conversationId,
|
|
51
53
|
isStreaming
|
|
52
54
|
);
|
|
53
|
-
|
|
55
|
+
useImperativeHandle(ref, () => ({
|
|
54
56
|
scrollToBottom: () => {
|
|
55
57
|
if (scrollQueued.current) return;
|
|
56
58
|
scrollQueued.current = true;
|
|
@@ -60,7 +62,7 @@ const LightspeedChatBox = React__default.forwardRef(
|
|
|
60
62
|
});
|
|
61
63
|
}
|
|
62
64
|
}));
|
|
63
|
-
|
|
65
|
+
useEffect(() => {
|
|
64
66
|
if (!autoScroll || scrollQueued.current) return undefined;
|
|
65
67
|
scrollQueued.current = true;
|
|
66
68
|
const rafId = requestAnimationFrame(() => {
|
|
@@ -80,39 +82,46 @@ const LightspeedChatBox = React__default.forwardRef(
|
|
|
80
82
|
};
|
|
81
83
|
}, [autoScroll, cmessages, containerRef]);
|
|
82
84
|
const messageBoxClasses = `${classes.container} ${classes.userMessageText}`;
|
|
83
|
-
return /* @__PURE__ */
|
|
85
|
+
return /* @__PURE__ */ jsxs(
|
|
84
86
|
MessageBox,
|
|
85
87
|
{
|
|
86
88
|
className: welcomePrompts.length ? `${messageBoxClasses} ${classes.prompt}` : messageBoxClasses,
|
|
87
89
|
announcement,
|
|
88
90
|
ref: containerRef,
|
|
89
91
|
onScrollToTopClick: scrollToTop,
|
|
90
|
-
onScrollToBottomClick: scrollToBottom
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
92
|
+
onScrollToBottomClick: scrollToBottom,
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
95
|
+
/* @__PURE__ */ jsx(
|
|
96
|
+
Alert,
|
|
97
|
+
{
|
|
98
|
+
title: t("aria.important"),
|
|
99
|
+
variant: "info",
|
|
100
|
+
isInline: true,
|
|
101
|
+
className: classes.alert,
|
|
102
|
+
children: questionValidationEnabled ? t("disclaimer.withValidation") : t("disclaimer.withoutValidation")
|
|
103
|
+
}
|
|
104
|
+
),
|
|
105
|
+
/* @__PURE__ */ jsx("br", {})
|
|
106
|
+
] }),
|
|
107
|
+
welcomePrompts.length ? /* @__PURE__ */ jsx(
|
|
108
|
+
ChatbotWelcomePrompt,
|
|
109
|
+
{
|
|
110
|
+
title: t("chatbox.welcome.greeting", {
|
|
111
|
+
userName: profileLoading ? t("user.loading") : userName ?? t("user.guest")
|
|
112
|
+
}),
|
|
113
|
+
description: t("chatbox.welcome.description"),
|
|
114
|
+
prompts: welcomePrompts
|
|
115
|
+
}
|
|
116
|
+
) : /* @__PURE__ */ jsx("br", {}),
|
|
117
|
+
conversationMessages.map((message, index) => {
|
|
118
|
+
if (index === cmessages.length - 1) {
|
|
119
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Message, { ...message }, `${message.role}-${index}`) }, `${message.role}-${index}`);
|
|
120
|
+
}
|
|
121
|
+
return /* @__PURE__ */ jsx(Message, { ...message }, `${message.role}-${index}`);
|
|
122
|
+
})
|
|
123
|
+
]
|
|
124
|
+
}
|
|
116
125
|
);
|
|
117
126
|
}
|
|
118
127
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedChatBox.esm.js","sources":["../../src/components/LightspeedChatBox.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
|
|
1
|
+
{"version":3,"file":"LightspeedChatBox.esm.js","sources":["../../src/components/LightspeedChatBox.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 {\n ForwardedRef,\n forwardRef,\n Fragment,\n useEffect,\n useImperativeHandle,\n useRef,\n} from 'react';\n\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { makeStyles } from '@material-ui/core';\nimport {\n ChatbotWelcomePrompt,\n Message,\n MessageBox,\n MessageBoxHandle,\n MessageProps,\n WelcomePrompt,\n} from '@patternfly/chatbot';\nimport { Alert } from '@patternfly/react-core';\n\nimport { useAutoScroll } from '../hooks/useAutoScroll';\nimport { useBufferedMessages } from '../hooks/useBufferedMessages';\nimport { useFeedbackActions } from '../hooks/useFeedbackActions';\nimport { useTranslation } from '../hooks/useTranslation';\n\nconst useStyles = makeStyles(theme => ({\n prompt: {\n 'justify-content': 'flex-end',\n },\n container: {\n maxWidth: 'unset !important',\n },\n alert: {\n background: 'unset !important',\n },\n userMessageText: {\n '& div.pf-chatbot__message--user': {\n '& div.pf-chatbot__message-text': {\n '& p': {\n color: theme.palette.common.white,\n },\n },\n },\n },\n}));\n\ntype LightspeedChatBoxProps = {\n userName?: string;\n messages: MessageProps[];\n profileLoading: boolean;\n announcement: string | undefined;\n welcomePrompts: WelcomePrompt[];\n conversationId: string;\n isStreaming: boolean;\n};\n\nexport interface ScrollContainerHandle {\n scrollToBottom: () => void;\n}\n\nexport const LightspeedChatBox = forwardRef(\n (\n {\n userName,\n messages,\n announcement,\n conversationId,\n profileLoading,\n welcomePrompts,\n isStreaming,\n }: LightspeedChatBoxProps,\n ref: ForwardedRef<ScrollContainerHandle>,\n ) => {\n const classes = useStyles();\n const scrollQueued = useRef(false);\n const containerRef = useRef<MessageBoxHandle>(null);\n const { t } = useTranslation();\n\n const configApi = useApi(configApiRef);\n const questionValidationEnabled =\n configApi.getOptionalBoolean('lightspeed.questionValidation') ?? true;\n const cmessages = useBufferedMessages(messages, 30);\n const { autoScroll, scrollToBottom, scrollToTop } =\n useAutoScroll(containerRef);\n const conversationMessages = useFeedbackActions(\n cmessages,\n conversationId,\n isStreaming,\n );\n\n useImperativeHandle(ref, () => ({\n scrollToBottom: () => {\n if (scrollQueued.current) return;\n scrollQueued.current = true;\n\n requestAnimationFrame(() => {\n scrollToBottom();\n scrollQueued.current = false;\n });\n },\n }));\n\n // Auto-scrolls to the latest message\n useEffect(() => {\n if (!autoScroll || scrollQueued.current) return undefined;\n\n scrollQueued.current = true;\n\n const rafId = requestAnimationFrame(() => {\n const container = containerRef.current;\n if (!container) return;\n\n setTimeout(() => {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'auto',\n });\n }, 0);\n\n scrollQueued.current = false;\n });\n\n return () => {\n cancelAnimationFrame(rafId);\n scrollQueued.current = false;\n };\n\n // eslint-disable-next-line\n }, [autoScroll, cmessages, containerRef]);\n\n const messageBoxClasses = `${classes.container} ${classes.userMessageText}`;\n return (\n <MessageBox\n className={\n welcomePrompts.length\n ? `${messageBoxClasses} ${classes.prompt}`\n : messageBoxClasses\n }\n announcement={announcement}\n ref={containerRef}\n onScrollToTopClick={scrollToTop}\n onScrollToBottomClick={scrollToBottom}\n >\n <div>\n <Alert\n title={t('aria.important')}\n variant=\"info\"\n isInline\n className={classes.alert}\n >\n {questionValidationEnabled\n ? t('disclaimer.withValidation')\n : t('disclaimer.withoutValidation')}\n </Alert>\n <br />\n </div>\n {welcomePrompts.length ? (\n <ChatbotWelcomePrompt\n title={t('chatbox.welcome.greeting' as any, {\n userName: profileLoading\n ? t('user.loading')\n : (userName ?? t('user.guest')),\n })}\n description={t('chatbox.welcome.description')}\n prompts={welcomePrompts}\n />\n ) : (\n <br />\n )}\n {conversationMessages.map((message, index) => {\n if (index === cmessages.length - 1) {\n return (\n <Fragment key={`${message.role}-${index}`}>\n <Message key={`${message.role}-${index}`} {...message} />\n </Fragment>\n );\n }\n return <Message key={`${message.role}-${index}`} {...message} />;\n })}\n </MessageBox>\n );\n },\n);\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
import { makeStyles, createStyles } from '@material-ui/core';
|
|
3
4
|
import { ChatbotHeaderActions } from '@patternfly/chatbot';
|
|
4
5
|
import { Dropdown, DropdownList, DropdownItem, MenuToggle } from '@patternfly/react-core';
|
|
6
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
5
7
|
|
|
6
8
|
const useStyles = makeStyles(
|
|
7
9
|
() => createStyles({
|
|
@@ -18,20 +20,21 @@ const LightspeedChatBoxHeader = ({
|
|
|
18
20
|
handleSelectedModel,
|
|
19
21
|
models
|
|
20
22
|
}) => {
|
|
21
|
-
const [isOptionsMenuOpen, setIsOptionsMenuOpen] =
|
|
23
|
+
const [isOptionsMenuOpen, setIsOptionsMenuOpen] = useState(false);
|
|
24
|
+
const { t } = useTranslation();
|
|
22
25
|
const styles = useStyles();
|
|
23
|
-
const toggle = (toggleRef) => /* @__PURE__ */
|
|
26
|
+
const toggle = (toggleRef) => /* @__PURE__ */ jsx(
|
|
24
27
|
MenuToggle,
|
|
25
28
|
{
|
|
26
29
|
variant: "secondary",
|
|
27
|
-
"aria-label": "
|
|
30
|
+
"aria-label": t("aria.chatbotSelector"),
|
|
28
31
|
ref: toggleRef,
|
|
29
32
|
isExpanded: isOptionsMenuOpen,
|
|
30
|
-
onClick: () => setIsOptionsMenuOpen(!isOptionsMenuOpen)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
onClick: () => setIsOptionsMenuOpen(!isOptionsMenuOpen),
|
|
34
|
+
children: selectedModel
|
|
35
|
+
}
|
|
33
36
|
);
|
|
34
|
-
return /* @__PURE__ */
|
|
37
|
+
return /* @__PURE__ */ jsx(ChatbotHeaderActions, { children: /* @__PURE__ */ jsx(
|
|
35
38
|
Dropdown,
|
|
36
39
|
{
|
|
37
40
|
className: styles.dropdown,
|
|
@@ -44,10 +47,10 @@ const LightspeedChatBoxHeader = ({
|
|
|
44
47
|
popperProps: { position: "right" },
|
|
45
48
|
shouldFocusToggleOnSelect: true,
|
|
46
49
|
shouldFocusFirstItemOnOpen: false,
|
|
47
|
-
toggle
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
));
|
|
50
|
+
toggle,
|
|
51
|
+
children: /* @__PURE__ */ jsx(DropdownList, { children: models.map((m) => /* @__PURE__ */ jsx(DropdownItem, { value: m.value, children: m.label }, m.value)) })
|
|
52
|
+
}
|
|
53
|
+
) });
|
|
51
54
|
};
|
|
52
55
|
|
|
53
56
|
export { LightspeedChatBoxHeader };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedChatBoxHeader.esm.js","sources":["../../src/components/LightspeedChatBoxHeader.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
|
|
1
|
+
{"version":3,"file":"LightspeedChatBoxHeader.esm.js","sources":["../../src/components/LightspeedChatBoxHeader.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, useState } from 'react';\n\nimport { createStyles, makeStyles } from '@material-ui/core';\nimport { ChatbotHeaderActions } from '@patternfly/chatbot';\nimport {\n Dropdown,\n DropdownItem,\n DropdownList,\n MenuToggle,\n MenuToggleElement,\n} from '@patternfly/react-core';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ntype LightspeedChatBoxHeaderProps = {\n selectedModel: string;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string }[];\n};\n\nconst useStyles = makeStyles(() =>\n createStyles({\n dropdown: {\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n },\n }),\n);\n\nexport const LightspeedChatBoxHeader = ({\n selectedModel,\n handleSelectedModel,\n models,\n}: LightspeedChatBoxHeaderProps) => {\n const [isOptionsMenuOpen, setIsOptionsMenuOpen] = useState(false);\n const { t } = useTranslation();\n\n const styles = useStyles();\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <MenuToggle\n variant=\"secondary\"\n aria-label={t('aria.chatbotSelector')}\n ref={toggleRef}\n isExpanded={isOptionsMenuOpen}\n onClick={() => setIsOptionsMenuOpen(!isOptionsMenuOpen)}\n >\n {selectedModel}\n </MenuToggle>\n );\n\n return (\n <ChatbotHeaderActions>\n <Dropdown\n className={styles.dropdown}\n isOpen={isOptionsMenuOpen}\n onSelect={(_e, value) => {\n handleSelectedModel(value as string);\n setIsOptionsMenuOpen(false);\n }}\n onOpenChange={isOpen => setIsOptionsMenuOpen(isOpen)}\n popperProps={{ position: 'right' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n >\n <DropdownList>\n {models.map(m => (\n <DropdownItem value={m.value} key={m.value}>\n {m.label}\n </DropdownItem>\n ))}\n </DropdownList>\n </Dropdown>\n </ChatbotHeaderActions>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAoCA,MAAM,SAAY,GAAA,UAAA;AAAA,EAAW,MAC3B,YAAa,CAAA;AAAA,IACX,QAAU,EAAA;AAAA,MACR,YAAc,EAAA;AAAA,QACZ,OAAS,EAAA,CAAA;AAAA,QACT,MAAQ,EAAA;AAAA;AACV;AACF,GACD;AACH,CAAA;AAEO,MAAM,0BAA0B,CAAC;AAAA,EACtC,aAAA;AAAA,EACA,mBAAA;AAAA,EACA;AACF,CAAoC,KAAA;AAClC,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAAS,KAAK,CAAA;AAChE,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EAAA,MAAM,SAAS,SAAU,EAAA;AAEzB,EAAM,MAAA,MAAA,GAAS,CAAC,SACd,qBAAA,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,WAAA;AAAA,MACR,YAAA,EAAY,EAAE,sBAAsB,CAAA;AAAA,MACpC,GAAK,EAAA,SAAA;AAAA,MACL,UAAY,EAAA,iBAAA;AAAA,MACZ,OAAS,EAAA,MAAM,oBAAqB,CAAA,CAAC,iBAAiB,CAAA;AAAA,MAErD,QAAA,EAAA;AAAA;AAAA,GACH;AAGF,EAAA,2BACG,oBACC,EAAA,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,WAAW,MAAO,CAAA,QAAA;AAAA,MAClB,MAAQ,EAAA,iBAAA;AAAA,MACR,QAAA,EAAU,CAAC,EAAA,EAAI,KAAU,KAAA;AACvB,QAAA,mBAAA,CAAoB,KAAe,CAAA;AACnC,QAAA,oBAAA,CAAqB,KAAK,CAAA;AAAA,OAC5B;AAAA,MACA,YAAA,EAAc,CAAU,MAAA,KAAA,oBAAA,CAAqB,MAAM,CAAA;AAAA,MACnD,WAAA,EAAa,EAAE,QAAA,EAAU,OAAQ,EAAA;AAAA,MACjC,yBAAyB,EAAA,IAAA;AAAA,MACzB,0BAA4B,EAAA,KAAA;AAAA,MAC5B,MAAA;AAAA,MAEA,QAAC,kBAAA,GAAA,CAAA,YAAA,EAAA,EACE,QAAO,EAAA,MAAA,CAAA,GAAA,CAAI,uBACT,GAAA,CAAA,YAAA,EAAA,EAAa,KAAO,EAAA,CAAA,CAAE,OACpB,QAAE,EAAA,CAAA,CAAA,KAAA,EAAA,EAD8B,CAAE,CAAA,KAErC,CACD,CACH,EAAA;AAAA;AAAA,GAEJ,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
2
3
|
import logo from '../images/logo-white.svg';
|
|
3
4
|
|
|
4
5
|
const LightspeedIcon = () => {
|
|
5
|
-
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
return /* @__PURE__ */ jsx(
|
|
8
|
+
"img",
|
|
9
|
+
{
|
|
10
|
+
src: logo,
|
|
11
|
+
alt: t("icon.lightspeed.alt"),
|
|
12
|
+
style: { height: "25px" }
|
|
13
|
+
}
|
|
14
|
+
);
|
|
6
15
|
};
|
|
7
16
|
|
|
8
17
|
export { LightspeedIcon };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedIcon.esm.js","sources":["../../src/components/LightspeedIcon.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
|
|
1
|
+
{"version":3,"file":"LightspeedIcon.esm.js","sources":["../../src/components/LightspeedIcon.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 { useTranslation } from '../hooks/useTranslation';\nimport logo from '../images/logo-white.svg';\n\n/**\n * @public\n * Lightspeed Icon\n */\nexport const LightspeedIcon = () => {\n const { t } = useTranslation();\n\n return (\n <img\n src={logo as any}\n alt={t('icon.lightspeed.alt')}\n style={{ height: '25px' }}\n />\n );\n};\n"],"names":[],"mappings":";;;;AAuBO,MAAM,iBAAiB,MAAM;AAClC,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EACE,uBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAK,EAAA,IAAA;AAAA,MACL,GAAA,EAAK,EAAE,qBAAqB,CAAA;AAAA,MAC5B,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAO;AAAA;AAAA,GAC1B;AAEJ;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useMemo, useEffect } from 'react';
|
|
2
3
|
import { useAsync } from 'react-use';
|
|
3
4
|
import { Page, Header, Content } from '@backstage/core-components';
|
|
4
5
|
import { useApi, identityApiRef } from '@backstage/core-plugin-api';
|
|
@@ -6,6 +7,7 @@ import { makeStyles, createStyles, useTheme } from '@material-ui/core/styles';
|
|
|
6
7
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
7
8
|
import { useAllModels } from '../hooks/useAllModels.esm.js';
|
|
8
9
|
import { useLightspeedViewPermission } from '../hooks/useLightspeedViewPermission.esm.js';
|
|
10
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
9
11
|
import queryClient from '../utils/queryClient.esm.js';
|
|
10
12
|
import FileAttachmentContextProvider from './AttachmentContext.esm.js';
|
|
11
13
|
import { LightspeedChat } from './LightSpeedChat.esm.js';
|
|
@@ -22,6 +24,7 @@ const THEME_DARK = "dark";
|
|
|
22
24
|
const THEME_DARK_CLASS = "pf-v6-theme-dark";
|
|
23
25
|
const LightspeedPageInner = () => {
|
|
24
26
|
const classes = useStyles();
|
|
27
|
+
const { t } = useTranslation();
|
|
25
28
|
const {
|
|
26
29
|
palette: { type }
|
|
27
30
|
} = useTheme();
|
|
@@ -31,12 +34,12 @@ const LightspeedPageInner = () => {
|
|
|
31
34
|
const { value: profile, loading: profileLoading } = useAsync(
|
|
32
35
|
async () => await identityApi.getProfileInfo()
|
|
33
36
|
);
|
|
34
|
-
const [selectedModel, setSelectedModel] =
|
|
35
|
-
const modelsItems =
|
|
37
|
+
const [selectedModel, setSelectedModel] = useState("");
|
|
38
|
+
const modelsItems = useMemo(
|
|
36
39
|
() => models ? models.map((m) => ({ label: m.id, value: m.id })) : [],
|
|
37
40
|
[models]
|
|
38
41
|
);
|
|
39
|
-
|
|
42
|
+
useEffect(() => {
|
|
40
43
|
const htmlTagElement = document.documentElement;
|
|
41
44
|
if (type === THEME_DARK) {
|
|
42
45
|
htmlTagElement.classList.add(THEME_DARK_CLASS);
|
|
@@ -44,35 +47,38 @@ const LightspeedPageInner = () => {
|
|
|
44
47
|
htmlTagElement.classList.remove(THEME_DARK_CLASS);
|
|
45
48
|
}
|
|
46
49
|
}, [type]);
|
|
47
|
-
|
|
50
|
+
useEffect(() => {
|
|
48
51
|
if (modelsItems.length > 0) setSelectedModel(modelsItems[0].value);
|
|
49
52
|
}, [modelsItems]);
|
|
50
53
|
if (loading) {
|
|
51
54
|
return null;
|
|
52
55
|
}
|
|
53
|
-
return /* @__PURE__ */
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
{
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
56
|
+
return /* @__PURE__ */ jsxs(Page, { themeId: "tool", children: [
|
|
57
|
+
/* @__PURE__ */ jsx(
|
|
58
|
+
Header,
|
|
59
|
+
{
|
|
60
|
+
title: t("page.title"),
|
|
61
|
+
style: { display: "none" },
|
|
62
|
+
pageTitleOverride: t("page.title")
|
|
63
|
+
}
|
|
64
|
+
),
|
|
65
|
+
/* @__PURE__ */ jsx(Content, { className: classes.container, children: !hasViewAccess ? /* @__PURE__ */ jsx(PermissionRequiredState, {}) : /* @__PURE__ */ jsx(FileAttachmentContextProvider, { children: /* @__PURE__ */ jsx(
|
|
66
|
+
LightspeedChat,
|
|
67
|
+
{
|
|
68
|
+
selectedModel,
|
|
69
|
+
handleSelectedModel: (item) => {
|
|
70
|
+
setSelectedModel(item);
|
|
71
|
+
},
|
|
72
|
+
models: modelsItems,
|
|
73
|
+
userName: profile?.displayName,
|
|
74
|
+
avatar: profile?.picture,
|
|
75
|
+
profileLoading
|
|
76
|
+
}
|
|
77
|
+
) }) })
|
|
78
|
+
] });
|
|
73
79
|
};
|
|
74
80
|
const LightspeedPage = () => {
|
|
75
|
-
return /* @__PURE__ */
|
|
81
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(LightspeedPageInner, {}) });
|
|
76
82
|
};
|
|
77
83
|
|
|
78
84
|
export { LightspeedPage };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedPage.esm.js","sources":["../../src/components/LightspeedPage.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
|
|
1
|
+
{"version":3,"file":"LightspeedPage.esm.js","sources":["../../src/components/LightspeedPage.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 { useEffect, useMemo, useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { Content, Header, Page } from '@backstage/core-components';\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { createStyles, makeStyles, useTheme } from '@material-ui/core/styles';\nimport { QueryClientProvider } from '@tanstack/react-query';\n\nimport { useAllModels } from '../hooks/useAllModels';\nimport { useLightspeedViewPermission } from '../hooks/useLightspeedViewPermission';\nimport { useTranslation } from '../hooks/useTranslation';\nimport queryClient from '../utils/queryClient';\nimport FileAttachmentContextProvider from './AttachmentContext';\nimport { LightspeedChat } from './LightSpeedChat';\nimport PermissionRequiredState from './PermissionRequiredState';\n\nconst useStyles = makeStyles(() =>\n createStyles({\n container: {\n padding: '0px',\n },\n }),\n);\n\nconst THEME_DARK = 'dark';\nconst THEME_DARK_CLASS = 'pf-v6-theme-dark';\n\nconst LightspeedPageInner = () => {\n const classes = useStyles();\n const { t } = useTranslation();\n const {\n palette: { type },\n } = useTheme();\n\n const identityApi = useApi(identityApiRef);\n\n const { data: models } = useAllModels();\n const { allowed: hasViewAccess, loading } = useLightspeedViewPermission();\n\n const { value: profile, loading: profileLoading } = useAsync(\n async () => await identityApi.getProfileInfo(),\n );\n\n const [selectedModel, setSelectedModel] = useState('');\n\n const modelsItems = useMemo(\n () => (models ? models.map(m => ({ label: m.id, value: m.id })) : []),\n [models],\n );\n\n useEffect(() => {\n const htmlTagElement = document.documentElement;\n if (type === THEME_DARK) {\n htmlTagElement.classList.add(THEME_DARK_CLASS);\n } else {\n htmlTagElement.classList.remove(THEME_DARK_CLASS);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [type]);\n\n useEffect(() => {\n if (modelsItems.length > 0) setSelectedModel(modelsItems[0].value);\n }, [modelsItems]);\n\n if (loading) {\n return null;\n }\n\n return (\n <Page themeId=\"tool\">\n <Header\n title={t('page.title')}\n style={{ display: 'none' }}\n pageTitleOverride={t('page.title')}\n />\n <Content className={classes.container}>\n {!hasViewAccess ? (\n <PermissionRequiredState />\n ) : (\n <FileAttachmentContextProvider>\n <LightspeedChat\n selectedModel={selectedModel}\n handleSelectedModel={item => {\n setSelectedModel(item);\n }}\n models={modelsItems}\n userName={profile?.displayName}\n avatar={profile?.picture}\n profileLoading={profileLoading}\n />\n </FileAttachmentContextProvider>\n )}\n </Content>\n </Page>\n );\n};\n\nexport const LightspeedPage = () => {\n return (\n <QueryClientProvider client={queryClient}>\n <LightspeedPageInner />\n </QueryClientProvider>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
2
3
|
import permissionRequired from '../images/permission-required.svg';
|
|
3
4
|
|
|
4
5
|
const PermissionRequiredIcon = () => {
|
|
5
|
-
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
return /* @__PURE__ */ jsx(
|
|
8
|
+
"img",
|
|
9
|
+
{
|
|
10
|
+
src: permissionRequired,
|
|
11
|
+
alt: t("icon.permissionRequired.alt")
|
|
12
|
+
}
|
|
13
|
+
);
|
|
6
14
|
};
|
|
7
15
|
|
|
8
16
|
export { PermissionRequiredIcon };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PermissionRequiredIcon.esm.js","sources":["../../src/components/PermissionRequiredIcon.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
|
|
1
|
+
{"version":3,"file":"PermissionRequiredIcon.esm.js","sources":["../../src/components/PermissionRequiredIcon.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 { useTranslation } from '../hooks/useTranslation';\nimport permissionRequired from '../images/permission-required.svg';\n\nexport const PermissionRequiredIcon = () => {\n const { t } = useTranslation();\n\n return (\n <img\n src={permissionRequired as any}\n alt={t('icon.permissionRequired.alt')}\n />\n );\n};\n"],"names":[],"mappings":";;;;AAmBO,MAAM,yBAAyB,MAAM;AAC1C,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EACE,uBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAK,EAAA,kBAAA;AAAA,MACL,GAAA,EAAK,EAAE,6BAA6B;AAAA;AAAA,GACtC;AAEJ;;;;"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { EmptyState } from '@backstage/core-components';
|
|
3
3
|
import { Typography, Button } from '@material-ui/core';
|
|
4
4
|
import { makeStyles, createStyles } from '@material-ui/core/styles';
|
|
5
5
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
|
6
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
6
7
|
import { PermissionRequiredIcon } from './PermissionRequiredIcon.esm.js';
|
|
8
|
+
import { Trans } from './Trans.esm.js';
|
|
7
9
|
|
|
8
10
|
const useStyles = makeStyles(
|
|
9
11
|
() => createStyles({
|
|
@@ -17,25 +19,37 @@ const useStyles = makeStyles(
|
|
|
17
19
|
);
|
|
18
20
|
const PermissionRequiredState = () => {
|
|
19
21
|
const classes = useStyles();
|
|
20
|
-
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
return /* @__PURE__ */ jsx("div", { className: classes.permissionError, children: /* @__PURE__ */ jsx(
|
|
21
24
|
EmptyState,
|
|
22
25
|
{
|
|
23
|
-
title: "
|
|
24
|
-
description: /* @__PURE__ */
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
title: t("permission.required.title"),
|
|
27
|
+
description: /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: /* @__PURE__ */ jsx(
|
|
28
|
+
Trans,
|
|
29
|
+
{
|
|
30
|
+
message: "permission.required.description",
|
|
31
|
+
components: {
|
|
32
|
+
"<b>lightspeed.chat.read</b>": /* @__PURE__ */ jsx("b", { children: "lightspeed.chat.read" }),
|
|
33
|
+
"<b>lightspeed.chat.create</b>": /* @__PURE__ */ jsx("b", { children: "lightspeed.chat.create" })
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
) }),
|
|
37
|
+
missing: { customImage: /* @__PURE__ */ jsx(PermissionRequiredIcon, {}) },
|
|
38
|
+
action: /* @__PURE__ */ jsxs(
|
|
27
39
|
Button,
|
|
28
40
|
{
|
|
29
41
|
variant: "outlined",
|
|
30
42
|
color: "primary",
|
|
31
43
|
target: "_blank",
|
|
32
|
-
href: "https://github.com/redhat-developer/rhdh-plugins/blob/main/workspaces/lightspeed/plugins/lightspeed/README.md#permission-framework-support"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
href: "https://github.com/redhat-developer/rhdh-plugins/blob/main/workspaces/lightspeed/plugins/lightspeed/README.md#permission-framework-support",
|
|
45
|
+
children: [
|
|
46
|
+
"Read more \xA0 ",
|
|
47
|
+
/* @__PURE__ */ jsx(OpenInNewIcon, {})
|
|
48
|
+
]
|
|
49
|
+
}
|
|
36
50
|
)
|
|
37
51
|
}
|
|
38
|
-
));
|
|
52
|
+
) });
|
|
39
53
|
};
|
|
40
54
|
|
|
41
55
|
export { PermissionRequiredState as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PermissionRequiredState.esm.js","sources":["../../src/components/PermissionRequiredState.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
|
|
1
|
+
{"version":3,"file":"PermissionRequiredState.esm.js","sources":["../../src/components/PermissionRequiredState.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 { EmptyState } from '@backstage/core-components';\n\nimport { Button, Typography } from '@material-ui/core';\nimport { createStyles, makeStyles } from '@material-ui/core/styles';\nimport OpenInNewIcon from '@mui/icons-material/OpenInNew';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { PermissionRequiredIcon } from './PermissionRequiredIcon';\nimport { Trans } from './Trans';\n\nconst useStyles = makeStyles(() =>\n createStyles({\n permissionError: {\n display: 'flex',\n height: '100%',\n alignItems: 'center',\n padding: '100px',\n },\n }),\n);\n\nconst PermissionRequiredState = () => {\n const classes = useStyles();\n const { t } = useTranslation();\n\n return (\n <div className={classes.permissionError}>\n <EmptyState\n title={t('permission.required.title')}\n description={\n <Typography variant=\"subtitle1\">\n <Trans\n message=\"permission.required.description\"\n components={{\n '<b>lightspeed.chat.read</b>': <b>lightspeed.chat.read</b>,\n '<b>lightspeed.chat.create</b>': <b>lightspeed.chat.create</b>,\n }}\n />\n </Typography>\n }\n missing={{ customImage: <PermissionRequiredIcon /> }}\n action={\n <Button\n variant=\"outlined\"\n color=\"primary\"\n target=\"_blank\"\n href=\"https://github.com/redhat-developer/rhdh-plugins/blob/main/workspaces/lightspeed/plugins/lightspeed/README.md#permission-framework-support\"\n >\n Read more <OpenInNewIcon />\n </Button>\n }\n />\n </div>\n );\n};\nexport default PermissionRequiredState;\n"],"names":[],"mappings":";;;;;;;;;AA0BA,MAAM,SAAY,GAAA,UAAA;AAAA,EAAW,MAC3B,YAAa,CAAA;AAAA,IACX,eAAiB,EAAA;AAAA,MACf,OAAS,EAAA,MAAA;AAAA,MACT,MAAQ,EAAA,MAAA;AAAA,MACR,UAAY,EAAA,QAAA;AAAA,MACZ,OAAS,EAAA;AAAA;AACX,GACD;AACH,CAAA;AAEA,MAAM,0BAA0B,MAAM;AACpC,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EAAA,uBACG,GAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,OAAA,CAAQ,eACtB,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,EAAE,2BAA2B,CAAA;AAAA,MACpC,WACE,kBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,WAClB,EAAA,QAAA,kBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,OAAQ,EAAA,iCAAA;AAAA,UACR,UAAY,EAAA;AAAA,YACV,6BAAA,kBAAgC,GAAA,CAAA,GAAA,EAAA,EAAE,QAAoB,EAAA,sBAAA,EAAA,CAAA;AAAA,YACtD,+BAAA,kBAAkC,GAAA,CAAA,GAAA,EAAA,EAAE,QAAsB,EAAA,wBAAA,EAAA;AAAA;AAC5D;AAAA,OAEJ,EAAA,CAAA;AAAA,MAEF,OAAS,EAAA,EAAE,WAAa,kBAAA,GAAA,CAAC,0BAAuB,CAAG,EAAA;AAAA,MACnD,MACE,kBAAA,IAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,OAAQ,EAAA,UAAA;AAAA,UACR,KAAM,EAAA,SAAA;AAAA,UACN,MAAO,EAAA,QAAA;AAAA,UACP,IAAK,EAAA,4IAAA;AAAA,UACN,QAAA,EAAA;AAAA,YAAA,iBAAA;AAAA,gCACmB,aAAc,EAAA,EAAA;AAAA;AAAA;AAAA;AAClC;AAAA,GAGN,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { cloneElement } from 'react';
|
|
3
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
4
|
+
|
|
5
|
+
const Trans = ({ message, params, components }) => {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
const translatedText = t(message, params || {});
|
|
8
|
+
if (!components) {
|
|
9
|
+
return /* @__PURE__ */ jsx(Fragment, { children: translatedText });
|
|
10
|
+
}
|
|
11
|
+
let result = translatedText;
|
|
12
|
+
const markers = {};
|
|
13
|
+
let markerIndex = 0;
|
|
14
|
+
for (const [placeholder, component] of Object.entries(components)) {
|
|
15
|
+
const marker = `__MARKER_${markerIndex}__`;
|
|
16
|
+
markers[marker] = component;
|
|
17
|
+
result = result.replace(new RegExp(escapeRegExp(placeholder), "g"), marker);
|
|
18
|
+
markerIndex++;
|
|
19
|
+
}
|
|
20
|
+
const parts = result.split(/(__MARKER_\d+__)/);
|
|
21
|
+
return /* @__PURE__ */ jsx(Fragment, { children: parts.map((part, index) => {
|
|
22
|
+
if (markers[part]) {
|
|
23
|
+
return cloneElement(markers[part], { key: index });
|
|
24
|
+
}
|
|
25
|
+
return part;
|
|
26
|
+
}) });
|
|
27
|
+
};
|
|
28
|
+
function escapeRegExp(string) {
|
|
29
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { Trans };
|
|
33
|
+
//# sourceMappingURL=Trans.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Trans.esm.js","sources":["../../src/components/Trans.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 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 { cloneElement } from 'react';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ninterface TransProps {\n message: string;\n params?: Record<string, any>;\n components?: Record<string, React.ReactElement>;\n}\n\nexport const Trans = ({ message, params, components }: TransProps) => {\n const { t } = useTranslation();\n const translatedText = t(message as any, params || {});\n\n // If no components are provided, just return the text\n if (!components) {\n return <>{translatedText}</>;\n }\n\n // Simple string replacement approach - no regex, no security risks\n let result = translatedText;\n\n // Replace each placeholder with a unique marker\n const markers: Record<string, React.ReactElement> = {};\n let markerIndex = 0;\n\n for (const [placeholder, component] of Object.entries(components)) {\n const marker = `__MARKER_${markerIndex}__`;\n markers[marker] = component;\n result = result.replace(new RegExp(escapeRegExp(placeholder), 'g'), marker);\n markerIndex++;\n }\n\n // Split by markers and render components\n const parts = result.split(/(__MARKER_\\d+__)/);\n\n return (\n <>\n {parts.map((part: string, index: number) => {\n if (markers[part]) {\n return cloneElement(markers[part], { key: index });\n }\n return part;\n })}\n </>\n );\n};\n\n// Helper function to escape special regex characters\nfunction escapeRegExp(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n"],"names":[],"mappings":";;;;AA2BO,MAAM,QAAQ,CAAC,EAAE,OAAS,EAAA,MAAA,EAAQ,YAA6B,KAAA;AACpE,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAC7B,EAAA,MAAM,cAAiB,GAAA,CAAA,CAAE,OAAgB,EAAA,MAAA,IAAU,EAAE,CAAA;AAGrD,EAAA,IAAI,CAAC,UAAY,EAAA;AACf,IAAA,uCAAU,QAAe,EAAA,cAAA,EAAA,CAAA;AAAA;AAI3B,EAAA,IAAI,MAAS,GAAA,cAAA;AAGb,EAAA,MAAM,UAA8C,EAAC;AACrD,EAAA,IAAI,WAAc,GAAA,CAAA;AAElB,EAAA,KAAA,MAAW,CAAC,WAAa,EAAA,SAAS,KAAK,MAAO,CAAA,OAAA,CAAQ,UAAU,CAAG,EAAA;AACjE,IAAM,MAAA,MAAA,GAAS,YAAY,WAAW,CAAA,EAAA,CAAA;AACtC,IAAA,OAAA,CAAQ,MAAM,CAAI,GAAA,SAAA;AAClB,IAAS,MAAA,GAAA,MAAA,CAAO,QAAQ,IAAI,MAAA,CAAO,aAAa,WAAW,CAAA,EAAG,GAAG,CAAA,EAAG,MAAM,CAAA;AAC1E,IAAA,WAAA,EAAA;AAAA;AAIF,EAAM,MAAA,KAAA,GAAQ,MAAO,CAAA,KAAA,CAAM,kBAAkB,CAAA;AAE7C,EAAA,uBAEK,GAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA,KAAA,CAAM,GAAI,CAAA,CAAC,MAAc,KAAkB,KAAA;AAC1C,IAAI,IAAA,OAAA,CAAQ,IAAI,CAAG,EAAA;AACjB,MAAA,OAAO,aAAa,OAAQ,CAAA,IAAI,GAAG,EAAE,GAAA,EAAK,OAAO,CAAA;AAAA;AAEnD,IAAO,OAAA,IAAA;AAAA,GACR,CACH,EAAA,CAAA;AAEJ;AAGA,SAAS,aAAa,MAAwB,EAAA;AAC5C,EAAO,OAAA,MAAA,CAAO,OAAQ,CAAA,qBAAA,EAAuB,MAAM,CAAA;AACrD;;;;"}
|