@buerokratt-ria/common-gui-components 0.0.57 → 0.0.59

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 (26) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/package.json +1 -1
  3. package/templates/history-page/src/History.scss +33 -3
  4. package/templates/history-page/src/components/ChatMetadataPanel/ChatMetadataPanel.scss +18 -0
  5. package/templates/history-page/src/components/ChatMetadataPanel/index.tsx +206 -0
  6. package/templates/history-page/src/components/ChatMetadataPanelItem/index.tsx +17 -0
  7. package/templates/history-page/src/components/FilterTag/FilterTag.scss +42 -0
  8. package/templates/history-page/src/components/FilterTag/index.tsx +16 -0
  9. package/templates/history-page/src/components/HeaderCombobox/index.tsx +66 -0
  10. package/templates/history-page/src/components/QualitySettings/QualitySettings.scss +19 -0
  11. package/templates/history-page/src/components/QualitySettings/index.tsx +115 -0
  12. package/templates/history-page/src/components/SelectedFilterTags/SelectedFilterTags.scss +36 -0
  13. package/templates/history-page/src/components/SelectedFilterTags/index.tsx +224 -0
  14. package/templates/history-page/src/components/index.tsx +6 -0
  15. package/templates/history-page/src/index.tsx +943 -209
  16. package/templates/history-page/src/types/index.ts +17 -0
  17. package/translations/en/common.json +22 -2
  18. package/translations/et/common.json +22 -2
  19. package/types/chat.ts +3 -0
  20. package/ui-components/FormElements/FormCombobox/FormCombobox.scss +252 -0
  21. package/ui-components/FormElements/FormCombobox/index.tsx +334 -0
  22. package/ui-components/FormElements/index.tsx +1 -0
  23. package/ui-components/HistoricalChat/ChatMessage.tsx +24 -9
  24. package/ui-components/HistoricalChat/index.tsx +16 -6
  25. package/ui-components/Icon/index.tsx +1 -0
  26. package/ui-components/index.tsx +2 -0
@@ -21,3 +21,4 @@ export {
21
21
  FormDatepicker,
22
22
  SwitchBox,
23
23
  };
24
+ export * from './FormCombobox';
@@ -1,6 +1,6 @@
1
1
  import React, { FC, useMemo } from "react";
2
2
  import { format } from "date-fns";
3
- import { Message } from "../../types/message";
3
+ import { Message, MessageButton } from "../../types/message";
4
4
  import Markdownify from "../Chat/Markdownify";
5
5
  import { parseButtons, parseOptions } from "../../utils/parse-utils";
6
6
  import ButtonMessage from "../ButtonMessage";
@@ -12,14 +12,25 @@ type ChatMessageProps = {
12
12
  message: Message;
13
13
  onMessageClick?: (message: Message) => void;
14
14
  toastContext: ToastContextType | null;
15
+ previousButtons?: MessageButton[];
15
16
  };
16
17
 
