Skip to content

Commit 31832cf

Browse files
committed
Refactor js code
1 parent 418c608 commit 31832cf

File tree

1 file changed

+111
-108
lines changed
  • src/KernelMemory.Ecommerce.Sample.Api/wwwroot

1 file changed

+111
-108
lines changed

src/KernelMemory.Ecommerce.Sample.Api/wwwroot/index.html

+111-108
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<!DOCTYPE html>
22
<html lang="en">
3+
34
<head>
45
<meta charset="UTF-8">
56
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -148,17 +149,17 @@
148149
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
149150
}
150151

151-
.json-output {
152-
background-color: #f9f9f9;
153-
border: 1px solid #ddd;
154-
padding: 10px;
155-
font-family: monospace;
156-
white-space: pre-wrap;
157-
max-height: 300px;
152+
.json-output {
153+
background-color: #f9f9f9;
154+
border: 1px solid #ddd;
155+
padding: 10px;
156+
font-family: monospace;
157+
white-space: pre-wrap;
158+
max-height: 300px;
158159
max-width: 100%;
159-
overflow-y: auto;
160-
margin-top: 20px;
161-
}
160+
overflow-y: auto;
161+
margin-top: 20px;
162+
}
162163

163164
.user-hints h3 {
164165
margin-top: 0;
@@ -171,6 +172,7 @@
171172
}
172173
</style>
173174
</head>
175+
174176
<body>
175177

176178
<header class="header">
@@ -182,8 +184,14 @@ <h1 class="title">Product Ingestion & Search</h1>
182184
<h3>How to Use:</h3>
183185
<ul>
184186
<li>Upload a CSV file for product ingestion. After uploading, the product IDs will be displayed.</li>
185-
<li>Use the Vector Search section to search for products by category or search query. Click the category buttons or enter a custom query.</li>
186-
<li>Use RAG (Retrieval Augmented Generation Search) to get smarter, context-driven results by blending search data with generated insights.</li>
187+
<li>
188+
Use the Vector Search section to search for products by category or search query. Click the category
189+
buttons or enter a custom query.
190+
</li>
191+
<li>
192+
Use RAG (Retrieval Augmented Generation Search) to get smarter, context-driven results by blending
193+
search data with generated insights.
194+
</li>
187195
</ul>
188196
</section>
189197

@@ -460,105 +468,100 @@ <h3>${product.name}</h3>
460468
}
461469
}
462470

