@red-hat-developer-hub/backstage-plugin-lightspeed 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +26 -20
  3. package/dist/alpha.d.ts +24 -0
  4. package/dist/api/LightspeedApiClient.esm.js.map +1 -1
  5. package/dist/api/api.esm.js.map +1 -1
  6. package/dist/components/AttachmentContext.esm.js +12 -2
  7. package/dist/components/AttachmentContext.esm.js.map +1 -1
  8. package/dist/components/LightSpeedChat.esm.js +199 -39
  9. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  10. package/dist/components/LightspeedChatBox.esm.js +70 -9
  11. package/dist/components/LightspeedChatBox.esm.js.map +1 -1
  12. package/dist/components/LightspeedChatBoxHeader.esm.js +84 -26
  13. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
  14. package/dist/components/LightspeedChatContainer.esm.js +118 -0
  15. package/dist/components/LightspeedChatContainer.esm.js.map +1 -0
  16. package/dist/components/LightspeedDrawerContext.esm.js +6 -0
  17. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -0
  18. package/dist/components/LightspeedDrawerProvider.esm.js +175 -0
  19. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -0
  20. package/dist/components/LightspeedDrawerStateExposer.esm.js +28 -0
  21. package/dist/components/LightspeedDrawerStateExposer.esm.js.map +1 -0
  22. package/dist/components/LightspeedFAB.esm.js +68 -0
  23. package/dist/components/LightspeedFAB.esm.js.map +1 -0
  24. package/dist/components/LightspeedIcon.esm.js +23 -2
  25. package/dist/components/LightspeedIcon.esm.js.map +1 -1
  26. package/dist/components/LightspeedPage.esm.js +5 -110
  27. package/dist/components/LightspeedPage.esm.js.map +1 -1
  28. package/dist/components/Router.esm.js +19 -0
  29. package/dist/components/Router.esm.js.map +1 -0
  30. package/dist/components/ToolCallContent.esm.js +217 -0
  31. package/dist/components/ToolCallContent.esm.js.map +1 -0
  32. package/dist/hooks/useConversationMessages.esm.js +136 -20
  33. package/dist/hooks/useConversationMessages.esm.js.map +1 -1
  34. package/dist/hooks/useLightspeedDrawerContext.esm.js +15 -0
  35. package/dist/hooks/useLightspeedDrawerContext.esm.js.map +1 -0
  36. package/dist/hooks/usePinnedChatsSettings.esm.js +118 -0
  37. package/dist/hooks/usePinnedChatsSettings.esm.js.map +1 -0
  38. package/dist/hooks/useSortSettings.esm.js +60 -0
  39. package/dist/hooks/useSortSettings.esm.js.map +1 -0
  40. package/dist/images/logo-black.svg +22 -0
  41. package/dist/images/rounded-logo.svg +22 -0
  42. package/dist/index.d.ts +52 -2
  43. package/dist/index.esm.js +4 -1
  44. package/dist/index.esm.js.map +1 -1
  45. package/dist/plugin.esm.js +44 -5
  46. package/dist/plugin.esm.js.map +1 -1
  47. package/dist/routes.esm.js +7 -2
  48. package/dist/routes.esm.js.map +1 -1
  49. package/dist/translations/de.esm.js +29 -1
  50. package/dist/translations/de.esm.js.map +1 -1
  51. package/dist/translations/es.esm.js +29 -1
  52. package/dist/translations/es.esm.js.map +1 -1
  53. package/dist/translations/fr.esm.js +120 -115
  54. package/dist/translations/fr.esm.js.map +1 -1
  55. package/dist/translations/index.esm.js +3 -1
  56. package/dist/translations/index.esm.js.map +1 -1
  57. package/dist/translations/it.esm.js +158 -0
  58. package/dist/translations/it.esm.js.map +1 -0
  59. package/dist/translations/ja.esm.js +158 -0
  60. package/dist/translations/ja.esm.js.map +1 -0
  61. package/dist/translations/ref.esm.js +29 -1
  62. package/dist/translations/ref.esm.js.map +1 -1
  63. package/dist/types.esm.js.map +1 -1
  64. package/dist/utils/lightspeed-chatbox-utils.esm.js +24 -5
  65. package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -1
  66. package/dist/utils/reasoningParser.esm.js +46 -0
  67. package/dist/utils/reasoningParser.esm.js.map +1 -0
  68. package/dist/utils/toolCallMapper.esm.js +15 -0
  69. package/dist/utils/toolCallMapper.esm.js.map +1 -0
  70. package/dist/utils/user-utils.esm.js +7 -0
  71. package/dist/utils/user-utils.esm.js.map +1 -0
  72. package/package.json +9 -4
  73. package/app-config.yaml +0 -18
@@ -2,10 +2,10 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import { useState, useEffect, useCallback, useMemo } from 'react';
3
3
  import { makeStyles } from '@material-ui/core';
4
4
  import Divider from '@mui/material/Divider';
5
- import { Chatbot, ChatbotDisplayMode, ChatbotHeader, ChatbotHeaderMain, ChatbotHeaderMenu, ChatbotHeaderTitle, FileDropZone, ChatbotAlert, ChatbotContent, ChatbotFooter, MessageBar, ChatbotFootnote } from '@patternfly/chatbot';
5
+ import { ChatbotDisplayMode, Chatbot, ChatbotHeader, ChatbotHeaderMain, ChatbotHeaderMenu, ChatbotHeaderTitle, FileDropZone, ChatbotAlert, ChatbotContent, ChatbotFooter, MessageBar, ChatbotFootnote } from '@patternfly/chatbot';
6
6
  import ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';
7
- import { DropdownItem, Title } from '@patternfly/react-core';
8
- import { PlusIcon, SearchIcon } from '@patternfly/react-icons';
7
+ import { DropdownItem, Tooltip, MenuToggle, Select, SelectList, SelectOption, Title } from '@patternfly/react-core';
8
+ import { SortAmountDownAltIcon, SortAmountDownIcon, PlusIcon, SearchIcon } from '@patternfly/react-icons';
9
9
  import { useQueryClient } from '@tanstack/react-query';
10
10
  import { TEMP_CONVERSATION_ID, supportedFileTypes } from '../const.esm.js';
11
11
  import '@backstage/core-plugin-api';
@@ -18,7 +18,10 @@ import { useLastOpenedConversation } from '../hooks/useLastOpenedConversation.es
18
18
  import { useLightspeedDeletePermission } from '../hooks/useLightspeedDeletePermission.esm.js';
19
19
  import '@backstage/plugin-permission-react';
20
20
  import '@red-hat-developer-hub/backstage-plugin-lightspeed-common';
21
+ import { usePinnedChatsSettings } from '../hooks/usePinnedChatsSettings.esm.js';
22
+ import { useSortSettings } from '../hooks/useSortSettings.esm.js';
21
23
  import { useTranslation } from '../hooks/useTranslation.esm.js';
24
+ import { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext.esm.js';
22
25
  import { useLightspeedUpdatePermission } from '../hooks/useLightspeedUpdatePermission.esm.js';
23
26
  import { useWelcomePrompts } from '../hooks/useWelcomePrompts.esm.js';
24
27
  import { getAttachments } from '../utils/attachment-utils.esm.js';
@@ -65,6 +68,10 @@ const useStyles = makeStyles((theme) => ({
65
68
  "& img": {
66
69
  maxWidth: "100%"
67
70
  }
71
+ },
72
+ sortDropdown: {
73
+ padding: 0,
74
+ margin: 0
68
75
  }
69
76
  }));
