#445 simple search

This commit is contained in:
Hamid Reza Mohammadi 2024-08-25 10:45:45 +03:30
parent 08c7e2cef2
commit 30cf219e8d
5 changed files with 186 additions and 9 deletions

View File

@ -2,13 +2,13 @@
@model IndexModel
@if(!string.IsNullOrEmpty(Model.LastError))
@if (!string.IsNullOrEmpty(Model.LastError))
{
@Html.Raw(Model.LastError)
return;
}
@if(Model.Poets == null)
@if (Model.Poets == null)
{
<p>
Хато дар дарёфт феҳристи суханварон
@ -17,6 +17,58 @@
}
<div class="text-center">
@if (Model.IsSearchPage)
{
@if (Model.Poems == null)
{
<div class="poem">
<h2>شعری با مشخصات مورد نظر شما پیدا نشد.</h2>
<p>
<strong>توصیه‌هایی برای دستیابی به نتیجهٔ مطلوبتر در جستجو:</strong>
</p>
<p>
الف) <strong>به جای جستجوی متن کامل یک بیت بهتر است حروف کلیدی آن را وارد کنید.</strong> از آنجا که اشعار به صورتهای مختلف در نسخه‌های متفاوت نقل شده‌اند ممکن است چیزی که شما در ذهن دارید با چیزی که در پایگاه ما ثبت شده متفاوت باشد. به عنوان نمونه مصرع «کشتی شکستگانیم ای باد شرطه برخیز» از حافظ در بعضی از نسخه‌ها به صورت «کشتی نشستگانیم ای باد شرطه برخیز» ضبط شده و شما با تایپ صورت صورت دوم آن را در گنجور نخواهید یافت. بهتر است برای یافتن این شعر کلماتی مانند کشتی و شرطه را جستجو کنیم.
</p>
<p>
ب) کلماتی را که ممکن است به صورت جدا یا سر هم نوشته شوند در گام اول به صورت جدا امتحان کنید (<strong>می شود</strong> و نه <del>میشود</del> یا <del>می‌شود</del>).
</p>
<p>
ج) در صورتی که نام سخنور را می‌دانید بهتر است از طریق لیست بازشوی جلوی جعبهٔ جستجو نام او را انتخاب کنید. این توصیه برای زمانی مناسب است که جستجوی عبارت مورد نظر شما باعث می‌شود آثار سخنورانی که مورد نظر شما نیستند در صدر نتایج قرار گیرد و به این وسیله شما می‌خواهید به فهرست محدودتری از نتایج دست پیدا کنید.
</p>
<p>
د) در صورتی که با فنون اولیهٔ جستجو آشنا نیستید یا <strong>معمولاً جستجوهایتان به نتیجهٔ مطلوب نمی‌رسد</strong> بد نیست نگاهی به <a href="http://hrmoh.ir/1385/04/18/howto-search-better/" title="توصیه هایی برای جستجوی بهتر در اینترنت">این نوشته</a> بیندازید.
</p>
</div>
}
else
for (int poemIndex = 0; poemIndex < Model.Poems.Count; poemIndex++)
{
var poem = Model.Poems[poemIndex];
<div class="sitem">
<h2>
<a href="@poem.FullUrl">@poem.FullTitle</a>
</h2>
<div class="spacer">&nbsp;</div>
<div class="sit">
@Html.Raw(poem.PlainText)
</div>
<div class="spacer">&nbsp;</div>
</div>
}
<div class="spacer">&nbsp;</div>
}
else
@if (Model.IsHomePage)
{
@foreach (var poet in Model.Poets)

View File

@ -4,10 +4,12 @@ using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using RMuseum.Models.Ganjoor.ViewModels;
using NAudio.Gui;
using RMuseum.Models.Ganjoor;
using System.Net;
using System.Reflection;
using DNTPersianUtils.Core;
using System.Drawing;
using RSecurityBackend.Models.Generic;
using System.Text.RegularExpressions;
namespace TajikGanjoor.Pages
@ -15,6 +17,9 @@ namespace TajikGanjoor.Pages
public class IndexModel : PageModel
{
public bool IsHomePage { get; set; }
public bool IsSearchPage { get; set; }
public string Query { get; set; }
public List<GanjoorPoetViewModel>? Poets { get; set; }
public bool IsPoetPage { get; set; }
public bool IsCatPage { get; set; }
@ -25,6 +30,8 @@ namespace TajikGanjoor.Pages
public string PreviousUrl { get; set; }
public string PreviousTitle { get; set; }
public string BreadCrumpUrls { get; set; }
public List<GanjoorPoemCompleteViewModel> Poems { get; set; }
public async Task<IActionResult> OnGetAsync()
{
if (bool.Parse(Configuration["MaintenanceMode"] ?? false.ToString()))
@ -37,8 +44,106 @@ namespace TajikGanjoor.Pages
{
return Page();
}
IsSearchPage = !string.IsNullOrEmpty(Request.Query["s"]);
IsHomePage = !IsSearchPage && Request.Path == "/";
if(IsSearchPage)
{
Query = Request.Query["s"].ToString().Trim();
int pageNumber = 1;
if (!string.IsNullOrEmpty(Request.Query["page"]))
{
pageNumber = int.Parse(Request.Query["page"]);
}
IsHomePage = Request.Path == "/";
HttpResponseMessage searchQueryResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/tajik/search?term={Query}&PageNumber={pageNumber}&PageSize=20");
if (!searchQueryResponse.IsSuccessStatusCode)
{
LastError = JsonConvert.DeserializeObject<string>(await searchQueryResponse.Content.ReadAsStringAsync());
return Page();
}
Poems = JArray.Parse(await searchQueryResponse.Content.ReadAsStringAsync()).ToObject<List<GanjoorPoemCompleteViewModel>>();
if (Poems != null && Poems.Count == 0)
{
Poems = null;
}
if (Poems != null)
{
// highlight searched word
string[] queryParts = Query.IndexOf('"') == 0 && Query.LastIndexOf('"') == (Query.Length - 1) ?
[Query.Replace("\"", "")]
:
Query.Replace("\"", "").Split(' ', StringSplitOptions.RemoveEmptyEntries);
foreach (var poem in Poems)
{
string[] lines = poem.PlainText.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
List<int> linesInExcerpt = new List<int>();
for (int i = 0; i < lines.Length; i++)
{
foreach (var queryPart in queryParts)
{
if (lines[i].IndexOf(queryPart) != -1)
{
if (i > 0)
{
if (linesInExcerpt.IndexOf(i - 1) == -1)
{
linesInExcerpt.Add(i - 1);
}
}
if (linesInExcerpt.IndexOf(i) == -1)
{
linesInExcerpt.Add(i);
}
if (i < (lines.Length - 1))
linesInExcerpt.Add(i + 1);
break;
}
}
}
string plainText = "";
for (int i = 0; i < linesInExcerpt.Count; i++)
{
if (linesInExcerpt[i] > 0 && linesInExcerpt.IndexOf(linesInExcerpt[i] - 1) == -1)
plainText += "... ";
plainText += $"{lines[linesInExcerpt[i]]}";
if (linesInExcerpt[i] < (lines.Length - 1) && linesInExcerpt.IndexOf(linesInExcerpt[i] + 1) == -1)
plainText += " ...";
plainText += $"{Environment.NewLine}";
}
string finalPlainText = "";
foreach (string line in plainText.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries))
{
finalPlainText += $"<p>{line}</p>";
}
if (linesInExcerpt.Count > 0)
{
poem.PlainText = finalPlainText;
}
for (int i = 0; i < queryParts.Length; i++)
{
string cssClass = i % 3 == 0 ? "hilite" : i % 3 == 1 ? "hilite2" : "hilite3";
poem.PlainText = Regex.Replace(poem.PlainText, queryParts[i], $"<span class=\"{cssClass}\">{queryParts[i]}</span>", RegexOptions.IgnoreCase | RegexOptions.RightToLeft); ;
}
}
}
}
else
if (!IsHomePage)
{
var pageQuery = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/tajik/page?url={Request.Path}&catPoems=true");

View File

@ -15,8 +15,8 @@
@Html.Raw(ViewData["BreadCrumpUrls"])
</div>
<div class="flex-fill"></div>
<form class="d-flex" action="/search" method="get" id="searchhorm">
<input type="search" class="form-control" placeholder="ҷустуҷӯ" aria-label="ҷустуҷӯ" name="s" id="s">
<form class="d-flex" action="/" method="get" id="searchhorm">
<input type="search" class="form-control" placeholder="ҷустуҷӯ" aria-label="ҷустуҷӯ" name="s" id="s" value="@Model.Query">
</form>
</nav>
</header>

View File

@ -7,11 +7,11 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;8602;8618</NoWarn>
<NoWarn>1701;1702;8602;8618;8601;8604;8625</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;8602;8618</NoWarn>
<NoWarn>1701;1702;8602;8618;8601;8604;8625</NoWarn>
</PropertyGroup>
<ItemGroup>

View File

@ -19,4 +19,24 @@ html {
body {
margin-bottom: 60px;
}
.hilite {
color: #000;
background-color: #9cf
}
.hilite1 {
color: #000;
background-color: #fc6
}
.hilite2 {
color: #000;
background-color: #9f6
}
.hilite3 {
color: #000;
background-color: #f99
}