@buerokratt-ria/common-gui-components 0.0.47 → 0.0.49

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 CHANGED
@@ -4,6 +4,14 @@ All changes to this project will be documented in this file.
4
4
 
5
5
  ## Template [MajorVersion.MediterraneanVersion.MinorVersion] - DD-MM-YYYY
6
6
 
7
+ ## [0.0.49] - 29.04.2026
8
+
9
+ - Fixed chat history XLSX download to use the S3 signed URL returned by the API instead of the previous base64 payload.
10
+
11
+ ## [0.0.48] - 23.04.2026
12
+
13
+ - Added chats preserve feature
14
+
7
15
  ## [0.0.47] - 21.04.2026
8
16
 
9
17
  - Added total chat counter under chat history
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buerokratt-ria/common-gui-components",
3
- "version": "0.0.47",
3
+ "version": "0.0.49",
4
4
  "description": "Common GUI components and pre defined templates.",
5
5
  "main": "index.ts",
6
6
  "author": "ExiRai",
package/services/file.ts CHANGED
@@ -1,42 +1,11 @@
1
- /**
2
- * Converts a base64 string to a Uint8Array (browser-compatible alternative to Buffer)
3
- */
4
- const base64ToUint8Array = (base64: string): Uint8Array<ArrayBuffer> => {
5
- const binaryString = atob(base64);
6
- const bytes = new Uint8Array(binaryString.length);
7
- for (let i = 0; i < binaryString.length; i++) {
8
- bytes[i] = binaryString.charCodeAt(i);
9
- }
10
- return bytes;
11
- };
12
-
13
- export const saveFile = async (base64String: string, fileName: `${string}.${string}`, type: string) => {
14
- const bytes = base64ToUint8Array(base64String);
15
- const blob = new Blob([bytes], {
16
- type: type,
17
- });
18
-
19
- const extension = fileName.split('.').pop();
20
-
21
- if (window.showSaveFilePicker) {
22
- const handle = await window.showSaveFilePicker({
23
- suggestedName: fileName,
24
- types: [
25
- {
26
- description: extension!.toUpperCase() + ' file',
27
- accept: { [type]: [`.${extension}` as `.${string}`] },
28
- },
29
- ],
30
- });
31
- const writable = await handle.createWritable();
32
- await writable.write(blob);
33
- writable.close();
34
- } else {
35
- const url = window.URL.createObjectURL(blob);
36
- const a = document.createElement('a');
37
- a.href = url;
38
- a.download = fileName;
39
- a.click();
40
- window.URL.revokeObjectURL(url);
41
- }
1
+ export const saveFile = async (
2
+ fileUrl: string,
3
+ fileName: `${string}.${string}`,
4
+ ) => {
5
+ const a = document.createElement('a');
6
+ a.href = fileUrl;
7
+ a.download = fileName;
8
+ document.body.appendChild(a);
9
+ a.click();
10
+ a.remove();
42
11
  };
@@ -391,6 +391,8 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
391
391
  columns.splice(5, 0, {label: t('global.test'), value: 'istest'});
392
392
  }
393
393
 
394
+ columns.splice(5, 0, {label: t('global.preserve'), value: 'isPreserve'});
395
+
394
396
  return columns;
395
397
  }, [t, showEmail, testMessageEnabled])
396
398
 
@@ -508,6 +510,31 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
508
510
  },
509
511
  });
510
512
 
513
+ const chatPreserveChangeMutation = useMutation({
514
+ mutationFn: (data: {
515
+ chatId: string | number;
516
+ isPreserve: boolean;
517
+ }) => apiDev.post('chats/mark-preserve', data),
518
+ onSuccess: (res, {chatId, isPreserve}) => {
519
+ const updatedChatList = filteredEndedChatsList.map((chat) =>
520
+ chat.id === chatId ? {...chat, isPreserve: isPreserve} : chat
521
+ );
522
+ filterChatsList(updatedChatList);
523
+ toast?.open({
524
+ type: 'success',
525
+ title: t('global.notification'),
526
+ message: t('toast.success.updateSuccess'),
527
+ });
528
+ },
529
+ onError: (error: AxiosError) => {
530
+ toast?.open({
531
+ type: 'error',
532
+ title: t('global.notificationError'),
533
+ message: error.message,
534
+ });
535
+ },
536
+ });
537
+
511
538
  const columnHelper = createColumnHelper<ChatType>();
