Added CriticalCSS, defered CSS and JS, fixed heading order, fixed front-end querycache url, added response compression and caching
This commit is contained in:
@@ -18,9 +18,10 @@
|
||||
}
|
||||
|
||||
<div class="container py-4">
|
||||
<h3 class="mb-4">
|
||||
<h1 class="visually-hidden">Searchdomains</h1>
|
||||
<p class="mb-4 fs-3">
|
||||
@(hasName ? T["Hi, {0}!", name] : T["Hi!"])
|
||||
</h3>
|
||||
</p>
|
||||
|
||||
<div class="row g-4">
|
||||
|
||||
@@ -28,7 +29,7 @@
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">@T["Embedding Cache"]</h5>
|
||||
<h2 class="card-title fs-5">@T["Embedding Cache"]</h2>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>@T["Size"]</span>
|
||||
@@ -62,7 +63,7 @@
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">@T["Health Checks"]</h5>
|
||||
<h2 class="card-title fs-5">@T["Health Checks"]</h2>
|
||||
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
@@ -88,7 +89,7 @@
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">@T["Searchdomains"]</h5>
|
||||
<h2 class="card-title fs-5">@T["Searchdomains"]</h2>
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>@T["Count"]</span>
|
||||
@@ -111,7 +112,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script defer>
|
||||
<script>
|
||||
var searchdomains = null;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
@@ -138,41 +139,55 @@
|
||||
let healthchecksServer = document.getElementById("healthchecksServer");
|
||||
let healthchecksAiProvider = document.getElementById("healthchecksAiProvider");
|
||||
|
||||
listSearchdomains().then(async result => {
|
||||
searchdomains = result.Searchdomains;
|
||||
hideThrobber(searchdomainCount);
|
||||
searchdomainCount.textContent = searchdomains.length;
|
||||
(async() => {
|
||||
listSearchdomains().then(async result => {
|
||||
searchdomains = result.Searchdomains;
|
||||
hideThrobber(searchdomainCount);
|
||||
searchdomainCount.textContent = searchdomains.length;
|
||||
|
||||
var entityCount = 0;
|
||||
var totalUtilization = 0;
|
||||
for (var name in searchdomains){
|
||||
let entityListResult = await listEntities(searchdomains[name]);
|
||||
let entities = entityListResult.Results;
|
||||
entityCount += entities.length;
|
||||
let querycacheUtilizationResult = await getQuerycacheUtilization(searchdomains[name]);
|
||||
let utilization = querycacheUtilizationResult.QueryCacheSizeBytes;
|
||||
totalUtilization += utilization;
|
||||
}
|
||||
hideThrobber(searchdomainEntityCount);
|
||||
hideThrobber(totalQuerycacheUtilization);
|
||||
searchdomainEntityCount.textContent = entityCount;
|
||||
totalQuerycacheUtilization.textContent = NumberOfBytesAsHumanReadable(totalUtilization);
|
||||
});
|
||||
getEmbeddingcacheUtilization().then(result => {
|
||||
let utilization = result.SizeInBytes;
|
||||
let maxElementCount = result.MaxElementCount;
|
||||
let elementCount = result.ElementCount;
|
||||
let embeddingCount = result.EmbeddingsCount;
|
||||
hideThrobber(embeddingcacheSize);
|
||||
embeddingcacheSize.textContent = NumberOfBytesAsHumanReadable(utilization);
|
||||
hideThrobber(embeddingcacheElementCount);
|
||||
embeddingcacheElementCount.textContent = `${elementCount.toLocaleString()} / ${maxElementCount.toLocaleString()}`;
|
||||
hideThrobber(embeddingcacheEmbeddingCount);
|
||||
embeddingcacheEmbeddingCount.textContent = embeddingCount;
|
||||
embeddingcacheElementCountProgressBar.style.width = `${elementCount / maxElementCount * 100}%`;
|
||||
});
|
||||
getHealthCheckStatusAndApply(healthchecksServer, "/healthz/Database");
|
||||
getHealthCheckStatusAndApply(healthchecksAiProvider, "/healthz/AIProvider");
|
||||
const perDomainPromises = searchdomains.map(async domain => {
|
||||
const [entityListResult, querycacheUtilizationResult] = await Promise.all([
|
||||
listEntities(domain),
|
||||
getQuerycacheUtilization(domain)
|
||||
]);
|
||||
|
||||
return {
|
||||
entityCount: entityListResult.Results.length,
|
||||
utilization: querycacheUtilizationResult.QueryCacheSizeBytes
|
||||
};
|
||||
});
|
||||
|
||||
const results = await Promise.all(perDomainPromises);
|
||||
|
||||
let entityCount = 0;
|
||||
let totalUtilization = 0;
|
||||
|
||||
for (const r of results) {
|
||||
entityCount += r.entityCount;
|
||||
totalUtilization += r.utilization;
|
||||
}
|
||||
|
||||
hideThrobber(searchdomainEntityCount);
|
||||
hideThrobber(totalQuerycacheUtilization);
|
||||
searchdomainEntityCount.textContent = entityCount;
|
||||
totalQuerycacheUtilization.textContent = NumberOfBytesAsHumanReadable(totalUtilization);
|
||||
});
|
||||
getEmbeddingcacheUtilization().then(result => {
|
||||
let utilization = result.SizeInBytes;
|
||||
let maxElementCount = result.MaxElementCount;
|
||||
let elementCount = result.ElementCount;
|
||||
let embeddingCount = result.EmbeddingsCount;
|
||||
hideThrobber(embeddingcacheSize);
|
||||
embeddingcacheSize.textContent = NumberOfBytesAsHumanReadable(utilization);
|
||||
hideThrobber(embeddingcacheElementCount);
|
||||
embeddingcacheElementCount.textContent = `${elementCount.toLocaleString()} / ${maxElementCount.toLocaleString()}`;
|
||||
hideThrobber(embeddingcacheEmbeddingCount);
|
||||
embeddingcacheEmbeddingCount.textContent = embeddingCount;
|
||||
embeddingcacheElementCountProgressBar.style.width = `${elementCount / maxElementCount * 100}%`;
|
||||
});
|
||||
getHealthCheckStatusAndApply(healthchecksServer, "/healthz/Database");
|
||||
getHealthCheckStatusAndApply(healthchecksAiProvider, "/healthz/AIProvider");
|
||||
})();
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}
|
||||
|
||||
<div class="container-fluid mt-4">
|
||||
<h1 class="visually-hidden">embeddingsearch</h1>
|
||||
<h1 class="visually-hidden">Searchdomains</h1>
|
||||
<div class="row">
|
||||
|
||||
<!-- Sidebar -->
|
||||
@@ -804,7 +804,7 @@
|
||||
.getElementById('cacheClear')
|
||||
.addEventListener('click', () => {
|
||||
const domainKey = getSelectedDomainKey();
|
||||
fetch(`/Searchdomain/SearchCache/Clear?searchdomain=${encodeURIComponent(domains[domainKey])}`, {
|
||||
fetch(`/Searchdomain/QueryCache/Clear?searchdomain=${encodeURIComponent(domains[domainKey])}`, {
|
||||
method: 'POST'
|
||||
}).then(response => {
|
||||
if (response.ok) {
|
||||
@@ -1031,7 +1031,7 @@
|
||||
}
|
||||
|
||||
function getSearchdomainCacheUtilization(domainKey) {
|
||||
return fetch(`/Searchdomain/SearchCache/Size?searchdomain=${encodeURIComponent(domains[domainKey])}`)
|
||||
return fetch(`/Searchdomain/QueryCache/Size?searchdomain=${encodeURIComponent(domains[domainKey])}`)
|
||||
.then(r => r.json());
|
||||
}
|
||||
|
||||
@@ -1106,10 +1106,10 @@
|
||||
}
|
||||
});
|
||||
cacheUtilizationPromise.then(cacheUtilization => {
|
||||
if (cacheUtilization != null && cacheUtilization.SearchCacheSizeBytes != null)
|
||||
if (cacheUtilization != null && cacheUtilization.QueryCacheSizeBytes != null)
|
||||
{
|
||||
document.querySelector('#cacheUtilization').innerText =
|
||||
`${NumberOfBytesAsHumanReadable(cacheUtilization.SearchCacheSizeBytes)}`;
|
||||
`${NumberOfBytesAsHumanReadable(cacheUtilization.QueryCacheSizeBytes)}`;
|
||||
} else {
|
||||
showToast("@T["Unable to fetch searchdomain cache utilization"]", "danger");
|
||||
console.error('Failed to fetch searchdomain cache utilization');
|
||||
|
||||
@@ -1,15 +1,39 @@
|
||||
@using Server.Services
|
||||
@using System.Globalization
|
||||
@using Server.Services
|
||||
@inject LocalizationService T
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="@CultureInfo.CurrentUICulture.TwoLetterISOLanguageName">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="Embeddingsearch server" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - embeddingsearch</title>
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
@if (!Context.Request.Query.ContainsKey("renderRaw"))
|
||||
{
|
||||
<link rel="preload" href="~/lib/bootstrap/dist/css/bootstrap.min.css" as="style"/>
|
||||
<link rel="stylesheet" fetchpriority="high"
|
||||
href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
||||
media="print"
|
||||
onload="this.media='all'">
|
||||
}
|
||||
<style>
|
||||
@Html.Raw(File.ReadAllText(System.IO.Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "css", "site.css")))
|
||||
</style>
|
||||
@if (!Context.Request.Query.ContainsKey("noCriticalCSS"))
|
||||
{
|
||||
<style>
|
||||
@if (Context.Request.Path.Value is not null)
|
||||
{
|
||||
string path = System.IO.Path.Combine("CriticalCSS", Context.Request.Path.Value.Trim('/').Replace("/", ".") + ".css");
|
||||
Console.WriteLine(path);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
@Html.Raw(File.ReadAllText(path));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}
|
||||
<script>
|
||||
window.appTranslations = {
|
||||
closeAlert: '@T["Close alert"]'
|
||||
@@ -61,9 +85,9 @@
|
||||
© 2025 - embeddingsearch
|
||||
</div>
|
||||
</footer>
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
<script src="~/lib/jquery/dist/jquery.min.js" defer></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js" defer></script>
|
||||
<script src="~/js/site.js" asp-append-version="true" defer></script>
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user