SetSources.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import { useState } from "react";
  2. import PlusIcon from "../../public/icons/plus.svg";
  3. import CrossIcon from "../../public/icons/cross.svg";
  4. import YoutubeIcon from "../../public/icons/youtube.svg";
  5. import PDFIcon from "../../public/icons/pdf.svg";
  6. import WebIcon from "../../public/icons/web.svg";
  7. import DocIcon from "../../public/icons/doc.svg";
  8. import SitemapIcon from "../../public/icons/sitemap.svg";
  9. import TextIcon from "../../public/icons/text.svg";
  10. export default function SetSources({
  11. setChats,
  12. embedding_model,
  13. setSelectChat,
  14. }) {
  15. const [sourceName, setSourceName] = useState("");
  16. const [sourceValue, setSourceValue] = useState("");
  17. const [isDropdownOpen, setIsDropdownOpen] = useState(false);
  18. const [isLoading, setIsLoading] = useState(false);
  19. const dataTypes = {
  20. youtube_video: "YouTube Video",
  21. pdf_file: "PDF File",
  22. web_page: "Web Page",
  23. doc_file: "Doc File",
  24. sitemap: "Sitemap",
  25. text: "Text",
  26. };
  27. const dataIcons = {
  28. youtube_video: <YoutubeIcon className="w-5 h-5 mr-3" />,
  29. pdf_file: <PDFIcon className="w-5 h-5 mr-3" />,
  30. web_page: <WebIcon className="w-5 h-5 mr-3" />,
  31. doc_file: <DocIcon className="w-5 h-5 mr-3" />,
  32. sitemap: <SitemapIcon className="w-5 h-5 mr-3" />,
  33. text: <TextIcon className="w-5 h-5 mr-3" />,
  34. };
  35. const handleDropdownClose = () => {
  36. setIsDropdownOpen(false);
  37. setSourceName("");
  38. setSelectChat(true);
  39. };
  40. const handleDropdownSelect = (dataType) => {
  41. setSourceName(dataType);
  42. setSourceValue("");
  43. setIsDropdownOpen(false);
  44. setSelectChat(false);
  45. };
  46. const handleAddDataSource = async (e) => {
  47. e.preventDefault();
  48. setIsLoading(true);
  49. const addDataSourceEntry = {
  50. sender: "B",
  51. message: `Adding the following ${dataTypes[sourceName]}: ${sourceValue}`,
  52. };
  53. setChats((prevChats) => [...prevChats, addDataSourceEntry]);
  54. let name = sourceName;
  55. let value = sourceValue;
  56. setSourceValue("");
  57. const response = await fetch("/api/add_sources", {
  58. method: "POST",
  59. body: JSON.stringify({
  60. embedding_model,
  61. name,
  62. value,
  63. }),
  64. headers: {
  65. "Content-Type": "application/json",
  66. },
  67. });
  68. if (response.ok) {
  69. const successEntry = {
  70. sender: "B",
  71. message: `Successfully added ${dataTypes[sourceName]}!`,
  72. };
  73. setChats((prevChats) => [...prevChats, successEntry]);
  74. } else {
  75. const errorEntry = {
  76. sender: "B",
  77. message: `Failed to add ${dataTypes[sourceName]}. Please try again.`,
  78. };
  79. setChats((prevChats) => [...prevChats, errorEntry]);
  80. }
  81. setSourceName("");
  82. setIsLoading(false);
  83. setSelectChat(true);
  84. };
  85. return (
  86. <>
  87. <div className="w-fit">
  88. <button
  89. type="button"
  90. onClick={() => setIsDropdownOpen(!isDropdownOpen)}
  91. className="w-fit p-2.5 rounded-xl text-white bg-black hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300"
  92. >
  93. <PlusIcon className="w-6 h-6" />
  94. </button>
  95. {isDropdownOpen && (
  96. <div className="absolute left-0 bottom-full bg-white border border-gray-300 rounded-lg shadow-lg mb-2">
  97. <ul className="py-1">
  98. <li
  99. className="block px-4 py-2 text-sm text-black cursor-pointer hover:bg-gray-200"
  100. onClick={handleDropdownClose}
  101. >
  102. <span className="flex items-center text-red-600">
  103. <CrossIcon className="w-5 h-5 mr-3" />
  104. Close
  105. </span>
  106. </li>
  107. {Object.entries(dataTypes).map(([key, value]) => (
  108. <li
  109. key={key}
  110. className="block px-4 py-2 text-sm text-black cursor-pointer hover:bg-gray-200"
  111. onClick={() => handleDropdownSelect(key)}
  112. >
  113. <span className="flex items-center">
  114. {dataIcons[key]}
  115. {value}
  116. </span>
  117. </li>
  118. ))}
  119. </ul>
  120. </div>
  121. )}
  122. </div>
  123. {sourceName && (
  124. <form
  125. onSubmit={handleAddDataSource}
  126. className="w-full flex flex-col sm:flex-row gap-y-2 gap-x-2 items-center"
  127. >
  128. <div className="w-full">
  129. <input
  130. type="text"
  131. placeholder="Enter URL, Data or File path here..."
  132. className="text-sm w-full border-2 border-black rounded-xl focus:outline-none focus:border-blue-800 sm:pl-4 h-11"
  133. required
  134. value={sourceValue}
  135. onChange={(e) => setSourceValue(e.target.value)}
  136. />
  137. </div>
  138. <div className="w-full sm:w-fit">
  139. <button
  140. type="submit"
  141. disabled={isLoading}
  142. className={`${
  143. isLoading ? "opacity-60" : ""
  144. } w-full bg-black hover:bg-blue-800 rounded-xl text-lg text-white px-6 h-11`}
  145. >
  146. Send
  147. </button>
  148. </div>
  149. </form>
  150. )}
  151. </>
  152. );
  153. }