512
539
 
513
540
  const copyValueToClipboard = async (value: string) => {
@@ -590,6 +617,19 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
590
617
  }
591
618
  };
592
619
 
620
+ const updateChatPreserve = function (chatId: string, isPreserve: boolean) {
621
+ setFilteredEndedChatsList((prevChats) =>
622
+ prevChats.map((chat) => (chat.id === chatId ? ({ ...chat, isPreserve: isPreserve } as ChatType) : chat))
623
+ );
624
+
625
+ if (selectedChat?.id === chatId) {
626
+ setSelectedChat({
627
+ ...selectedChat,
628
+ isPreserve: isPreserve,
629
+ } as ChatType);
630
+ }
631
+ };
632
+
593
633
  const markConversationAsTest = (props: any) => {
594
634
  const chatId = props.row.original.id;
595
635
  const newIsTestValue = props.getValue();
@@ -613,6 +653,29 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
613
653
  );
614
654
  };
615
655
 
656
+ const markConversationAsPreserve = (props: any) => {
657
+ const chatId = props.row.original.id;
658
+ const newIsPreserveValue = props.getValue();
659
+ return (
660
+ <FormCheckbox
661
+ checked={newIsPreserveValue}
662
+ label={""}
663
+ hideLabel
664
+ emptyItem={true}
665
+ name="active"
666
+ item={{
667
+ label: "",
668
+ value: "active",
669
+ }}
670
+ onChange={(e) => {
671
+ const isPreserve = e.target.checked;
672
+ updateChatPreserve(chatId, isPreserve);
673
+ chatPreserveChangeMutation.mutate({ chatId, isPreserve });
674
+ }}
675
+ />
676
+ );
677
+ };
678
+
616
679
  const detailsView = (props: any) => (
617
680
  <Button
618
681
  appearance="text"
@@ -765,6 +828,12 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
765
828
  }));
766
829
  }
767
830
 
831
+ columns.splice(4, 0, columnHelper.accessor('isPreserve', {
832
+ id: 'isPreserve',
833
+ header: t('global.preserve') ?? '',
834
+ cell: markConversationAsPreserve
835
+ }));
836
+
768
837
  return columns;
769
838
  }, [t, showEmail, testMessageEnabled])
770
839
 
@@ -810,6 +879,8 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
810
879
  return 'id';
811
880
  case 'istest':
812
881
  return t('global.test') ?? ''
882
+ case 'isPreserve':
883
+ return t('global.preserve') ?? ''
813
884
  default:
814
885
  return '';
815
886
  }
@@ -953,15 +1024,15 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
953
1024
  customerSupportIds: passedCustomerSupportIds,
954
1025
  });
955
1026
 
1027
+ const downloadData = response.data.data ?? response.data;
956
1028
 
957
1029
  await saveFile(
958
- response.data.base64String,
1030
+ downloadData.url,
959
1031
  'history.xlsx',
960
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
961
1032
  );
962
1033
 
963
1034
  } catch (error) {
964
- console.error('Error getting CSV file:', error);
1035
+ console.error('Error downloading chat history file:', error);
965
1036
  } finally {
966
1037
  setLoading(false);
967
1038
  }
package/types/chat.ts CHANGED
@@ -88,6 +88,7 @@ export interface Chat {
88
88
  nps?: number;
89
89
  userDisplayName?: string;
90
90
  istest?: boolean;
91
+ isPreserve?: boolean;
91
92
  isFiveRatingScale?: string;
92
93
  allCsa?: string[];
93
94
  totalPages?: number;