17
- const ChatMessage: FC<ChatMessageProps> = ({ message, onMessageClick, toastContext }) => {
18
+ const isButtonPayload = (content: string) =>
19
+ content.startsWith("#service,") || content.startsWith("#common_service,");
20
+
21
+ const ChatMessage: FC<ChatMessageProps> = ({ message, onMessageClick, toastContext, previousButtons }) => {
18
22
  const buttons = useMemo(() => parseButtons(message), [message.buttons]);
19
23
  const options = useMemo(() => parseOptions(message), [message.options]);
20
24
  const { t } = useTranslation();
21
25
  const toast = toastContext;
22
26
 
27
+ const selectedButton = useMemo(() => {
28
+ const content = message.content ?? "";
29
+ if (!isButtonPayload(content)) return null;
30
+ const match = previousButtons?.find((b) => b.payload === content);
31
+ return match ?? { title: content, payload: content };
32
+ }, [message.content, previousButtons]);
33
+
23
34
  const handleContextMenu = (event: React.MouseEvent<HTMLButtonElement>) => {
24
35
  event.preventDefault();
25
36
  const content = message.content ?? "";
@@ -44,13 +55,17 @@ const ChatMessage: FC<ChatMessageProps> = ({ message, onMessageClick, toastConte
44
55
  return (
45
56
  <>
46
57
  <div className="historical-chat__message">
47
- <button
48
- className="historical-chat__message-text"
49
- onClick={onMessageClick ? () => onMessageClick(message) : undefined}
50
- onContextMenu={handleContextMenu}
51
- >
52
- <Markdownify message={message.content ?? ""} sanitizeLinks={message.authorRole === "end-user"} />
53
- </button>
58
+ {selectedButton ? (
59
+ <ButtonMessage buttons={[selectedButton]} />
60
+ ) : (
61
+ <button
62
+ className="historical-chat__message-text"
63
+ onClick={onMessageClick ? () => onMessageClick(message) : undefined}
64
+ onContextMenu={handleContextMenu}
65
+ >
66
+ <Markdownify message={message.content ?? ""} sanitizeLinks={message.authorRole === "end-user"} />
67
+ </button>
68
+ )}
54
69
  <time dateTime={message.created} className="historical-chat__message-date">
55
70
  {format(new Date(message.created ?? ""), "HH:mm:ss")}
56
71
  </time>
@@ -13,6 +13,8 @@ import { apiDev } from "../../services/api";
13
13
  import ChatEvent from "../../ui-components/ChatEvent";
14
14
  import { ToastContextType } from "../../context";
15
15
  import { AUTHOR_ROLES } from "../../utils/constants";
16
+ import { parseButtons } from "../../utils/parse-utils";
17
+ import { MessageButton } from "../../types/message";
16
18
 
17
19
  type ChatProps = {
18
20
  chat: ChatType;
@@ -57,7 +59,7 @@ const HistoricalChat: FC<ChatProps> = ({
57
59
  onMessageClick,
58
60
  }) => {
59
61
  const { t } = useTranslation();
60
- const chatRef = useRef<HTMLDivElement>(null);
62
+ const groupWrapperRef = useRef<HTMLDivElement>(null);
61
63
  const [messageGroups, setMessageGroups] = useState<GroupedMessage[]>([]);
62
64
  const [editingComment, setEditingComment] = useState<string | null>(null);
63
65
  const [messagesList, setMessagesList] = useState<Message[]>([]);
@@ -184,14 +186,22 @@ const HistoricalChat: FC<ChatProps> = ({
184
186
  }, [messagesList, endUserFullName]);
185
187
 
186
188
  useEffect(() => {
187
- if (!chatRef.current || !messageGroups) return;
188
- chatRef.current.scrollIntoView({ block: "end", inline: "end" });
189
+ if (!groupWrapperRef.current || !messageGroups) return;
190
+ groupWrapperRef.current.scrollTop = groupWrapperRef.current.scrollHeight;
189
191
  }, [messageGroups]);
190
192
 
191
193
  const isEvent = (group: GroupedMessage) => {
192
194
  return (group.type === "event" || group.name.trim() === "" || group.messages.some((message) => message.event && message.event !== CHAT_EVENTS.GREETING));
193
195
  };
194
196
 
197
+ const getPreviousButtons = (messageId: string | undefined): MessageButton[] => {
198
+ const idx = messagesList.findIndex((m) => m.id === messageId);
199
+ for (let i = idx - 1; i >= 0; i--) {
200
+ if (messagesList[i].buttons) return parseButtons(messagesList[i]);
201
+ }
202
+ return [];
203
+ };
204
+
195
205
  const eventGroup = (group: GroupedMessage) => {
196
206
  return group.messages.map((message) => {
197
207
  if (message.event) {
@@ -232,6 +242,7 @@ const HistoricalChat: FC<ChatProps> = ({
232
242
  message={message}
233
243
  key={`${message.id ?? ""}`}
234
244
  toastContext={toastContext}
245
+ previousButtons={getPreviousButtons(message.id)}
235
246
  onMessageClick={(message) => {
236
247
  onMessageClick?.(message);
237
248
  }}
@@ -247,7 +258,7 @@ const HistoricalChat: FC<ChatProps> = ({
247
258
  <div className="historical-chat">
248
259
  <div className="historical-chat__body">
249
260
  {header_link && <div className={"header-link"}>{header_link}</div>}
250
- <div className="historical-chat__group-wrapper">
261
+ <div className="historical-chat__group-wrapper" ref={groupWrapperRef}>
251
262
  {messageGroups?.map((group, index) => (
252
263
  <div
253
264
  className={clsx(["historical-chat__group", `historical-chat__group--${group.type}`])}
@@ -282,6 +293,7 @@ const HistoricalChat: FC<ChatProps> = ({
282
293
  message={message}
283
294
  key={`${message.id ?? ""}-${i}`}
284
295
  toastContext={toastContext}
296
+ previousButtons={getPreviousButtons(message.id)}
285
297
  onMessageClick={(message) => {
286
298
  onMessageClick?.(message);
287
299
  }}
@@ -292,7 +304,6 @@ const HistoricalChat: FC<ChatProps> = ({
292
304
  )}
293
305
  </div>
294
306
  ))}
295
- <div id="anchor" ref={chatRef}></div>
296
307
  </div>
297
308
  {lastMessage && (
298
309
  <div className="historical-chat__toolbar">
@@ -350,7 +361,6 @@ const HistoricalChat: FC<ChatProps> = ({
350
361
  </div>
351
362
  )}
352
363
  </div>
353
- <div id="anchor" ref={chatRef}></div>
354
364
  </div>
355
365
  );
356
366
  };
@@ -14,6 +14,7 @@ const Icon = forwardRef<HTMLSpanElement, IconProps>(({ label, icon, size = 'smal
14
14
  const iconClasses = clsx(
15
15
  'icon',
16
16
  `icon--${size}`,
17
+ rest.className,
17
18
  );
18
19
 
19
20
  return (
@@ -12,6 +12,7 @@ import {
12
12
  FormTextarea,
13
13
  Switch,
14
14
  SwitchBox,
15
+ FormCombobox,
15
16
  } from './FormElements';
16
17
  import DataTable from './DataTable';
17
18
  import Tooltip from './Tooltip';
@@ -52,4 +53,5 @@ export {
52
53
  Toast,
53
54
  Label,
54
55
  ClearFiltersButton,
56
+ FormCombobox,
55
57
  };