3emibrahim/debugging-testing2
0
1<!DOCTYPE html>2<html lang="en">3 <head>4 <meta charset="UTF-8" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />6 <title>AIToolkit - Text Generator</title>7 <style>8 :root {9 --primary: #4f46e5;10 --primary-dark: #4338ca;11 --secondary: #10b981;12 --accent: #f97316;13 --light: #f3f4f6;14 --dark: #1f2937;15 --gray: #9ca3af;16 }17 18 * {19 margin: 0;20 padding: 0;21 box-sizing: border-box;22 font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;23 }24 25 body {26 background-color: #f9fafb;27 color: var(--dark);28 line-height: 1.6;29 }30 31 header {32 background-color: white;33 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);34 padding: 1rem 2rem;35 position: sticky;36 top: 0;37 z-index: 10;38 }39 40 nav {41 display: flex;42 justify-content: space-between;43 align-items: center;44 max-width: 1200px;45 margin: 0 auto;46 }47 48 .logo {49 font-size: 1.5rem;50 font-weight: 700;51 color: var(--primary);52 display: flex;53 align-items: center;54 gap: 0.5rem;55 }56 57 .nav-links {58 display: flex;59 gap: 2rem;60 }61 62 .nav-links a {63 text-decoration: none;64 color: var(--dark);65 font-weight: 500;66 transition: color 0.2s;67 }68 69 .nav-links a:hover {70 color: var(--primary);71 }72 73 main {74 max-width: 1200px;75 margin: 0 auto;76 padding: 2rem;77 }78 79 .page-title {80 text-align: center;81 margin-bottom: 3rem;82 }83 84 .page-title h1 {85 font-size: 2.5rem;86 color: var(--dark);87 margin-bottom: 1rem;88 }89 90 .page-title p {91 font-size: 1.2rem;92 color: var(--gray);93 max-width: 700px;94 margin: 0 auto;95 }96 97 .text-generator-container {98 background-color: white;99 border-radius: 0.75rem;100 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);101 padding: 2rem;102 margin-bottom: 2rem;103 display: flex;104 gap: 2rem;105 max-width: 1800px;106 width: 100%;107 margin-left: auto;108 margin-right: auto;109 min-height: 200px; /* Increased height */110 }111 112 .conversation-section {113 flex: 1.5;114 display: flex;115 flex-direction: column;116 }117 118 .media-section {119 flex: 0.9;120 border-left: 1px solid #e5e7eb;121 padding-left: 2rem;122 }123 124 .conversation-history {125 flex: 1;126 overflow-y: auto;127 background-color: var(--light);128 border-radius: 0.5rem;129 padding: 1rem;130 margin-bottom: 1rem;131 max-height: 380px; /* Increased height */132 }133 134 .message {135 margin-bottom: 1rem;136 padding: 0.75rem;137 border-radius: 0.5rem;138 word-wrap: break-word;139 overflow-wrap: break-word;140 width: auto;141 display: inline-block;142 max-width: 80%;143 }144 145 .user-message {146 background-color: #e2e8f0;147 text-align: right;148 float: right;149 clear: both;150 }151 152 .ai-message {153 background-color: #dbeafe;154 float: left;155 clear: both;156 }157 158 .input-area {159 display: flex;160 gap: 1rem;161 }162 163 .input-area textarea {164 flex: 1;165 min-height: 60px;166 resize: none;167 padding: 0.75rem;168 border: 1px solid #e5e7eb;169 border-radius: 0.5rem;170 font-size: 1rem;171 }172 173 .send-btn {174 background-color: var(--primary);175 color: white;176 border: none;177 border-radius: 0.5rem;178 padding: 0 1rem;179 font-size: 1rem;180 font-weight: 500;181 cursor: pointer;182 transition: background-color 0.2s;183 }184 185 .send-btn:hover {186 background-color: var(--primary-dark);187 }188 189 .media-controls {190 display: flex;191 flex-direction: column;192 gap: 1rem;193 margin-bottom: 1.5rem;194 }195 196 .media-upload {197 display: flex;198 gap: 1rem;199 align-items: center;200 }201 202 .upload-btn {203 background-color: var(--secondary);204 color: white;205 border: none;206 border-radius: 0.5rem;207 padding: 0.75rem 1rem;208 font-size: 1rem;209 font-weight: 500;210 cursor: pointer;211 transition: background-color 0.2s;212 flex-shrink: 0; /* Prevent button from shrinking */213 }214 215 .upload-btn:hover {216 background-color: #0ca678;217 }218 219 .file-name-container {220 overflow: hidden;221 text-overflow: ellipsis;222 white-space: nowrap;223 max-width: 200px; /* Limit the width of the filename */224 }225 226 .media-preview {227 background-color: var(--light);228 border-radius: 0.5rem;229 min-height: 380px; /* Increased height */230 display: flex;231 flex-direction: column; /* Change to column to allow for size info below */232 align-items: center;233 justify-content: center;234 overflow: hidden;235 position: relative; /* For positioning the size info */236 padding: 1rem;237 }238 239 .media-preview img,240 .media-preview video {241 max-width: 100%;242 max-height: 300px; /* Limit the height of media */243 object-fit: contain;244 }245 246 .media-info {247 margin-top: 0.5rem;248 font-size: 0.875rem;249 color: var(--gray);250 text-align: center;251 background-color: rgba(255, 255, 255, 0.8);252 padding: 0.25rem 0.5rem;253 border-radius: 0.25rem;254 width: 100%;255 }256 257 .options-panel {258 margin-bottom: 1rem;259 }260 261 .options-panel h3 {262 margin-bottom: 0.75rem;263 }264 265 .input-row {266 display: flex;267 gap: 1rem;268 margin-bottom: 1rem;269 }270 271 .input-row > div {272 flex: 1;273 }274 275 .input-section label {276 display: block;277 margin-bottom: 0.5rem;278 font-weight: 500;279 }280 281 .input-section select {282 width: 100%;283 padding: 0.75rem;284 border: 1px solid #e5e7eb;285 border-radius: 0.5rem;286 font-size: 1rem;287 }288 289 .hidden {290 display: none;291 }292 293 @media (max-width: 968px) {294 .text-generator-container {295 flex-direction: column;296 }297 298 .media-section {299 border-left: none;300 border-top: 1px solid #e5e7eb;301 padding-left: 0;302 padding-top: 2rem;303 }304 }305 306 @media (max-width: 768px) {307 .input-row {308 flex-direction: column;309 gap: 1rem;310 }311 312 .nav-links {313 display: none;314 }315 }316 317 .copyright {318 text-align: center;319 padding: 1.5rem 0;320 background-color: #374151;321 color: var(--gray);322 margin-top: 2rem;323 font-size: 0.9rem;324 border-top: 1px solid #374151;325 }326 327 .copyright p {328 max-width: 1200px;329 margin: 0 auto;330 }331 </style>332 </head>333 <body>334 <header>335 <nav>336 <div class="logo">337 <span>AIToolkit</span>338 </div>339 <div class="nav-links">340 <a href="/">Home</a>341 <a href="/features">Features</a>342 <a href="/contact">Contact us</a>343 <a href="/about">About</a>344 </div>345 </nav>346 </header>347 348 <main>349 <div class="text-generator-container">350 <!-- Left column: Conversation interface -->351 <div class="conversation-section">352 <div class="options-panel">353 <h3>Content Options</h3>354 <div class="input-row">355 <div class="input-section"></div>356 <div class="input-section"></div>357 </div>358 </div>359 360 <div class="conversation-history" id="conversation-history">361 <div class="message ai-message">362 Hello! Ask me anything about that?363 </div>364 </div>365 366 <div class="input-area">367 <textarea368 id="user-input"369 placeholder="Type your message here..."370 ></textarea>371 <button class="send-btn" onclick="sendMessage()">Send</button>372 </div>373 </div>374 375 <!-- Right column: Media display -->376 <div class="media-section">377 <h2>Media</h2>378 <div class="media-controls">379 <div class="media-upload">380 <input381 type="file"382 id="media-file"383 class="hidden"384 accept="image/*,.pdf,.txt,.pptx,.xlsx"385 onchange="handleFileUpload()"386 />387 <button388 class="upload-btn"389 onclick="document.getElementById('media-file').click()"390 >391 Upload Media392 </button>393 <div class="file-name-container">394 <span id="file-name">No file chosen</span>395 </div>396 </div>397 </div>398 <div class="media-preview" id="media-preview">399 <p>Your uploaded media will appear here...</p>400 </div>401 </div>402 </div>403 </main>404 405 <footer class="copyright">406 <p>© 2025 AIToolkit. All rights reserved.</p>407 </footer>408 409 <script>410 async function sendMessage() {411 const userInput = document.getElementById("user-input").value;412 const conversationHistory = document.getElementById(413 "conversation-history"414 );415 const fileInput = document.getElementById("media-file");416 417 if (!userInput.trim()) {418 alert("Please enter a message.");419 return;420 }421 422 // Add user message to the conversation423 const userMessageDiv = document.createElement("div");424 userMessageDiv.className = "message user-message";425 userMessageDiv.textContent = userInput;426 conversationHistory.appendChild(userMessageDiv);427 428 // Clear input field429 document.getElementById("user-input").value = "";430 431 // Add loading message432 const loadingMessage = document.createElement("div");433 loadingMessage.className = "message ai-message";434 loadingMessage.textContent = "Processing your request...";435 conversationHistory.appendChild(loadingMessage);436 437 try {438 // Create form data (works for both file and text-only cases)439 const formData = new FormData();440 formData.append("user_prompt", userInput);441 442 if (fileInput.files.length > 0) {443 formData.append("file", fileInput.files[0]);444 } else {445 formData.append("file", new File([""], "empty.txt"));446 }447 448 const response = await fetch("/process/", {449 method: "POST",450 body: formData,451 });452 453 // Remove loading message454 conversationHistory.removeChild(loadingMessage);455 456 if (!response.ok) {457 throw new Error("Failed to fetch response from the server.");458 }459 460 const data = await response.json();461 const aiMessageDiv = document.createElement("div");462 aiMessageDiv.className = "message ai-message";463 464 // Format the response with HTML465 const formattedResponse = formatAIResponse(data.response);466 aiMessageDiv.innerHTML = formattedResponse;467 468 conversationHistory.appendChild(aiMessageDiv);469 } catch (error) {470 console.error("Error:", error);471 conversationHistory.removeChild(loadingMessage);472 473 const errorMessageDiv = document.createElement("div");474 errorMessageDiv.className = "message ai-message error-message";475 errorMessageDiv.textContent = "Error: " + error.message;476 conversationHistory.appendChild(errorMessageDiv);477 }478 479 // Scroll to the latest message480 conversationHistory.scrollTop = conversationHistory.scrollHeight;481 }482 483 // Helper function to format the AI response484 function formatAIResponse(text) {485 // Escape HTML first for security486 let formatted = text.replace(/</g, "<").replace(/>/g, ">");487 488 // Convert line breaks to <br>489 formatted = formatted.replace(/\n/g, "<br>");490 491 // Better handling for bullet points with proper list nesting492 // Look for bullet patterns (• or * or -) followed by space493 formatted = formatted.replace(494 /(?:<br>)?(•|\*|\-) (.*?)(?:<br>|$)/g,495 "<ul>$2</ul>"496 );497 498 // If we found any list items, wrap them in a <ul>499 if (formatted.includes("<ul>")) {500 // Group consecutive list items into a single <ul>501 formatted = formatted.replace(502 /(<ul>.*?<\/ul>)(?:<br>)?/g,503 "<ul>$1</ul>"504 );505 506 // Clean up any adjacent <ul> tags that might have been created507 formatted = formatted.replace(/<\/ul><ul>/g, "");508 }509 510 // Improved pattern for bold headings like "**Setting:**"511 formatted = formatted.replace(512 /\*\*(.*?)\*\*:/g,513 "<strong>$1:</strong>"514 );515 516 return formatted;517 }518 519 function handleFileUpload() {520 const fileInput = document.getElementById("media-file");521 const preview = document.getElementById("media-preview");522 const fileName = document.getElementById("file-name");523 524 if (fileInput.files && fileInput.files[0]) {525 const file = fileInput.files[0];526 const fileType = file.type;527 const fileExtension = file.name.split('.').pop().toLowerCase();528 529 // Truncate long filenames530 if (file.name.length > 20) {531 const extension = file.name.split(".").pop();532 const nameWithoutExt = file.name.substring(0, file.name.lastIndexOf("."));533 fileName.textContent =534 nameWithoutExt.substring(0, 10) +535 "..." +536 nameWithoutExt.substring(nameWithoutExt.length - 5) +537 "." +538 extension;539 } else {540 fileName.textContent = file.name;541 }542 543 const reader = new FileReader();544 545 reader.onload = function (e) {546 preview.innerHTML = "";547 548 // Handle different file types549 if (fileType.startsWith("image/")) {550 const img = document.createElement("img");551 img.src = e.target.result;552 preview.appendChild(img);553 554 img.onload = function () {555 const infoDiv = document.createElement("div");556 infoDiv.className = "media-info";557 infoDiv.textContent = `Size: ${img.naturalWidth}×${img.naturalHeight}px | File size: ${formatFileSize(file.size)}`;558 preview.appendChild(infoDiv);559 };560 } else if (fileType.startsWith("video/")) {561 const video = document.createElement("video");562 video.src = e.target.result;563 video.controls = true;564 preview.appendChild(video);565 566 video.onloadedmetadata = function () {567 const infoDiv = document.createElement("div");568 infoDiv.className = "media-info";569 infoDiv.textContent = `Size: ${video.videoWidth}×${video.videoHeight}px | Duration: ${formatTime(video.duration)} | File size: ${formatFileSize(file.size)}`;570 preview.appendChild(infoDiv);571 };572 } 573 // Handle document files (PDF, PPTX, XLSX, TXT)574 else if (575 fileType === "application/pdf" || 576 fileExtension === "pdf" ||577 fileExtension === "txt" || 578 fileType === "text/plain" ||579 fileExtension === "pptx" || 580 fileType === "application/vnd.openxmlformats-officedocument.presentationml.presentation" ||581 fileExtension === "xlsx" || 582 fileType === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"583 ) {584 const fileIcon = document.createElement("div");585 fileIcon.style.fontSize = "3rem";586 fileIcon.style.marginBottom = "1rem";587 588 // Set appropriate icon based on file type589 if (fileType === "application/pdf" || fileExtension === "pdf") {590 fileIcon.textContent = "📄";591 fileIcon.title = "PDF Document";592 } else if (fileExtension === "pptx" || fileType.includes("presentation")) {593 fileIcon.textContent = "📊";594 fileIcon.title = "PowerPoint Presentation";595 } else if (fileExtension === "xlsx" || fileType.includes("spreadsheet")) {596 fileIcon.textContent = "📈";597 fileIcon.title = "Excel Spreadsheet";598 } else if (fileExtension === "txt" || fileType === "text/plain") {599 fileIcon.textContent = "📝";600 fileIcon.title = "Text File";601 602 // For text files, show a preview of the content603 const textPreview = document.createElement("pre");604 textPreview.style.maxHeight = "200px";605 textPreview.style.overflow = "auto";606 textPreview.style.backgroundColor = "#f5f5f5";607 textPreview.style.padding = "0.5rem";608 textPreview.style.borderRadius = "0.25rem";609 textPreview.style.fontSize = "0.875rem";610 textPreview.style.width = "100%";611 textPreview.style.whiteSpace = "pre-wrap";612 textPreview.style.wordBreak = "break-word";613 614 // Use FileReader to read text content615 const textReader = new FileReader();616 textReader.onload = function(e) {617 // Limit text preview to first 1000 characters618 const content = e.target.result.substring(0, 1000);619 textPreview.textContent = content + (content.length < e.target.result.length ? "..." : "");620 };621 textReader.readAsText(file);622 623 preview.appendChild(textPreview);624 }625 626 preview.insertBefore(fileIcon, preview.firstChild);627 628 const docInfo = document.createElement("div");629 docInfo.className = "media-info";630 docInfo.textContent = `File: ${file.name} | Type: ${fileExtension.toUpperCase()} | Size: ${formatFileSize(file.size)}`;631 preview.appendChild(docInfo);632 } else {633 // Unsupported file type634 const unsupportedMsg = document.createElement("p");635 unsupportedMsg.textContent = "Unsupported file type";636 preview.appendChild(unsupportedMsg);637 638 const fileInfo = document.createElement("div");639 fileInfo.className = "media-info";640 fileInfo.textContent = `File: ${file.name} | Size: ${formatFileSize(file.size)}`;641 preview.appendChild(fileInfo);642 }643 };644 645 // Use appropriate reader method based on file type646 if (fileExtension === "txt" || fileType === "text/plain") {647 // Text files are handled within the above logic648 reader.readAsDataURL(file);649 } else {650 reader.readAsDataURL(file);651 }652 }653 }654 655 // Helper function to format file size656 function formatFileSize(bytes) {657 if (bytes < 1024) return bytes + " bytes";658 else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + " KB";659 else return (bytes / 1048576).toFixed(1) + " MB";660 }661 662 // Helper function to format video duration663 function formatTime(seconds) {664 const min = Math.floor(seconds / 60);665 const sec = Math.floor(seconds % 60);666 return `${min}:${sec < 10 ? "0" + sec : sec}`;667 }668 669 // Add event listener for Enter key in the textarea670 document671 .getElementById("user-input")672 .addEventListener("keydown", function (event) {673 if (event.key === "Enter" && !event.shiftKey) {674 event.preventDefault();675 sendMessage();676 }677 });678 </script>679 </body>680</html>681 