FolderTitle.svelte 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <script lang="ts">
  2. import { getContext } from 'svelte';
  3. const i18n = getContext('i18n');
  4. import DOMPurify from 'dompurify';
  5. import fileSaver from 'file-saver';
  6. const { saveAs } = fileSaver;
  7. import { toast } from 'svelte-sonner';
  8. import { selectedFolder } from '$lib/stores';
  9. import { deleteFolderById, updateFolderById } from '$lib/apis/folders';
  10. import { getChatsByFolderId } from '$lib/apis/chats';
  11. import FolderModal from '$lib/components/layout/Sidebar/Folders/FolderModal.svelte';
  12. import Folder from '$lib/components/icons/Folder.svelte';
  13. import XMark from '$lib/components/icons/XMark.svelte';
  14. import FolderMenu from '$lib/components/layout/Sidebar/Folders/FolderMenu.svelte';
  15. import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte';
  16. import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
  17. export let folder = null;
  18. export let onUpdate: Function = (folderId) => {};
  19. export let onDelete: Function = (folderId) => {};
  20. let showFolderModal = false;
  21. let showDeleteConfirm = false;
  22. const updateHandler = async ({ name, data }) => {
  23. if (name === '') {
  24. toast.error($i18n.t('Folder name cannot be empty.'));
  25. return;
  26. }
  27. const currentName = folder.name;
  28. name = name.trim();
  29. folder.name = name;
  30. const res = await updateFolderById(localStorage.token, folder.id, {
  31. name,
  32. ...(data ? { data } : {})
  33. }).catch((error) => {
  34. toast.error(`${error}`);
  35. folder.name = currentName;
  36. return null;
  37. });
  38. if (res) {
  39. folder.name = name;
  40. if (data) {
  41. folder.data = data;
  42. }
  43. toast.success($i18n.t('Folder updated successfully'));
  44. selectedFolder.set(folder);
  45. onUpdate(folder);
  46. }
  47. };
  48. const deleteHandler = async () => {
  49. const res = await deleteFolderById(localStorage.token, folder.id).catch((error) => {
  50. toast.error(`${error}`);
  51. return null;
  52. });
  53. if (res) {
  54. toast.success($i18n.t('Folder deleted successfully'));
  55. onDelete(folder);
  56. }
  57. };
  58. const exportHandler = async () => {
  59. const chats = await getChatsByFolderId(localStorage.token, folder.id).catch((error) => {
  60. toast.error(`${error}`);
  61. return null;
  62. });
  63. if (!chats) {
  64. return;
  65. }
  66. const blob = new Blob([JSON.stringify(chats)], {
  67. type: 'application/json'
  68. });
  69. saveAs(blob, `folder-${folder.name}-export-${Date.now()}.json`);
  70. };
  71. </script>
  72. {#if folder}
  73. <FolderModal bind:show={showFolderModal} edit={true} {folder} onSubmit={updateHandler} />
  74. <DeleteConfirmDialog
  75. bind:show={showDeleteConfirm}
  76. title={$i18n.t('Delete folder?')}
  77. on:confirm={() => {
  78. deleteHandler();
  79. }}
  80. >
  81. <div class=" text-sm text-gray-700 dark:text-gray-300 flex-1 line-clamp-3">
  82. {@html DOMPurify.sanitize(
  83. $i18n.t(
  84. 'This will delete <strong>{{NAME}}</strong> and <strong>all its contents</strong>.',
  85. {
  86. NAME: folder.name
  87. }
  88. )
  89. )}
  90. </div>
  91. </DeleteConfirmDialog>
  92. <div class="mb-3 px-6 @md:max-w-3xl justify-between w-full flex relative group items-center">
  93. <div class="text-center flex gap-3.5 items-center">
  94. <div class=" rounded-full bg-gray-50 dark:bg-gray-800 p-3 w-fit">
  95. <Folder className="size-4.5" strokeWidth="2" />
  96. </div>
  97. <div class="text-3xl">
  98. {folder.name}
  99. </div>
  100. </div>
  101. <div class="flex items-center">
  102. <FolderMenu
  103. align="end"
  104. onEdit={() => {
  105. showFolderModal = true;
  106. }}
  107. onDelete={() => {
  108. showDeleteConfirm = true;
  109. }}
  110. onExport={() => {
  111. exportHandler();
  112. }}
  113. >
  114. <button class="p-1.5 dark:hover:bg-gray-850 rounded-full touch-auto" on:click={(e) => {}}>
  115. <EllipsisHorizontal className="size-4" strokeWidth="2.5" />
  116. </button>
  117. </FolderMenu>
  118. </div>
  119. </div>
  120. {/if}