70
77
  const LightspeedChat = ({
@@ -84,15 +91,36 @@ const LightspeedChat = ({
84
91
  const [filterValue, setFilterValue] = useState("");
85
92
  const [announcement, setAnnouncement] = useState("");
86
93
  const [conversationId, setConversationId] = useState("");
87
- const [isDrawerOpen, setIsDrawerOpen] = useState(!isMobile);
88
94
  const [newChatCreated, setNewChatCreated] = useState(false);
89
95
  const [isSendButtonDisabled, setIsSendButtonDisabled] = useState(false);
90
- const [isPinningChatsEnabled, setIsPinningChatsEnabled] = useState(true);
91
- const [pinnedChats, setPinnedChats] = useState([]);
92
96
  const [targetConversationId, setTargetConversationId] = useState("");
93
97
  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
94
98
  const [isRenameModalOpen, setIsRenameModalOpen] = useState(false);
99
+ const [isSortSelectOpen, setIsSortSelectOpen] = useState(false);
95
100
  const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } = useLastOpenedConversation(user);
101
+ const {
102
+ displayMode,
103
+ setDisplayMode,
104
+ currentConversationId: routeConversationId,
105
+ setCurrentConversationId,
106
+ draftMessage,
107
+ setDraftMessage
108
+ } = useLightspeedDrawerContext();
109
+ const isFullscreenMode = displayMode === ChatbotDisplayMode.embedded;
110
+ const [isChatHistoryDrawerOpen, setIsChatHistoryDrawerOpen] = useState(!isMobile && isFullscreenMode);
111
+ useEffect(() => {
112
+ if (!isMobile && isFullscreenMode) {
113
+ setIsChatHistoryDrawerOpen(true);
114
+ }
115
+ }, [isMobile, isFullscreenMode]);
116
+ const {
117
+ isPinningChatsEnabled,
118
+ pinnedChats,
119
+ handlePinningChatsToggle,
120
+ pinChat,
121
+ unpinChat
122
+ } = usePinnedChatsSettings(user);
123
+ const { selectedSort, handleSortChange } = useSortSettings(user);
96
124
  const {
97
125
  uploadError,
98
126
  showAlert,
@@ -107,11 +135,6 @@ const LightspeedChat = ({
107
135
  setConversationId(lastOpenedId);
108
136
  }
109
137
  }, [lastOpenedId, isReady]);
110
- useEffect(() => {
111
- if (!isPinningChatsEnabled) {
112
- setPinnedChats([]);
113
- }
114
- }, [isPinningChatsEnabled]);
115
138
  const queryClient = useQueryClient();
116
139
  const {
117
140
  data: conversations = [],
@@ -132,6 +155,29 @@ const LightspeedChat = ({
132
155
  clearLastOpenedId();
133
156
  }
134
157
  }, [isLoading, isRefetching, conversations, lastOpenedId, clearLastOpenedId]);
158
+ useEffect(() => {
159
+ if (!isLoading && !isRefetching && routeConversationId && isFullscreenMode) {
160
+ const conversationExists = conversations.some(
161
+ (c) => c.conversation_id === routeConversationId
162
+ );
163
+ if (!conversationExists) {
164
+ setConversationId(TEMP_CONVERSATION_ID);
165
+ setCurrentConversationId(undefined);
166
+ setNewChatCreated(true);
167
+ } else if (conversationId !== routeConversationId) {
168
+ setConversationId(routeConversationId);
169
+ }
170
+ }
171
+ }, [
172
+ isLoading,
173
+ isRefetching,
174
+ routeConversationId,
175
+ conversations,
176
+ displayMode,
177
+ conversationId,
178
+ setCurrentConversationId,
179
+ isFullscreenMode
180
+ ]);
135
181
  useEffect(() => {
136
182
  if (conversationId) {
137
183
  setLastOpenedId(conversationId);
@@ -139,6 +185,7 @@ const LightspeedChat = ({
139
185
  }, [conversationId, setLastOpenedId]);
140
186
  const onStart = (conv_id) => {
141
187
  setConversationId(conv_id);
188
+ setCurrentConversationId(conv_id);
142
189
  };
143
190
  const onComplete = (message) => {
144
191
  setIsSendButtonDisabled(false);
@@ -173,6 +220,7 @@ const LightspeedChat = ({
173
220
  handleInputPrompt(message.toString(), getAttachments(fileContents));
174
221
  setIsSendButtonDisabled(true);
175
222
  setFileContents([]);
223
+ setDraftMessage("");
176
224
  };
177
225
  const onNewChat = useCallback(() => {
178
226
  (async () => {
@@ -180,16 +228,22 @@ const LightspeedChat = ({
180
228
  setMessages([]);
181
229
  setFileContents([]);
182
230
  setUploadError({ message: null });
231
+ setDraftMessage("");
183
232
  setConversationId(TEMP_CONVERSATION_ID);
184
233
  setNewChatCreated(true);
234
+ setCurrentConversationId(undefined);
235
+ if (!isFullscreenMode) {
236
+ setIsChatHistoryDrawerOpen(false);
237
+ }
185
238
  }
186
239
  })();
187
240
  }, [
188
241
  conversationId,
189
- setConversationId,
190
- setMessages,
242
+ setFileContents,
191
243
  setUploadError,
192
- setFileContents
244
+ setDraftMessage,
245
+ setCurrentConversationId,
246
+ isFullscreenMode
193
247
  ]);
194
248
  const openDeleteModal = (conversation_id) => {
195
249
  setTargetConversationId(conversation_id);
@@ -206,12 +260,6 @@ const LightspeedChat = ({
206
260
  }
207
261
  setIsDeleteModalOpen(false);
208
262
  }, [clearLastOpenedId, lastOpenedId, onNewChat, targetConversationId]);
209
- const pinChat = (convId) => {
210
- setPinnedChats((prev) => [...prev, convId]);
211
- };
212
- const unpinChat = (convId) => {
213
- setPinnedChats((prev) => prev.filter((id) => id !== convId));
214
- };
215
263
  const additionalMessageProps = useCallback(
216
264
  (conversationSummary) => {
217
265
  const isChatFavorite = pinnedChats?.find(
@@ -251,16 +299,25 @@ const LightspeedChat = ({
251
299
  ] })
252
300
  };
253
301
  },
254
- [pinnedChats, hasDeleteAccess, isPinningChatsEnabled, hasUpdateAccess, t]
302
+ [
303
+ pinnedChats,
304
+ hasDeleteAccess,
305
+ isPinningChatsEnabled,
306
+ hasUpdateAccess,
307
+ t,
308
+ pinChat,
309
+ unpinChat
310
+ ]
255
311
  );
256
312
  const categorizedMessages = useMemo(
257
313
  () => getCategorizeMessages(
258
314
  conversations,
259
315
  pinnedChats,
260
316
  additionalMessageProps,
261
- t
317
+ t,
318
+ selectedSort
262
319
  ),
263
- [additionalMessageProps, conversations, pinnedChats, t]
320
+ [additionalMessageProps, conversations, pinnedChats, t, selectedSort]
264
321
  );
265
322
  const filterConversations = useCallback(
266
323
  (targetValue) => {
@@ -323,22 +380,42 @@ const LightspeedChat = ({
323
380
  const onSelectActiveItem = useCallback(
324
381
  (_, selectedItem) => {
325
382
  setNewChatCreated(false);
383
+ const newConvId = String(selectedItem);
326
384
  setConversationId((c_id) => {
327
385
  if (c_id !== selectedItem) {
328
- return String(selectedItem);
386
+ return newConvId;
329
387
  }
330
388
  return c_id;
331
389
  });
390
+ setCurrentConversationId(newConvId);
332
391
  setFileContents([]);
333
392
  setUploadError({ message: null });
393
+ setDraftMessage("");
334
394
  scrollToBottomRef.current?.scrollToBottom();
335
395
  },
336
- [setConversationId, setUploadError, setFileContents, scrollToBottomRef]
396
+ [
397
+ setConversationId,
398
+ setUploadError,
399
+ setFileContents,
400
+ setDraftMessage,
401
+ scrollToBottomRef,
402
+ setCurrentConversationId
403
+ ]
337
404
  );
338
405
  const conversationFound = !!conversations.find(
339
406
  (c) => c.conversation_id === conversationId
340
407
  );
341
- const welcomePrompts = newChatCreated && conversationMessages.length === 0 || !conversationFound && conversationMessages.length === 0 ? samplePrompts?.map((prompt) => {
408
+ const getMaxPrompts = () => {
409
+ if (isFullscreenMode) {
410
+ return samplePrompts?.length;
411
+ }
412
+ if (displayMode === ChatbotDisplayMode.docked) {
413
+ return 2;
414
+ }
415
+ return 1;
416
+ };
417
+ const maxPrompts = getMaxPrompts();
418
+ const welcomePrompts = newChatCreated && conversationMessages.length === 0 || !conversationFound && conversationMessages.length === 0 ? samplePrompts?.slice(0, maxPrompts).map((prompt) => {
342
419
  const p = prompt;
343
420
  return {
344
421
  title: p.title,
@@ -351,16 +428,85 @@ const LightspeedChat = ({
351
428
  const handleFilter = useCallback((value) => {
352
429
  setFilterValue(value);
353
430
  }, []);
354
- const onDrawerToggle = useCallback(() => {
355
- setIsDrawerOpen((isOpen) => !isOpen);
431
+ const onChatHistoryDrawerToggle = useCallback(() => {
432
+ setIsChatHistoryDrawerOpen((isOpen) => !isOpen);
433
+ }, []);
434
+ const onSortToggle = useCallback(() => {
435
+ setIsSortSelectOpen((prev) => !prev);
356
436
  }, []);
437
+ const onSortSelect = useCallback(
438
+ (_event, value) => {
439
+ handleSortChange(value);
440
+ setIsSortSelectOpen(false);
441
+ },
442
+ [handleSortChange]
443
+ );
444
+ const getSortLabel = useCallback(
445
+ (option) => {
446
+ const labels = {
447
+ newest: t("sort.newest"),
448
+ oldest: t("sort.oldest"),
449
+ alphabeticalAsc: t("sort.alphabeticalAsc"),
450
+ alphabeticalDesc: t("sort.alphabeticalDesc")
451
+ };
452
+ return labels[option];
453
+ },
454
+ [t]
455
+ );
456
+ const sortToggle = useCallback(
457
+ (toggleRef) => /* @__PURE__ */ jsx(Tooltip, { content: `${t("sort.label")} - ${getSortLabel(selectedSort)}`, children: /* @__PURE__ */ jsx(
458
+ MenuToggle,
459
+ {
460
+ ref: toggleRef,
461
+ "aria-label": t("sort.label"),
462
+ variant: "plain",
463
+ onClick: onSortToggle,
464
+ isExpanded: isSortSelectOpen,
465
+ children: selectedSort === "oldest" || selectedSort === "alphabeticalDesc" ? /* @__PURE__ */ jsx(SortAmountDownAltIcon, {}) : /* @__PURE__ */ jsx(SortAmountDownIcon, {})
466
+ }
467
+ ) }),
468
+ [t, getSortLabel, selectedSort, onSortToggle, isSortSelectOpen]
469
+ );
470
+ const sortDropdown = useMemo(
471
+ () => /* @__PURE__ */ jsx(
472
+ Select,
473
+ {
474
+ id: "sort-select",
475
+ isOpen: isSortSelectOpen,
476
+ selected: selectedSort,
477
+ onSelect: onSortSelect,
478
+ onOpenChange: (isOpen) => setIsSortSelectOpen(isOpen),
479
+ popperProps: { position: "end" },
480
+ toggle: sortToggle,
481
+ shouldFocusToggleOnSelect: true,
482
+ children: /* @__PURE__ */ jsxs(SelectList, { className: classes.sortDropdown, children: [
483
+ /* @__PURE__ */ jsx(SelectOption, { value: "newest", children: t("sort.newest") }),
484
+ /* @__PURE__ */ jsx(SelectOption, { value: "oldest", children: t("sort.oldest") }),
485
+ /* @__PURE__ */ jsx(SelectOption, { value: "alphabeticalAsc", children: t("sort.alphabeticalAsc") }),
486
+ /* @__PURE__ */ jsx(SelectOption, { value: "alphabeticalDesc", children: t("sort.alphabeticalDesc") })
487
+ ] })
488
+ }
489
+ ),
490
+ [
491
+ isSortSelectOpen,
492
+ selectedSort,
493
+ onSortSelect,
494
+ sortToggle,
495
+ t,
496
+ classes.sortDropdown
497
+ ]
498
+ );
357
499
  const handleAttach = (data, event) => {
358
500
  event.preventDefault();
359
501
  handleFileUpload(data);
360
502
  };
503
+ const handleDraftMessage = (_e, value) => setDraftMessage(value);
361
504
  const onAttachRejected = (data) => {
362
505
  data.forEach((attachment) => {
363
- if (!!attachment.errors.find((e) => e.code === "file-invalid-type")) {
506
+ const hasInvalidTypeError = attachment.errors.some(
507
+ (e) => e.code === "file-invalid-type"
508
+ );
509
+ if (hasInvalidTypeError) {
364
510
  setShowAlert(true);
365
511
  setUploadError({
366
512
  message: t("file.upload.error.unsupportedType")
@@ -397,23 +543,29 @@ const LightspeedChat = ({
397
543
  /* @__PURE__ */ jsx(
398
544
  ChatbotHeaderMenu,
399
545
  {
400
- "aria-expanded": isDrawerOpen,
401
- onMenuToggle: () => setIsDrawerOpen(!isDrawerOpen),
546
+ "aria-expanded": isChatHistoryDrawerOpen,
547
+ onMenuToggle: () => setIsChatHistoryDrawerOpen(!isChatHistoryDrawerOpen),
402
548
  className: classes.headerMenu,
403
549
  tooltipContent: t("tooltip.chatHistoryMenu"),
404
550
  "aria-label": t("aria.chatHistoryMenu")
405
551
  }
406
552
  ),
407
- /* @__PURE__ */ jsx(ChatbotHeaderTitle, { className: classes.headerTitle, children: /* @__PURE__ */ jsx(Title, { headingLevel: "h1", size: "3xl", children: t("chatbox.header.title") }) })
553
+ isFullscreenMode && /* @__PURE__ */ jsx(ChatbotHeaderTitle, { className: classes.headerTitle, children: /* @__PURE__ */ jsx(Title, { headingLevel: "h1", size: "3xl", children: t("chatbox.header.title") }) })
408
554
  ] }),
409
555
  /* @__PURE__ */ jsx(
410
556
  LightspeedChatBoxHeader,
411
557
  {
412
558
  selectedModel,
413
- handleSelectedModel: (item) => handleSelectedModel(item),
559
+ handleSelectedModel: (item) => {
560
+ onNewChat();
561
+ handleSelectedModel(item);
562
+ },
414
563
  models,
415
564
  isPinningChatsEnabled,
416
- onPinnedChatsToggle: setIsPinningChatsEnabled
565
+ isModelSelectorDisabled: isSendButtonDisabled,
566
+ setDisplayMode,
567
+ displayMode,
568
+ onPinnedChatsToggle: handlePinningChatsToggle
417
569
  }
418
570
  )
419
571
  ] }),
@@ -421,17 +573,21 @@ const LightspeedChat = ({
421
573
  /* @__PURE__ */ jsx(
422
574
  ChatbotConversationHistoryNav,
423
575
  {
424
- drawerPanelContentProps: { isResizable: true, minSize: "200px" },
576
+ drawerPanelContentProps: {
577
+ isResizable: isFullscreenMode,
578
+ hasNoBorder: !isFullscreenMode,
579
+ style: isFullscreenMode ? undefined : { zIndex: 1300 }
580
+ },
425
581
  reverseButtonOrder: true,
426
582
  displayMode: ChatbotDisplayMode.embedded,
427
- onDrawerToggle,
583
+ onDrawerToggle: onChatHistoryDrawerToggle,
428
584
  title: "",
429
585
  navTitleIcon: null,
430
- isDrawerOpen,
586
+ isDrawerOpen: isChatHistoryDrawerOpen,
431
587
  drawerCloseButtonProps: {
432
588
  "aria-label": t("aria.closeDrawerPanel")
433
589
  },
434
- setIsDrawerOpen,
590
+ setIsDrawerOpen: setIsChatHistoryDrawerOpen,
435
591
  activeItemId: conversationId,
436
592
  onSelectActiveItem,
437
593
  conversations: filterConversations(filterValue),
@@ -449,6 +605,7 @@ const LightspeedChat = ({
449
605
  setFilterValue("");
450
606
  }
451
607
  },
608
+ searchActionEnd: sortDropdown,
452
609
  noResultsState: filterValue && Object.keys(filterConversations(filterValue)).length === 0 ? {
453
610
  bodyText: t("chatbox.emptyState.noResults.body"),
454
611
  titleText: t("chatbox.emptyState.noResults.title"),
@@ -485,7 +642,8 @@ const LightspeedChat = ({
485
642
  welcomePrompts,
486
643
  conversationId,
487
644
  isStreaming: isSendButtonDisabled,
488
- topicRestrictionEnabled
645
+ topicRestrictionEnabled,
646
+ displayMode
489
647
  }
490
648
  ) }),
491
649
  /* @__PURE__ */ jsxs(ChatbotFooter, { className: classes.footer, children: [
@@ -498,6 +656,8 @@ const LightspeedChat = ({
498
656
  hasAttachButton: true,
499
657
  handleAttach,
500
658
  hasMicrophoneButton: true,
659
+ value: draftMessage,
660
+ onChange: handleDraftMessage,
501
661
  buttonProps: {
502
662
  attach: {
503
663
  inputTestId: "attachment-input",
@@ -1 +1 @@
1
- {"version":3,"file":"LightSpeedChat.esm.js","sources":["../../src/components/LightSpeedChat.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 { MouseEvent, useCallback, useEffect, useMemo, useState } from 'react';\nimport { FileRejection } from 'react-dropzone/.';\n\nimport { makeStyles } from '@material-ui/core';\nimport Divider from '@mui/material/Divider';\nimport {\n Chatbot,\n ChatbotAlert,\n ChatbotContent,\n ChatbotDisplayMode,\n ChatbotFooter,\n ChatbotFootnote,\n ChatbotHeader,\n ChatbotHeaderMain,\n ChatbotHeaderMenu,\n ChatbotHeaderTitle,\n FileDropZone,\n MessageBar,\n MessageProps,\n} from '@patternfly/chatbot';\nimport ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';\nimport { DropdownItem, DropEvent, Title } from '@patternfly/react-core';\nimport { PlusIcon, SearchIcon } from '@patternfly/react-icons';\nimport { useQueryClient } from '@tanstack/react-query';\n\nimport { supportedFileTypes, TEMP_CONVERSATION_ID } from '../const';\nimport {\n useBackstageUserIdentity,\n useConversationMessages,\n useConversations,\n useIsMobile,\n useLastOpenedConversation,\n useLightspeedDeletePermission,\n} from '../hooks';\nimport { useLightspeedUpdatePermission } from '../hooks/useLightspeedUpdatePermission';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { useWelcomePrompts } from '../hooks/useWelcomePrompts';\nimport { ConversationSummary } from '../types';\nimport { getAttachments } from '../utils/attachment-utils';\nimport {\n getCategorizeMessages,\n getFootnoteProps,\n} from '../utils/lightspeed-chatbox-utils';\nimport Attachment from './Attachment';\nimport { useFileAttachmentContext } from './AttachmentContext';\nimport { DeleteModal } from './DeleteModal';\nimport FilePreview from './FilePreview';\nimport { LightspeedChatBox } from './LightspeedChatBox';\nimport { LightspeedChatBoxHeader } from './LightspeedChatBoxHeader';\nimport { RenameConversationModal } from './RenameConversationModal';\n\nconst useStyles = makeStyles(theme => ({\n body: {\n // remove default margin and padding from common elements\n '& h1, & h2, & h3, & h4, & h5, & h6, & p, & ul, & ol, & li': {\n margin: 0,\n padding: 0,\n },\n },\n header: {\n padding: `${theme.spacing(3)}px !important`,\n },\n errorContainer: {\n padding: theme.spacing(3),\n },\n headerMenu: {\n // align hamburger icon with title\n '& .pf-v6-c-button': {\n display: 'flex',\n alignItems: 'center',\n },\n },\n headerTitle: {\n justifyContent: 'left !important',\n },\n footer: {\n '&>.pf-chatbot__footer-container': {\n width: '95% !important',\n maxWidth: 'unset !important',\n },\n },\n footerPopover: {\n '& img': {\n maxWidth: '100%',\n },\n },\n}));\n\ntype LightspeedChatProps = {\n selectedModel: string;\n topicRestrictionEnabled: boolean;\n selectedProvider: string;\n userName?: string;\n avatar?: string;\n profileLoading: boolean;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string; provider: string }[];\n};\n\nexport const LightspeedChat = ({\n selectedModel,\n topicRestrictionEnabled,\n selectedProvider,\n userName,\n avatar,\n profileLoading,\n handleSelectedModel,\n models,\n}: LightspeedChatProps) => {\n const isMobile = useIsMobile();\n const classes = useStyles();\n const { t } = useTranslation();\n const user = useBackstageUserIdentity();\n const [filterValue, setFilterValue] = useState<string>('');\n const [announcement, setAnnouncement] = useState<string>('');\n const [conversationId, setConversationId] = useState<string>('');\n const [isDrawerOpen, setIsDrawerOpen] = useState<boolean>(!isMobile);\n const [newChatCreated, setNewChatCreated] = useState<boolean>(false);\n const [isSendButtonDisabled, setIsSendButtonDisabled] =\n useState<boolean>(false);\n const [isPinningChatsEnabled, setIsPinningChatsEnabled] = useState(true); // read from user settings in future\n const [pinnedChats, setPinnedChats] = useState<string[]>([]); // read from user settings in future\n const [targetConversationId, setTargetConversationId] = useState<string>('');\n const [isDeleteModalOpen, setIsDeleteModalOpen] = useState<boolean>(false);\n const [isRenameModalOpen, setIsRenameModalOpen] = useState<boolean>(false);\n const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } =\n useLastOpenedConversation(user);\n\n const {\n uploadError,\n showAlert,\n fileContents,\n setShowAlert,\n setFileContents,\n handleFileUpload,\n setUploadError,\n } = useFileAttachmentContext();\n\n // Sync conversationId with lastOpenedId whenever lastOpenedId changes\n useEffect(() => {\n if (isReady && lastOpenedId !== null) {\n setConversationId(lastOpenedId);\n }\n }, [lastOpenedId, isReady]);\n\n useEffect(() => {\n if (!isPinningChatsEnabled) {\n setPinnedChats([]);\n }\n }, [isPinningChatsEnabled]);\n\n const queryClient = useQueryClient();\n\n const {\n data: conversations = [],\n isLoading,\n isRefetching,\n } = useConversations();\n\n const { allowed: hasDeleteAccess } = useLightspeedDeletePermission();\n const { allowed: hasUpdateAccess } = useLightspeedUpdatePermission();\n const samplePrompts = useWelcomePrompts();\n useEffect(() => {\n if (user && lastOpenedId === null && isReady) {\n setConversationId(TEMP_CONVERSATION_ID);\n setNewChatCreated(true);\n }\n }, [user, isReady, lastOpenedId, setConversationId]);\n\n useEffect(() => {\n // Clear last opened conversationId when there are no conversations.\n if (\n !isLoading &&\n !isRefetching &&\n conversations.length === 0 &&\n lastOpenedId\n ) {\n clearLastOpenedId();\n }\n }, [isLoading, isRefetching, conversations, lastOpenedId, clearLastOpenedId]);\n\n useEffect(() => {\n // Update last opened conversation whenever `conversationId` changes\n if (conversationId) {\n setLastOpenedId(conversationId);\n }\n }, [conversationId, setLastOpenedId]);\n\n const onStart = (conv_id: string) => {\n setConversationId(conv_id);\n };\n\n const onComplete = (message: string) => {\n setIsSendButtonDisabled(false);\n setAnnouncement(`Message from Bot: ${message}`);\n queryClient.invalidateQueries({\n queryKey: ['conversations'],\n });\n queryClient.invalidateQueries({\n queryKey: ['conversationMessages', conversationId],\n });\n setNewChatCreated(false);\n };\n\n const { conversationMessages, handleInputPrompt, scrollToBottomRef } =\n useConversationMessages(\n conversationId,\n userName,\n selectedModel,\n selectedProvider,\n avatar,\n onComplete,\n onStart,\n );\n\n const [messages, setMessages] =\n useState<MessageProps[]>(conversationMessages);\n\n const sendMessage = (message: string | number) => {\n if (conversationId !== TEMP_CONVERSATION_ID) {\n setNewChatCreated(false);\n }\n setAnnouncement(\n t('conversation.announcement.userMessage' as any, {\n prompt: message.toString(),\n }),\n );\n handleInputPrompt(message.toString(), getAttachments(fileContents));\n setIsSendButtonDisabled(true);\n setFileContents([]);\n };\n\n const onNewChat = useCallback(() => {\n (async () => {\n if (conversationId !== TEMP_CONVERSATION_ID) {\n setMessages([]);\n setFileContents([]);\n setUploadError({ message: null });\n setConversationId(TEMP_CONVERSATION_ID);\n setNewChatCreated(true);\n }\n })();\n }, [\n conversationId,\n setConversationId,\n setMessages,\n setUploadError,\n setFileContents,\n ]);\n\n const openDeleteModal = (conversation_id: string) => {\n setTargetConversationId(conversation_id);\n setIsDeleteModalOpen(true);\n };\n\n const openChatRenameModal = (conversation_id: string) => {\n setTargetConversationId(conversation_id);\n setIsRenameModalOpen(true);\n };\n\n const handleDeleteConversation = useCallback(() => {\n if (targetConversationId === lastOpenedId) {\n onNewChat();\n clearLastOpenedId();\n }\n setIsDeleteModalOpen(false);\n }, [clearLastOpenedId, lastOpenedId, onNewChat, targetConversationId]);\n\n const pinChat = (convId: string) => {\n setPinnedChats(prev => [...prev, convId]); // write to user settings in future\n };\n\n const unpinChat = (convId: string) => {\n setPinnedChats(prev => prev.filter(id => id !== convId)); // write to user settings in future\n };\n\n const additionalMessageProps = useCallback(\n (conversationSummary: ConversationSummary) => {\n const isChatFavorite = pinnedChats?.find(\n c => c === conversationSummary.conversation_id,\n );\n return {\n menuItems: (\n <>\n <DropdownItem\n isDisabled={!hasUpdateAccess}\n onClick={() =>\n openChatRenameModal(conversationSummary.conversation_id)\n }\n >\n {t('conversation.rename')}\n </DropdownItem>\n {isPinningChatsEnabled && (\n <>\n {isChatFavorite ? (\n <DropdownItem\n onClick={() =>\n unpinChat(conversationSummary.conversation_id)\n }\n >\n {t('conversation.removeFromPinnedChats')}\n </DropdownItem>\n ) : (\n <DropdownItem\n onClick={() => pinChat(conversationSummary.conversation_id)}\n >\n {t('conversation.addToPinnedChats')}\n </DropdownItem>\n )}\n </>\n )}\n <DropdownItem\n isDisabled={!hasDeleteAccess}\n onClick={() =>\n openDeleteModal(conversationSummary.conversation_id)\n }\n >\n {t('conversation.delete')}\n </DropdownItem>\n </>\n ),\n };\n },\n [pinnedChats, hasDeleteAccess, isPinningChatsEnabled, hasUpdateAccess, t],\n );\n\n const categorizedMessages = useMemo(\n () =>\n getCategorizeMessages(\n conversations,\n pinnedChats,\n additionalMessageProps,\n t,\n ),\n [additionalMessageProps, conversations, pinnedChats, t],\n );\n\n const filterConversations = useCallback(\n (targetValue: string) => {\n const pinnedChatsKey = t('conversation.category.pinnedChats') || 'Pinned';\n let isNoPinnedChatsSearchResults = false;\n let isNoRecentChatsSearchResults = false;\n const filteredConversations = Object.entries(categorizedMessages).reduce(\n (acc, [key, items]) => {\n const filteredItems = items.filter(item =>\n item.text\n .toLocaleLowerCase('en-US')\n .includes(targetValue.toLocaleLowerCase('en-US')),\n );\n const isPinnedCategory = key === pinnedChatsKey;\n if (isPinnedCategory && isPinningChatsEnabled) {\n if (filteredItems.length > 0) {\n acc[pinnedChatsKey] = filteredItems;\n } else {\n isNoPinnedChatsSearchResults =\n categorizedMessages[pinnedChatsKey].length > 0;\n acc[pinnedChatsKey] = [\n {\n id: isNoPinnedChatsSearchResults\n ? 'no-pinned-chats-search-results'\n : 'no-pinned-chats',\n text: isNoPinnedChatsSearchResults\n ? t('common.noSearchResults')\n : t('chatbox.emptyState.noPinnedChats'),\n noIcon: true,\n additionalProps: {\n isDisabled: true,\n },\n },\n ];\n }\n } else if (!isPinnedCategory) {\n if (filteredItems.length > 0) {\n acc[key] = filteredItems;\n } else {\n isNoRecentChatsSearchResults =\n categorizedMessages[key].length > 0;\n\n acc[key] = [\n {\n id: isNoRecentChatsSearchResults\n ? 'no-recent-chats-search-results'\n : 'no-recent-chats',\n text: isNoRecentChatsSearchResults\n ? t('common.noSearchResults')\n : t('chatbox.emptyState.noRecentChats'),\n noIcon: true,\n additionalProps: {\n isDisabled: true,\n },\n },\n ];\n }\n }\n return acc;\n },\n {} as any,\n );\n // If both sections had items but search filtered them all out, return empty object\n // so PatternFly's default empty state shows instead of custom empty state messages\n if (isNoPinnedChatsSearchResults && isNoRecentChatsSearchResults) {\n return {};\n }\n return filteredConversations;\n },\n [categorizedMessages, isPinningChatsEnabled, t],\n );\n\n useEffect(() => {\n setMessages(conversationMessages);\n }, [conversationMessages]);\n\n const onSelectActiveItem = useCallback(\n (_: MouseEvent | undefined, selectedItem: string | number | undefined) => {\n setNewChatCreated(false);\n setConversationId((c_id: string) => {\n if (c_id !== selectedItem) {\n return String(selectedItem);\n }\n return c_id;\n });\n setFileContents([]);\n setUploadError({ message: null });\n scrollToBottomRef.current?.scrollToBottom();\n },\n [setConversationId, setUploadError, setFileContents, scrollToBottomRef],\n );\n\n const conversationFound = !!conversations.find(\n (c: ConversationSummary) => c.conversation_id === conversationId,\n );\n\n const welcomePrompts =\n (newChatCreated && conversationMessages.length === 0) ||\n (!conversationFound && conversationMessages.length === 0)\n ? samplePrompts?.map(prompt => {\n const p = prompt as { title: string; message: string };\n return {\n title: p.title,\n message: p.message,\n onClick: () => {\n sendMessage(p.message);\n },\n };\n })\n : [];\n\n const handleFilter = useCallback((value: string) => {\n setFilterValue(value);\n }, []);\n\n const onDrawerToggle = useCallback(() => {\n setIsDrawerOpen(isOpen => !isOpen);\n }, []);\n\n const handleAttach = (data: File[], event: DropEvent) => {\n event.preventDefault();\n handleFileUpload(data);\n };\n\n const onAttachRejected = (data: FileRejection[]) => {\n data.forEach(attachment => {\n if (!!attachment.errors.find(e => e.code === 'file-invalid-type')) {\n setShowAlert(true);\n setUploadError({\n message: t('file.upload.error.unsupportedType'),\n });\n }\n });\n };\n\n return (\n <>\n {isDeleteModalOpen && (\n <DeleteModal\n isOpen={isDeleteModalOpen}\n conversationId={targetConversationId}\n onClose={() => setIsDeleteModalOpen(false)}\n onConfirm={handleDeleteConversation}\n />\n )}\n {isRenameModalOpen && (\n <RenameConversationModal\n isOpen={isRenameModalOpen}\n onClose={() => setIsRenameModalOpen(false)}\n conversationId={targetConversationId}\n />\n )}\n <Chatbot\n displayMode={ChatbotDisplayMode.embedded}\n className={classes.body}\n >\n <ChatbotHeader className={classes.header}>\n <ChatbotHeaderMain>\n <ChatbotHeaderMenu\n aria-expanded={isDrawerOpen}\n onMenuToggle={() => setIsDrawerOpen(!isDrawerOpen)}\n className={classes.headerMenu}\n tooltipContent={t('tooltip.chatHistoryMenu')}\n aria-label={t('aria.chatHistoryMenu')}\n />\n <ChatbotHeaderTitle className={classes.headerTitle}>\n <Title headingLevel=\"h1\" size=\"3xl\">\n {t('chatbox.header.title')}\n </Title>\n </ChatbotHeaderTitle>\n </ChatbotHeaderMain>\n\n <LightspeedChatBoxHeader\n selectedModel={selectedModel}\n handleSelectedModel={item => handleSelectedModel(item)}\n models={models}\n isPinningChatsEnabled={isPinningChatsEnabled}\n onPinnedChatsToggle={setIsPinningChatsEnabled}\n />\n </ChatbotHeader>\n <Divider />\n <ChatbotConversationHistoryNav\n drawerPanelContentProps={{ isResizable: true, minSize: '200px' }}\n reverseButtonOrder\n displayMode={ChatbotDisplayMode.embedded}\n onDrawerToggle={onDrawerToggle}\n title=\"\"\n navTitleIcon={null}\n isDrawerOpen={isDrawerOpen}\n drawerCloseButtonProps={{\n 'aria-label': t('aria.closeDrawerPanel'),\n }}\n setIsDrawerOpen={setIsDrawerOpen}\n activeItemId={conversationId}\n onSelectActiveItem={onSelectActiveItem}\n conversations={filterConversations(filterValue)}\n onNewChat={newChatCreated ? undefined : onNewChat}\n newChatButtonText={t('button.newChat')}\n newChatButtonProps={{\n icon: <PlusIcon />,\n }}\n handleTextInputChange={handleFilter}\n searchInputPlaceholder={t('chatbox.search.placeholder')}\n searchInputAriaLabel={t('aria.search.placeholder')}\n searchInputProps={{\n value: filterValue,\n onClear: () => {\n setFilterValue('');\n },\n }}\n noResultsState={\n filterValue &&\n Object.keys(filterConversations(filterValue)).length === 0\n ? {\n bodyText: t('chatbox.emptyState.noResults.body'),\n titleText: t('chatbox.emptyState.noResults.title'),\n icon: SearchIcon,\n }\n : undefined\n }\n drawerContent={\n <FileDropZone\n onFileDrop={(e, data) => handleAttach(data, e)}\n displayMode={ChatbotDisplayMode.embedded}\n infoText={t('chatbox.fileUpload.infoText')}\n allowedFileTypes={supportedFileTypes}\n onAttachRejected={onAttachRejected}\n >\n {showAlert && uploadError.message && (\n <div className={classes.errorContainer}>\n <ChatbotAlert\n component=\"h4\"\n title={t('chatbox.fileUpload.failed')}\n variant={uploadError.type ?? 'danger'}\n isInline\n onClose={() => setUploadError({ message: null })}\n >\n {uploadError.message}\n </ChatbotAlert>\n </div>\n )}\n\n <ChatbotContent>\n <LightspeedChatBox\n userName={userName}\n messages={messages}\n profileLoading={profileLoading}\n announcement={announcement}\n ref={scrollToBottomRef}\n welcomePrompts={welcomePrompts}\n conversationId={conversationId}\n isStreaming={isSendButtonDisabled}\n topicRestrictionEnabled={topicRestrictionEnabled}\n />\n </ChatbotContent>\n <ChatbotFooter className={classes.footer}>\n <FilePreview />\n <MessageBar\n onSendMessage={sendMessage}\n isSendButtonDisabled={isSendButtonDisabled}\n hasAttachButton\n handleAttach={handleAttach}\n hasMicrophoneButton\n buttonProps={{\n attach: {\n inputTestId: 'attachment-input',\n tooltipContent: t('tooltip.attach'),\n },\n microphone: {\n tooltipContent: {\n active: t('tooltip.microphone.active'),\n inactive: t('tooltip.microphone.inactive'),\n },\n },\n send: {\n tooltipContent: t('tooltip.send'),\n },\n }}\n allowedFileTypes={supportedFileTypes}\n onAttachRejected={onAttachRejected}\n placeholder={t('chatbox.message.placeholder')}\n />\n <ChatbotFootnote\n {...getFootnoteProps(classes.footerPopover, t)}\n />\n </ChatbotFooter>\n </FileDropZone>\n }\n />\n </Chatbot>\n <Attachment />\n </>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LightSpeedChat.esm.js","sources":["../../src/components/LightSpeedChat.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 ChangeEvent,\n MouseEvent,\n Ref,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport { FileRejection } from 'react-dropzone/.';\n\nimport { makeStyles } from '@material-ui/core';\nimport Divider from '@mui/material/Divider';\nimport {\n Chatbot,\n ChatbotAlert,\n ChatbotContent,\n ChatbotDisplayMode,\n ChatbotFooter,\n ChatbotFootnote,\n ChatbotHeader,\n ChatbotHeaderMain,\n ChatbotHeaderMenu,\n ChatbotHeaderTitle,\n FileDropZone,\n MessageBar,\n MessageProps,\n} from '@patternfly/chatbot';\nimport ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';\nimport {\n DropdownItem,\n DropEvent,\n MenuToggle,\n MenuToggleElement,\n Select,\n SelectList,\n SelectOption,\n Title,\n Tooltip,\n} from '@patternfly/react-core';\nimport {\n PlusIcon,\n SearchIcon,\n SortAmountDownAltIcon,\n SortAmountDownIcon,\n} from '@patternfly/react-icons';\nimport { useQueryClient } from '@tanstack/react-query';\n\nimport { supportedFileTypes, TEMP_CONVERSATION_ID } from '../const';\nimport {\n useBackstageUserIdentity,\n useConversationMessages,\n useConversations,\n useIsMobile,\n useLastOpenedConversation,\n useLightspeedDeletePermission,\n usePinnedChatsSettings,\n useSortSettings,\n} from '../hooks';\nimport { useLightspeedDrawerContext } from '../hooks/useLightspeedDrawerContext';\nimport { useLightspeedUpdatePermission } from '../hooks/useLightspeedUpdatePermission';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { useWelcomePrompts } from '../hooks/useWelcomePrompts';\nimport { ConversationSummary } from '../types';\nimport { getAttachments } from '../utils/attachment-utils';\nimport {\n getCategorizeMessages,\n getFootnoteProps,\n SortOption,\n} from '../utils/lightspeed-chatbox-utils';\nimport Attachment from './Attachment';\nimport { useFileAttachmentContext } from './AttachmentContext';\nimport { DeleteModal } from './DeleteModal';\nimport FilePreview from './FilePreview';\nimport { LightspeedChatBox } from './LightspeedChatBox';\nimport { LightspeedChatBoxHeader } from './LightspeedChatBoxHeader';\nimport { RenameConversationModal } from './RenameConversationModal';\n\nconst useStyles = makeStyles(theme => ({\n body: {\n // remove default margin and padding from common elements\n '& h1, & h2, & h3, & h4, & h5, & h6, & p, & ul, & ol, & li': {\n margin: 0,\n padding: 0,\n },\n },\n header: {\n padding: `${theme.spacing(3)}px !important`,\n },\n errorContainer: {\n padding: theme.spacing(3),\n },\n headerMenu: {\n // align hamburger icon with title\n '& .pf-v6-c-button': {\n display: 'flex',\n alignItems: 'center',\n },\n },\n headerTitle: {\n justifyContent: 'left !important',\n },\n footer: {\n '&>.pf-chatbot__footer-container': {\n width: '95% !important',\n maxWidth: 'unset !important',\n },\n },\n footerPopover: {\n '& img': {\n maxWidth: '100%',\n },\n },\n sortDropdown: {\n padding: 0,\n margin: 0,\n },\n}));\n\ntype LightspeedChatProps = {\n selectedModel: string;\n topicRestrictionEnabled: boolean;\n selectedProvider: string;\n userName?: string;\n avatar?: string;\n profileLoading: boolean;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string; provider: string }[];\n};\n\nexport const LightspeedChat = ({\n selectedModel,\n topicRestrictionEnabled,\n selectedProvider,\n userName,\n avatar,\n profileLoading,\n handleSelectedModel,\n models,\n}: LightspeedChatProps) => {\n const isMobile = useIsMobile();\n const classes = useStyles();\n const { t } = useTranslation();\n const user = useBackstageUserIdentity();\n const [filterValue, setFilterValue] = useState<string>('');\n const [announcement, setAnnouncement] = useState<string>('');\n const [conversationId, setConversationId] = useState<string>('');\n const [newChatCreated, setNewChatCreated] = useState<boolean>(false);\n const [isSendButtonDisabled, setIsSendButtonDisabled] =\n useState<boolean>(false);\n const [targetConversationId, setTargetConversationId] = useState<string>('');\n const [isDeleteModalOpen, setIsDeleteModalOpen] = useState<boolean>(false);\n const [isRenameModalOpen, setIsRenameModalOpen] = useState<boolean>(false);\n const [isSortSelectOpen, setIsSortSelectOpen] = useState<boolean>(false);\n const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } =\n useLastOpenedConversation(user);\n const {\n displayMode,\n setDisplayMode,\n currentConversationId: routeConversationId,\n setCurrentConversationId,\n draftMessage,\n setDraftMessage,\n } = useLightspeedDrawerContext();\n const isFullscreenMode = displayMode === ChatbotDisplayMode.embedded;\n const [isChatHistoryDrawerOpen, setIsChatHistoryDrawerOpen] =\n useState<boolean>(!isMobile && isFullscreenMode);\n\n // Open the chat history drawer when entering fullscreen mode on desktop\n useEffect(() => {\n if (!isMobile && isFullscreenMode) {\n setIsChatHistoryDrawerOpen(true);\n }\n }, [isMobile, isFullscreenMode]);\n\n const {\n isPinningChatsEnabled,\n pinnedChats,\n handlePinningChatsToggle,\n pinChat,\n unpinChat,\n } = usePinnedChatsSettings(user);\n\n const { selectedSort, handleSortChange } = useSortSettings(user);\n\n const {\n uploadError,\n showAlert,\n fileContents,\n setShowAlert,\n setFileContents,\n handleFileUpload,\n setUploadError,\n } = useFileAttachmentContext();\n\n // Sync conversationId with lastOpenedId whenever lastOpenedId changes\n useEffect(() => {\n if (isReady && lastOpenedId !== null) {\n setConversationId(lastOpenedId);\n }\n }, [lastOpenedId, isReady]);\n\n const queryClient = useQueryClient();\n\n const {\n data: conversations = [],\n isLoading,\n isRefetching,\n } = useConversations();\n\n const { allowed: hasDeleteAccess } = useLightspeedDeletePermission();\n const { allowed: hasUpdateAccess } = useLightspeedUpdatePermission();\n const samplePrompts = useWelcomePrompts();\n useEffect(() => {\n if (user && lastOpenedId === null && isReady) {\n setConversationId(TEMP_CONVERSATION_ID);\n setNewChatCreated(true);\n }\n }, [user, isReady, lastOpenedId, setConversationId]);\n\n useEffect(() => {\n // Clear last opened conversationId when there are no conversations.\n if (\n !isLoading &&\n !isRefetching &&\n conversations.length === 0 &&\n lastOpenedId\n ) {\n clearLastOpenedId();\n }\n }, [isLoading, isRefetching, conversations, lastOpenedId, clearLastOpenedId]);\n\n useEffect(() => {\n if (\n !isLoading &&\n !isRefetching &&\n routeConversationId &&\n isFullscreenMode\n ) {\n const conversationExists = conversations.some(\n (c: ConversationSummary) => c.conversation_id === routeConversationId,\n );\n if (!conversationExists) {\n // Conversation from route doesn't exist, start a new chat\n setConversationId(TEMP_CONVERSATION_ID);\n setCurrentConversationId(undefined);\n setNewChatCreated(true);\n } else if (conversationId !== routeConversationId) {\n setConversationId(routeConversationId);\n }\n }\n }, [\n isLoading,\n isRefetching,\n routeConversationId,\n conversations,\n displayMode,\n conversationId,\n setCurrentConversationId,\n isFullscreenMode,\n ]);\n\n useEffect(() => {\n // Update last opened conversation whenever `conversationId` changes\n if (conversationId) {\n setLastOpenedId(conversationId);\n }\n }, [conversationId, setLastOpenedId]);\n\n const onStart = (conv_id: string) => {\n setConversationId(conv_id);\n setCurrentConversationId(conv_id);\n };\n\n const onComplete = (message: string) => {\n setIsSendButtonDisabled(false);\n setAnnouncement(`Message from Bot: ${message}`);\n queryClient.invalidateQueries({\n queryKey: ['conversations'],\n });\n queryClient.invalidateQueries({\n queryKey: ['conversationMessages', conversationId],\n });\n setNewChatCreated(false);\n };\n\n const { conversationMessages, handleInputPrompt, scrollToBottomRef } =\n useConversationMessages(\n conversationId,\n userName,\n selectedModel,\n selectedProvider,\n avatar,\n onComplete,\n onStart,\n );\n\n const [messages, setMessages] =\n useState<MessageProps[]>(conversationMessages);\n\n const sendMessage = (message: string | number) => {\n if (conversationId !== TEMP_CONVERSATION_ID) {\n setNewChatCreated(false);\n }\n setAnnouncement(\n t('conversation.announcement.userMessage' as any, {\n prompt: message.toString(),\n }),\n );\n handleInputPrompt(message.toString(), getAttachments(fileContents));\n setIsSendButtonDisabled(true);\n setFileContents([]);\n setDraftMessage('');\n };\n\n const onNewChat = useCallback(() => {\n (async () => {\n if (conversationId !== TEMP_CONVERSATION_ID) {\n setMessages([]);\n setFileContents([]);\n setUploadError({ message: null });\n setDraftMessage('');\n setConversationId(TEMP_CONVERSATION_ID);\n setNewChatCreated(true);\n setCurrentConversationId(undefined);\n if (!isFullscreenMode) {\n setIsChatHistoryDrawerOpen(false);\n }\n }\n })();\n }, [\n conversationId,\n setFileContents,\n setUploadError,\n setDraftMessage,\n setCurrentConversationId,\n isFullscreenMode,\n ]);\n\n const openDeleteModal = (conversation_id: string) => {\n setTargetConversationId(conversation_id);\n setIsDeleteModalOpen(true);\n };\n\n const openChatRenameModal = (conversation_id: string) => {\n setTargetConversationId(conversation_id);\n setIsRenameModalOpen(true);\n };\n\n const handleDeleteConversation = useCallback(() => {\n if (targetConversationId === lastOpenedId) {\n onNewChat();\n clearLastOpenedId();\n }\n setIsDeleteModalOpen(false);\n }, [clearLastOpenedId, lastOpenedId, onNewChat, targetConversationId]);\n\n const additionalMessageProps = useCallback(\n (conversationSummary: ConversationSummary) => {\n const isChatFavorite = pinnedChats?.find(\n c => c === conversationSummary.conversation_id,\n );\n return {\n menuItems: (\n <>\n <DropdownItem\n isDisabled={!hasUpdateAccess}\n onClick={() =>\n openChatRenameModal(conversationSummary.conversation_id)\n }\n >\n {t('conversation.rename')}\n </DropdownItem>\n {isPinningChatsEnabled && (\n <>\n {isChatFavorite ? (\n <DropdownItem\n onClick={() =>\n unpinChat(conversationSummary.conversation_id)\n }\n >\n {t('conversation.removeFromPinnedChats')}\n </DropdownItem>\n ) : (\n <DropdownItem\n onClick={() => pinChat(conversationSummary.conversation_id)}\n >\n {t('conversation.addToPinnedChats')}\n </DropdownItem>\n )}\n </>\n )}\n <DropdownItem\n isDisabled={!hasDeleteAccess}\n onClick={() =>\n openDeleteModal(conversationSummary.conversation_id)\n }\n >\n {t('conversation.delete')}\n </DropdownItem>\n </>\n ),\n };\n },\n [\n pinnedChats,\n hasDeleteAccess,\n isPinningChatsEnabled,\n hasUpdateAccess,\n t,\n pinChat,\n unpinChat,\n ],\n );\n\n const categorizedMessages = useMemo(\n () =>\n getCategorizeMessages(\n conversations,\n pinnedChats,\n additionalMessageProps,\n t,\n selectedSort,\n ),\n [additionalMessageProps, conversations, pinnedChats, t, selectedSort],\n );\n\n const filterConversations = useCallback(\n (targetValue: string) => {\n const pinnedChatsKey = t('conversation.category.pinnedChats') || 'Pinned';\n let isNoPinnedChatsSearchResults = false;\n let isNoRecentChatsSearchResults = false;\n const filteredConversations = Object.entries(categorizedMessages).reduce(\n (acc, [key, items]) => {\n const filteredItems = items.filter(item =>\n item.text\n .toLocaleLowerCase('en-US')\n .includes(targetValue.toLocaleLowerCase('en-US')),\n );\n const isPinnedCategory = key === pinnedChatsKey;\n if (isPinnedCategory && isPinningChatsEnabled) {\n if (filteredItems.length > 0) {\n acc[pinnedChatsKey] = filteredItems;\n } else {\n isNoPinnedChatsSearchResults =\n categorizedMessages[pinnedChatsKey].length > 0;\n acc[pinnedChatsKey] = [\n {\n id: isNoPinnedChatsSearchResults\n ? 'no-pinned-chats-search-results'\n : 'no-pinned-chats',\n text: isNoPinnedChatsSearchResults\n ? t('common.noSearchResults')\n : t('chatbox.emptyState.noPinnedChats'),\n noIcon: true,\n additionalProps: {\n isDisabled: true,\n },\n },\n ];\n }\n } else if (!isPinnedCategory) {\n if (filteredItems.length > 0) {\n acc[key] = filteredItems;\n } else {\n isNoRecentChatsSearchResults =\n categorizedMessages[key].length > 0;\n\n acc[key] = [\n {\n id: isNoRecentChatsSearchResults\n ? 'no-recent-chats-search-results'\n : 'no-recent-chats',\n text: isNoRecentChatsSearchResults\n ? t('common.noSearchResults')\n : t('chatbox.emptyState.noRecentChats'),\n noIcon: true,\n additionalProps: {\n isDisabled: true,\n },\n },\n ];\n }\n }\n return acc;\n },\n {} as any,\n );\n // If both sections had items but search filtered them all out, return empty object\n // so PatternFly's default empty state shows instead of custom empty state messages\n if (isNoPinnedChatsSearchResults && isNoRecentChatsSearchResults) {\n return {};\n }\n return filteredConversations;\n },\n [categorizedMessages, isPinningChatsEnabled, t],\n );\n\n useEffect(() => {\n setMessages(conversationMessages);\n }, [conversationMessages]);\n\n const onSelectActiveItem = useCallback(\n (_: MouseEvent | undefined, selectedItem: string | number | undefined) => {\n setNewChatCreated(false);\n const newConvId = String(selectedItem);\n setConversationId((c_id: string) => {\n if (c_id !== selectedItem) {\n return newConvId;\n }\n return c_id;\n });\n setCurrentConversationId(newConvId);\n setFileContents([]);\n setUploadError({ message: null });\n setDraftMessage('');\n scrollToBottomRef.current?.scrollToBottom();\n },\n [\n setConversationId,\n setUploadError,\n setFileContents,\n setDraftMessage,\n scrollToBottomRef,\n setCurrentConversationId,\n ],\n );\n\n const conversationFound = !!conversations.find(\n (c: ConversationSummary) => c.conversation_id === conversationId,\n );\n\n const getMaxPrompts = () => {\n if (isFullscreenMode) {\n return samplePrompts?.length; // In the Fullscreen mode, show all prompts\n }\n if (displayMode === ChatbotDisplayMode.docked) {\n return 2; // In the docked mode, show 2 prompts\n }\n return 1; // In the overlay mode, show 1 prompt\n };\n const maxPrompts = getMaxPrompts();\n\n const welcomePrompts =\n (newChatCreated && conversationMessages.length === 0) ||\n (!conversationFound && conversationMessages.length === 0)\n ? samplePrompts?.slice(0, maxPrompts).map(prompt => {\n const p = prompt as { title: string; message: string };\n return {\n title: p.title,\n message: p.message,\n onClick: () => {\n sendMessage(p.message);\n },\n };\n })\n : [];\n\n const handleFilter = useCallback((value: string) => {\n setFilterValue(value);\n }, []);\n\n const onChatHistoryDrawerToggle = useCallback(() => {\n setIsChatHistoryDrawerOpen(isOpen => !isOpen);\n }, []);\n\n const onSortToggle = useCallback(() => {\n setIsSortSelectOpen(prev => !prev);\n }, []);\n\n const onSortSelect = useCallback(\n (_event?: MouseEvent<Element>, value?: string | number) => {\n handleSortChange(value as SortOption);\n setIsSortSelectOpen(false);\n },\n [handleSortChange],\n );\n\n const getSortLabel = useCallback(\n (option: SortOption): string => {\n const labels: Record<SortOption, string> = {\n newest: t('sort.newest'),\n oldest: t('sort.oldest'),\n alphabeticalAsc: t('sort.alphabeticalAsc'),\n alphabeticalDesc: t('sort.alphabeticalDesc'),\n };\n return labels[option];\n },\n [t],\n );\n\n const sortToggle = useCallback(\n (toggleRef: Ref<MenuToggleElement>) => (\n <Tooltip content={`${t('sort.label')} - ${getSortLabel(selectedSort)}`}>\n <MenuToggle\n ref={toggleRef}\n aria-label={t('sort.label')}\n variant=\"plain\"\n onClick={onSortToggle}\n isExpanded={isSortSelectOpen}\n >\n {selectedSort === 'oldest' || selectedSort === 'alphabeticalDesc' ? (\n <SortAmountDownAltIcon />\n ) : (\n <SortAmountDownIcon />\n )}\n </MenuToggle>\n </Tooltip>\n ),\n [t, getSortLabel, selectedSort, onSortToggle, isSortSelectOpen],\n );\n\n const sortDropdown = useMemo(\n () => (\n <Select\n id=\"sort-select\"\n isOpen={isSortSelectOpen}\n selected={selectedSort}\n onSelect={onSortSelect}\n onOpenChange={(isOpen: boolean) => setIsSortSelectOpen(isOpen)}\n popperProps={{ position: 'end' }}\n toggle={sortToggle}\n shouldFocusToggleOnSelect\n >\n <SelectList className={classes.sortDropdown}>\n <SelectOption value=\"newest\">{t('sort.newest')}</SelectOption>\n <SelectOption value=\"oldest\">{t('sort.oldest')}</SelectOption>\n <SelectOption value=\"alphabeticalAsc\">\n {t('sort.alphabeticalAsc')}\n </SelectOption>\n <SelectOption value=\"alphabeticalDesc\">\n {t('sort.alphabeticalDesc')}\n </SelectOption>\n </SelectList>\n </Select>\n ),\n [\n isSortSelectOpen,\n selectedSort,\n onSortSelect,\n sortToggle,\n t,\n classes.sortDropdown,\n ],\n );\n\n const handleAttach = (data: File[], event: DropEvent) => {\n event.preventDefault();\n handleFileUpload(data);\n };\n\n const handleDraftMessage = (\n _e: ChangeEvent<HTMLTextAreaElement>,\n value: string | number,\n ) => setDraftMessage(value as any);\n\n const onAttachRejected = (data: FileRejection[]) => {\n data.forEach(attachment => {\n const hasInvalidTypeError = attachment.errors.some(\n e => e.code === 'file-invalid-type',\n );\n if (hasInvalidTypeError) {\n setShowAlert(true);\n setUploadError({\n message: t('file.upload.error.unsupportedType'),\n });\n }\n });\n };\n\n return (\n <>\n {isDeleteModalOpen && (\n <DeleteModal\n isOpen={isDeleteModalOpen}\n conversationId={targetConversationId}\n onClose={() => setIsDeleteModalOpen(false)}\n onConfirm={handleDeleteConversation}\n />\n )}\n {isRenameModalOpen && (\n <RenameConversationModal\n isOpen={isRenameModalOpen}\n onClose={() => setIsRenameModalOpen(false)}\n conversationId={targetConversationId}\n />\n )}\n <Chatbot\n displayMode={ChatbotDisplayMode.embedded}\n className={classes.body}\n >\n <ChatbotHeader className={classes.header}>\n <ChatbotHeaderMain>\n <ChatbotHeaderMenu\n aria-expanded={isChatHistoryDrawerOpen}\n onMenuToggle={() =>\n setIsChatHistoryDrawerOpen(!isChatHistoryDrawerOpen)\n }\n className={classes.headerMenu}\n tooltipContent={t('tooltip.chatHistoryMenu')}\n aria-label={t('aria.chatHistoryMenu')}\n />\n {isFullscreenMode && (\n <ChatbotHeaderTitle className={classes.headerTitle}>\n <Title headingLevel=\"h1\" size=\"3xl\">\n {t('chatbox.header.title')}\n </Title>\n </ChatbotHeaderTitle>\n )}\n </ChatbotHeaderMain>\n\n <LightspeedChatBoxHeader\n selectedModel={selectedModel}\n handleSelectedModel={item => {\n onNewChat();\n handleSelectedModel(item);\n }}\n models={models}\n isPinningChatsEnabled={isPinningChatsEnabled}\n isModelSelectorDisabled={isSendButtonDisabled}\n setDisplayMode={setDisplayMode}\n displayMode={displayMode}\n onPinnedChatsToggle={handlePinningChatsToggle}\n />\n </ChatbotHeader>\n <Divider />\n <ChatbotConversationHistoryNav\n drawerPanelContentProps={{\n isResizable: isFullscreenMode,\n hasNoBorder: !isFullscreenMode,\n style: isFullscreenMode ? undefined : { zIndex: 1300 },\n }}\n reverseButtonOrder\n displayMode={ChatbotDisplayMode.embedded}\n onDrawerToggle={onChatHistoryDrawerToggle}\n title=\"\"\n navTitleIcon={null}\n isDrawerOpen={isChatHistoryDrawerOpen}\n drawerCloseButtonProps={{\n 'aria-label': t('aria.closeDrawerPanel'),\n }}\n setIsDrawerOpen={setIsChatHistoryDrawerOpen}\n activeItemId={conversationId}\n onSelectActiveItem={onSelectActiveItem}\n conversations={filterConversations(filterValue)}\n onNewChat={newChatCreated ? undefined : onNewChat}\n newChatButtonText={t('button.newChat')}\n newChatButtonProps={{\n icon: <PlusIcon />,\n }}\n handleTextInputChange={handleFilter}\n searchInputPlaceholder={t('chatbox.search.placeholder')}\n searchInputAriaLabel={t('aria.search.placeholder')}\n searchInputProps={{\n value: filterValue,\n onClear: () => {\n setFilterValue('');\n },\n }}\n searchActionEnd={sortDropdown}\n noResultsState={\n filterValue &&\n Object.keys(filterConversations(filterValue)).length === 0\n ? {\n bodyText: t('chatbox.emptyState.noResults.body'),\n titleText: t('chatbox.emptyState.noResults.title'),\n icon: SearchIcon,\n }\n : undefined\n }\n drawerContent={\n <FileDropZone\n onFileDrop={(e, data) => handleAttach(data, e)}\n displayMode={ChatbotDisplayMode.embedded}\n infoText={t('chatbox.fileUpload.infoText')}\n allowedFileTypes={supportedFileTypes}\n onAttachRejected={onAttachRejected}\n >\n {showAlert && uploadError.message && (\n <div className={classes.errorContainer}>\n <ChatbotAlert\n component=\"h4\"\n title={t('chatbox.fileUpload.failed')}\n variant={uploadError.type ?? 'danger'}\n isInline\n onClose={() => setUploadError({ message: null })}\n >\n {uploadError.message}\n </ChatbotAlert>\n </div>\n )}\n\n <ChatbotContent>\n <LightspeedChatBox\n userName={userName}\n messages={messages}\n profileLoading={profileLoading}\n announcement={announcement}\n ref={scrollToBottomRef}\n welcomePrompts={welcomePrompts}\n conversationId={conversationId}\n isStreaming={isSendButtonDisabled}\n topicRestrictionEnabled={topicRestrictionEnabled}\n displayMode={displayMode}\n />\n </ChatbotContent>\n <ChatbotFooter className={classes.footer}>\n <FilePreview />\n <MessageBar\n onSendMessage={sendMessage}\n isSendButtonDisabled={isSendButtonDisabled}\n hasAttachButton\n handleAttach={handleAttach}\n hasMicrophoneButton\n value={draftMessage}\n onChange={handleDraftMessage}\n buttonProps={{\n attach: {\n inputTestId: 'attachment-input',\n tooltipContent: t('tooltip.attach'),\n },\n microphone: {\n tooltipContent: {\n active: t('tooltip.microphone.active'),\n inactive: t('tooltip.microphone.inactive'),\n },\n },\n send: {\n tooltipContent: t('tooltip.send'),\n },\n }}\n allowedFileTypes={supportedFileTypes}\n onAttachRejected={onAttachRejected}\n placeholder={t('chatbox.message.placeholder')}\n />\n <ChatbotFootnote\n {...getFootnoteProps(classes.footerPopover, t)}\n />\n </ChatbotFooter>\n </FileDropZone>\n }\n />\n </Chatbot>\n <Attachment />\n </>\n );\n};\n"],"names":[],"mappings":"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"}