diff --git a/GanjooRazor/Pages/SemanticSearch.cshtml b/GanjooRazor/Pages/SemanticSearch.cshtml deleted file mode 100644 index c024a72d..00000000 --- a/GanjooRazor/Pages/SemanticSearch.cshtml +++ /dev/null @@ -1,147 +0,0 @@ -@page -@model GanjooRazor.Pages.SemanticSearchModel -@{ - Layout = "_Layout"; - ViewData["Title"] = "جست‌وجوی معنایی"; -} -@section Head { - -} - -
- -

جست‌وجوی معنایی

-

- به‌جای جست‌وجوی کلمه‌به‌کلمه، توصیف کنید دنبال چه مضمونی هستید — مثلاً «شعری دربارهٔ بی‌وفایی دنیا». -
- اگر نام یک سخنور یا یک بخش/کتاب خاص را هم در جمله بیاورید (مثلاً «در کدام شعر حافظ» یا «در کدام بخش شاهنامه»)، جست‌وجو فقط در همان محدوده انجام می‌شود. -

- -
- - -
- - - -
- -
- -@section Scripts { - -} diff --git a/GanjooRazor/Pages/SemanticSearch.cshtml.cs b/GanjooRazor/Pages/SemanticSearch.cshtml.cs deleted file mode 100644 index 38cc4e3e..00000000 --- a/GanjooRazor/Pages/SemanticSearch.cshtml.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using System; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; - -namespace GanjooRazor.Pages -{ - /// - /// "find a poem about..." chatbox. Deliberately calls APIRoot.SemanticSearchUrl, NOT - /// APIRoot.Url/InternetUrl — see the comment on that property in APIRoot.cs. Currently a - /// physically separate domain/app pool (ganjgah.ir) from api.ganjoor.net, so a problem with - /// this one feature can't affect the main site or its API, a precaution proven necessary by - /// an actual production incident during development, not a hypothetical one. - /// - [IgnoreAntiforgeryToken(Order = 1001)] - public class SemanticSearchModel : PageModel - { - public void OnGet() - { - } - - /// - /// proxies the query to the semantic search API and passes its JSON straight back to the - /// page's own JS — no local re-modeling of the response, so there's no risk of a shape - /// mismatch between the two sides silently dropping a field - /// - public async Task OnPostSearchAsync(string query) - { - if (string.IsNullOrWhiteSpace(query)) - { - return BadRequest("لطفاً عبارتی برای جست‌وجو وارد کنید."); - } - - using (HttpClient client = new HttpClient()) - { - client.Timeout = TimeSpan.FromSeconds(30); // query-time ONNX inference is not instant - give it real room, but not unbounded - - var requestBody = "{\"query\":" + System.Text.Json.JsonSerializer.Serialize(query) + ",\"topK\":10}"; - var content = new StringContent(requestBody, Encoding.UTF8, "application/json"); - - HttpResponseMessage response; - try - { - response = await client.PostAsync($"{APIRoot.SemanticSearchUrl}/api/ganjoor/search/semantic", content); - } - catch (Exception) - { - // a network-level failure reaching the isolated semantic-search domain - - // exactly the kind of failure this domain-level isolation is meant to - // contain to just this feature, so report it plainly rather than let an - // unhandled exception propagate - return StatusCode((int)HttpStatusCode.ServiceUnavailable, - "در حال حاضر جست‌وجوی معنایی در دسترس نیست. لطفاً کمی بعد دوباره امتحان کنید."); - } - - string responseBody = await response.Content.ReadAsStringAsync(); - if (!response.IsSuccessStatusCode) - { - return StatusCode((int)response.StatusCode, responseBody); - } - - return Content(responseBody, "application/json"); - } - } - } -} diff --git a/GanjooRazor/Pages/Shared/_Layout.cshtml b/GanjooRazor/Pages/Shared/_Layout.cshtml index d7bc7256..8adeeea1 100644 --- a/GanjooRazor/Pages/Shared/_Layout.cshtml +++ b/GanjooRazor/Pages/Shared/_Layout.cshtml @@ -49,6 +49,8 @@ + + @await RenderSectionAsync("Scripts", required: false) diff --git a/GanjooRazor/Pages/Shared/_SemanticSearchWidgetPartial.cshtml b/GanjooRazor/Pages/Shared/_SemanticSearchWidgetPartial.cshtml new file mode 100644 index 00000000..028dd658 --- /dev/null +++ b/GanjooRazor/Pages/Shared/_SemanticSearchWidgetPartial.cshtml @@ -0,0 +1,315 @@ +@{ + // Global floating "find a poem about..." widget — included once from _Layout.cshtml, so it + // appears on every page that opts into that shared layout, same guarantee the theme toggle + // has. Self-contained CSS (scoped under #ss-widget* ids) rather than added to p8.css + // deliberately - avoids needing a cache-busting version bump on that large shared file for + // every iteration of a still-settling feature, at the cost of not being in the "official" + // stylesheet yet. Reuses real site CSS variables (--card-inner, --border-gold, --brand, + // --text-muted, --bg-page) throughout for visual consistency regardless. + // + // Calls APIRoot.SemanticSearchUrl DIRECTLY from browser JS (not a server-side proxy) - see + // the comment on SemanticSearchUrl in APIRoot.cs for why it's a separate, currently-isolated + // domain. CORS is already wide open on that backend (Startup.cs: SetIsOriginAllowed(_ => + // true)), confirmed before choosing this approach rather than guessed. +} + + + + + + + + + + + + +