463-
async function ragStreamingSearch(category) {
464-
const query = category || document.getElementById('ragStreamingSearchQuery').value;
465-
const ragStreamingSearchButton = document.getElementById('ragStreamingSearchButton');
466-
const resultContainer = document.getElementById('ragStreamingSearchResult');
471+
async function ragStreamingSearch(category) {
472+
const query = category || document.getElementById('ragStreamingSearchQuery').value;
473+
const searchButton = document.getElementById('ragStreamingSearchButton');
474+
const resultContainer = document.getElementById('ragStreamingSearchResult');
467475
const jsonOutputContainer = document.getElementById('ragStreamingJsonOutput');
468476

469-
resultContainer.innerHTML = '';
470-
jsonOutputContainer.textContent = '';
471-
472-
lockSectionButtons('ragStreamingSearchSection');
473-
ragStreamingSearchButton.classList.add('is-loading');
474-
475-
const startTime = Date.now();
476-
let jsonOutput = '';
477-
let parsedResults = [];
478-
let accumulatedData = '';
479-
480-
try {
481-
const response = await fetch(`/api/products/search/rag/streaming?searchQuery=${encodeURIComponent(query)}`);
482-
const reader = response.body.getReader();
483-
const decoder = new TextDecoder("utf-8");
484-
485-
while (true) {
486-
const { done, value } = await reader.read();
487-
if (done) break;
488-
const chunk = decoder.decode(value, { stream: true });
489-
accumulatedData += chunk;
490-
jsonOutput += chunk;
491-
jsonOutputContainer.textContent = jsonOutput;
492-
493-
// Attempt to parse the JSON data
494-
try {
495-
// Check if the accumulated data ends with a valid JSON structure
496-
const lastBraceIndex = accumulatedData.lastIndexOf('}');
497-
const lastBracketIndex = accumulatedData.lastIndexOf(']');
498-
const endIndex = Math.max(lastBraceIndex, lastBracketIndex);
499-
500-
if (endIndex !== -1) {
501-
const jsonString = accumulatedData.substring(0, endIndex + 1);
502-
const parsedChunk = JSON.parse(jsonString);
503-
parsedResults.push(parsedChunk);
504-
accumulatedData = accumulatedData.substring(endIndex + 1); // Remove the parsed part
505-
}
506-
} catch (e) {
507-
// Ignore parsing errors
508-
console.error('Error parsing chunk:', e);
509-
}
510-
}
511-
512-
const endTime = Date.now();
513-
const duration = (endTime - startTime) / 1000; // Convert to seconds
514-
515-
if (parsedResults.length === 0) {
516-
resultContainer.innerHTML = '<div class="notification is-danger"><strong>No results found</strong></div>';
517-
} else {
518-
const products = parsedResults[0];
519-
const transformedResult = {
520-
noResult: false,
521-
minRelevance: 0.8,
522-
relevantSourcesCount: products.length,
523-
products: products.map(product => ({
524-
id: product.Id,
525-
name: product.Name,
526-
description: product.Description,
527-
price: product.Price,
528-
priceCurrency: product.PriceCurrency,
529-
supplyAbility: product.SupplyAbility,
530-
minimumOrder: product.MinimumOrder
531-
}))
532-
};
533-
534-
resultContainer.innerHTML = `
535-
<div>
536-
<p><strong>Min Relevance:</strong> ${transformedResult.minRelevance}</p>
537-
<p><strong>Relevant Sources Count:</strong> ${transformedResult.relevantSourcesCount}</p>
538-
<p><strong>Request Duration:</strong> ${duration.toFixed(2)} seconds</p>
539-
</div>
540-
<div class="products-container">
541-
${transformedResult.products.map(product => `
542-
<div class="product-card">
543-
<h3>${product.name}</h3>
544-
<p class="description">${product.description}</p>
545-
<p class="price">${product.price} ${product.priceCurrency}</p>
546-
<p>Supply Ability: ${product.supplyAbility}</p>
547-
<p>Minimum Order: ${product.minimumOrder}</p>
548-
</div>
549-
`).join('')}
477+
resetUI(resultContainer, jsonOutputContainer, searchButton);
478+
lockSectionButtons('ragStreamingSearchSection');
479+
480+
const startTime = Date.now();
481+
let result = '';
482+
483+
try {
484+
const response = await fetch(`/api/products/search/rag/streaming?searchQuery=${encodeURIComponent(query)}`);
485+
const reader = response.body.getReader();
486+
const decoder = new TextDecoder("utf-8");
487+
488+
result = await processStream(reader, decoder, jsonOutputContainer, result);
489+
490+
displayResults(result, resultContainer, startTime);
491+
} catch (error) {
492+
console.error(error);
493+
resultContainer.innerHTML = '<div class="notification is-danger"><strong>Error occurred while searching.</strong></div>';
494+
} finally {
495+
searchButton.classList.remove('is-loading');
496+
unlockSectionButtons('ragStreamingSearchSection');
497+
}
498+
}
499+
500+
function resetUI(resultContainer, jsonOutputContainer, searchButton) {
501+
resultContainer.innerHTML = '';
502+
jsonOutputContainer.textContent = '';
503+
searchButton.classList.add('is-loading');
504+
}
505+
506+
async function processStream(reader, decoder, jsonOutputContainer) {
507+
let streamContent = '';
508+
509+
while (true) {
510+
const { done, value } = await reader.read();
511+
if (done) break;
512+
513+
const chunk = decoder.decode(value, { stream: true });
514+
jsonOutputContainer.textContent += chunk;
515+
streamContent += chunk;
516+
}
517+
518+
return streamContent;
519+
}
520+
521+
function displayResults(result, resultContainer, startTime) {
522+
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
523+
524+
if (result.length === 0) {
525+
resultContainer.innerHTML = '<div class="notification is-danger"><strong>No results found</strong></div>';
526+
return;
527+
}
528+
529+
const products = JSON.parse(result);
530+
const transformedResult = {
531+
noResult: false,
532+
minRelevance: 0.8,
533+
relevantSourcesCount: products.length,
534+
products: products.map(product => ({
535+
id: product.Id,
536+
name: product.Name,
537+
description: product.Description,
538+
price: product.Price,
539+
priceCurrency: product.PriceCurrency,
540+
supplyAbility: product.SupplyAbility,
541+
minimumOrder: product.MinimumOrder
542+
}))
543+
};
544+
545+
resultContainer.innerHTML = `
546+
<div>
547+
<p><strong>Min Relevance:</strong> ${transformedResult.minRelevance}</p>
548+
<p><strong>Relevant Sources Count:</strong> ${transformedResult.relevantSourcesCount}</p>
549+
<p><strong>Request Duration:</strong> ${duration} seconds</p>
550+
</div>
551+
<div class="products-container">
552+
${transformedResult.products.map(product => `
553+
<div class="product-card">
554+
<h3>${product.name}</h3>
555+
<p class="description">${product.description}</p>
556+
<p class="price">${product.price} ${product.priceCurrency}</p>
557+
<p>Supply Ability: ${product.supplyAbility}</p>
558+
<p>Minimum Order: ${product.minimumOrder}</p>
550559
</div>
551-
`;
552-
}
553-
} catch (error) {
554-
console.error('Error occurred while searching:', error);
555-
resultContainer.innerHTML = '<div class="notification is-danger"><strong>Error occurred while searching.</strong></div>';
556-
} finally {
557-
ragStreamingSearchButton.classList.remove('is-loading');
558-
unlockSectionButtons('ragStreamingSearchSection');
559-
}
560-
}
560+
`).join('')}
561+
</div>`;
562+
}
561563

562564
</script>
563565
</body>
564-
</html>
566+
567+
</html>

0 commit comments

Comments
 (0)