main
Ogoun 4 months ago
parent 708729b3f0
commit 62dd21a4b7

@ -6,29 +6,6 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Page Include="web\css\fonts\Raleway-Italic-VariableFont_wght.ttf" />
<Page Include="web\css\fonts\Raleway-VariableFont_wght.ttf" />
<Page Include="web\css\fonts\Roboto-300.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-300.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-300.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-400.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-400.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="web\css\fonts\Roboto-400.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\BukiVedi.Shared\BukiVedi.Shared.csproj" /> <ProjectReference Include="..\BukiVedi.Shared\BukiVedi.Shared.csproj" />
</ItemGroup> </ItemGroup>
@ -40,6 +17,9 @@
<None Update="web\assets\cover.jpg"> <None Update="web\assets\cover.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\assets\fortune.svg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\assets\heart.svg"> <None Update="web\assets\heart.svg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
@ -52,10 +32,31 @@
<None Update="web\assets\search.svg"> <None Update="web\assets\search.svg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\css\buki-common.css"> <None Update="web\css\common.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\css\common.css"> <None Update="web\css\fonts\Raleway-Italic-VariableFont_wght.ttf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Raleway-VariableFont_wght.ttf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.ttf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.woff">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-300.woff2">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.ttf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.woff">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\css\fonts\Roboto-400.woff2">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\css\login.css"> <None Update="web\css\login.css">
@ -74,60 +75,54 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-Black.ttf"> <None Update="web\fonts\Roboto-Black.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-BlackItalic.ttf"> <None Update="web\fonts\Roboto-BlackItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-Bold.ttf"> <None Update="web\fonts\Roboto-Bold.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-BoldItalic.ttf"> <None Update="web\fonts\Roboto-BoldItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-Italic.ttf"> <None Update="web\fonts\Roboto-Italic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-Light.ttf"> <None Update="web\fonts\Roboto-Light.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-LightItalic.ttf"> <None Update="web\fonts\Roboto-LightItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-Medium.ttf"> <None Update="web\fonts\Roboto-Medium.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-MediumItalic.ttf"> <None Update="web\fonts\Roboto-MediumItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-Regular.ttf"> <None Update="web\fonts\Roboto-Regular.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-Thin.ttf"> <None Update="web\fonts\Roboto-Thin.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\fonts\Roboto-ThinItalic.ttf"> <None Update="web\fonts\Roboto-ThinItalic.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\images\favicon.ico"> <None Update="web\images\favicon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\images\flower.jpeg"> <None Update="web\images\flower.jpeg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\js\bukivedi-auth.js"> <None Update="web\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\bukivedi.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\js\common\jquery.js"> <None Update="web\js\common\jquery.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\js\common\jquery.min.js"> <None Update="web\js\components\menu\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\js\components\tags\index.js"> <None Update="web\js\components\tags\index.js">
@ -136,9 +131,6 @@
<None Update="web\js\constants\index.js"> <None Update="web\js\constants\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\js\jquery.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="web\js\login\index.js"> <None Update="web\js\login\index.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
@ -160,6 +152,9 @@
<None Update="web\loginScript.js"> <None Update="web\loginScript.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="web\README.md">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="web\script.js"> <None Update="web\script.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>

@ -36,6 +36,17 @@ namespace BukiVedi.App.Controllers
return Ok(await _handler.Search(request.Query, tag, OperationContext)); return Ok(await _handler.Search(request.Query, tag, OperationContext));
} }
/// <summary>
/// Поиск книг по запросу
/// </summary>
/// <param name="request">Поисковый запрос</param>
/// <returns>Список найденных книг</returns>
[HttpPost("qsearch")]
public async Task<ActionResult<IEnumerable<BookInfo>>> SearchAI()
{
return Ok(await _handler.SearchAI(OperationContext));
}
#endregion #endregion
/// <summary> /// <summary>

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("BukiVedi.App")] [assembly: System.Reflection.AssemblyCompanyAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+78ef654d3cca93dcdff7557d9a44da30b9d10a6a")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+708729b3f0a4a46b4ed8277753e30266f9b02ae4")]
[assembly: System.Reflection.AssemblyProductAttribute("BukiVedi.App")] [assembly: System.Reflection.AssemblyProductAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyTitleAttribute("BukiVedi.App")] [assembly: System.Reflection.AssemblyTitleAttribute("BukiVedi.App")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
9dd3a16a8dacdbe5f2cc466ad40a08504afd3b209bf5aa3244617367acdb74bb 5d627d5604365b2a4254a699545c17a9cb8aa8618ee125b742c4fb1f29d8de02

@ -88,10 +88,19 @@ G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\requests\i
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\scroll\index.js G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\scroll\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\script.js G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\script.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\assets\pencil.svg G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\assets\pencil.svg
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\common\jquery.min.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\components\tags\index.js G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\components\tags\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\utils\index.js G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\utils\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\loginScript.js G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\loginScript.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\server.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\LemmaSharpPrebuilt.pdb G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\LemmaSharpPrebuilt.pdb
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\LemmaSharpPrebuilt.dll.config G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\LemmaSharpPrebuilt.dll.config
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\assets\fortune.svg
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Raleway-Italic-VariableFont_wght.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Raleway-VariableFont_wght.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-300.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-300.woff
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-300.woff2
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-400.ttf
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-400.woff
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\css\fonts\Roboto-400.woff2
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\js\components\menu\index.js
G:\Documents\GitHub\BukiVedi\src\BukiVedi.App\bin\Debug\net8.0\web\README.md

@ -0,0 +1,12 @@
# Vanilla JS Project
Vesion 1.0
## To run chrome for localhost:
`
"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --disable-gpu --user-data-dir=C:\Users\User\chromeTemp
`
## To run project for [localhost](http://localhost:3001/login.html):
`
npm start
`

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path d="M256,16c-64.106,0-124.375,24.964-169.706,70.294S16,191.894,16,256s24.964,124.375,70.294,169.706S191.894,496,256,496 s124.375-24.964,169.706-70.294S496,320.106,496,256s-24.964-124.375-70.294-169.706S320.106,16,256,16z M456.194,155.59 l-40.313,26.875c-16.205-35.093-43.629-63.977-77.648-82.032l18.959-44.238C399.847,77.886,434.664,112.839,456.194,155.59z M256,416c-88.224,0-160-71.776-160-160S167.776,96,256,96s160,71.776,160,160S344.224,416,256,416z M342.674,49.453l-18.91,44.122 C302.896,84.836,280.003,80,256,80s-46.896,4.836-67.764,13.575l-18.91-44.122C196.001,38.218,225.287,32,256,32 S315.999,38.218,342.674,49.453z M154.809,56.195l18.959,44.238c-32.088,17.03-58.312,43.692-74.785,76.114l-42.925-21.463 C77.606,112.563,112.321,77.801,154.809,56.195z M49.336,169.612l43.052,21.526C84.398,211.22,80,233.105,80,256 c0,24.003,4.836,46.896,13.575,67.764l-44.122,18.91C38.218,315.999,32,286.713,32,256C32,225.396,38.176,196.21,49.336,169.612z M56.195,357.191l44.238-18.959c16.541,31.165,42.169,56.794,73.335,73.335l-18.959,44.238 C112.412,434.246,77.754,399.588,56.195,357.191z M169.326,462.547l18.91-44.122C209.104,427.164,231.997,432,256,432 s46.896-4.836,67.764-13.575l18.91,44.122C315.999,473.782,286.713,480,256,480S196.001,473.782,169.326,462.547z M357.191,455.805 l-18.959-44.238c34.019-18.055,61.443-46.939,77.648-82.032l40.313,26.875C434.664,399.161,399.847,434.114,357.191,455.805z M462.951,341.686l-40.925-27.283C428.477,296.118,432,276.464,432,256c0-20.464-3.523-40.118-9.974-58.403l40.925-27.283 C473.927,196.724,480,225.664,480,256C480,286.336,473.927,315.276,462.951,341.686z M349.654,338.341l-48.821-48.821 c5.494-7.329,9.225-16.047,10.587-25.519H336v16c0,2.882,1.55,5.542,4.059,6.961c1.224,0.693,2.583,1.039,3.941,1.039 c1.426,0,2.851-0.381,4.116-1.14l40-24c2.409-1.446,3.884-4.05,3.884-6.86s-1.475-5.414-3.884-6.86l-40-24 c-2.472-1.483-5.549-1.521-8.058-0.102S336,229.118,336,232v16h-24.581c-1.361-9.473-5.093-18.19-10.587-25.519l48.821-48.821 C351.103,172.211,352,170.21,352,168c0-4.418-3.582-8-8-8c-2.21,0-4.211,0.897-5.659,2.346l-48.821,48.821 c-7.329-5.494-16.046-9.225-25.519-10.587V184h16c4.418,0,8-3.582,8-8s-3.582-8-8-8h-6.131c3.809-4.249,6.131-9.858,6.131-16 c0-4.516-1.255-8.743-3.433-12.354c5.482-2.567,8.518-5.418,9.085-5.985c1.45-1.448,2.347-3.45,2.347-5.661c0-4.418-3.582-8-8-8 c-2.21,0-4.21,0.896-5.658,2.344C274.274,122.411,268.13,128,256,128c-12.149,0-18.184-5.512-18.435-5.747l0.088,0.087 c-1.447-1.446-3.446-2.34-5.653-2.34c-4.418,0-8,3.582-8,8c0,2.211,0.897,4.213,2.347,5.661c0.567,0.567,3.603,3.418,9.085,5.985 C233.255,143.257,232,147.484,232,152c0,6.142,2.322,11.751,6.131,16H232c-4.418,0-8,3.582-8,8s3.582,8,8,8h16v16.581 c-9.473,1.361-18.19,5.093-25.519,10.587l-48.821-48.821C172.211,160.897,170.21,160,168,160c-4.418,0-8,3.582-8,8 c0,2.21,0.897,4.211,2.346,5.659l48.821,48.821c-5.494,7.329-9.225,16.046-10.587,25.519h-33.957c-3.302-9.311-12.194-16-22.624-16 c-13.234,0-24,10.766-24,24s10.766,24,24,24c10.429,0,19.322-6.689,22.624-16h33.957c1.361,9.473,5.093,18.19,10.587,25.519 l-48.821,48.821C160.897,339.789,160,341.79,160,344c0,4.418,3.582,8,8,8c2.21,0,4.211-0.897,5.659-2.346l48.821-48.821 c7.329,5.494,16.046,9.225,25.519,10.587v21.267l-2.343-2.343c-3.124-3.124-8.189-3.124-11.313,0l-15.997,15.997 C216.897,347.789,216,349.79,216,352c0,4.418,3.582,8,8,8c2.21,0,4.211-0.897,5.659-2.346L240,347.314l10.343,10.343 c1.562,1.562,3.609,2.343,5.657,2.343s4.095-0.781,5.657-2.343L272,347.314l10.341,10.34C283.789,359.103,285.79,360,288,360 c4.418,0,8-3.582,8-8c0-2.21-0.897-4.211-2.346-5.659l-15.997-15.997c-3.124-3.124-8.189-3.124-11.313,0L264,332.686v-21.267 c9.473-1.361,18.19-5.093,25.519-10.587l48.821,48.821C339.789,351.103,341.79,352,344,352c4.418,0,8-3.582,8-8 C352,341.79,351.103,339.789,349.654,338.341z M352,246.129L368.451,256L352,265.871V246.129z M264,152c0,4.411-3.589,8-8,8 s-8-3.589-8-8s3.589-8,8-8S264,147.589,264,152z M256,296c-22.056,0-40-17.944-40-40s17.944-40,40-40s40,17.944,40,40 S278.056,296,256,296z M144,264c-4.411,0-8-3.589-8-8s3.589-8,8-8s8,3.589,8,8S148.411,264,144,264z M296,384c0,4.418-3.582,8-8,8 c-2.21,0-4.211-0.897-5.659-2.346L272,379.314l-10.343,10.343C260.095,391.219,258.047,392,256,392s-4.095-0.781-5.657-2.343 L240,379.314l-10.341,10.34C228.211,391.103,226.21,392,224,392c-4.418,0-8-3.582-8-8c0-2.21,0.897-4.211,2.346-5.659l15.997-15.997 c3.124-3.124,8.189-3.124,11.313,0L256,372.686l10.343-10.343c3.124-3.124,8.189-3.124,11.313,0l15.997,15.997 C295.103,379.789,296,381.79,296,384z"/></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

@ -76,6 +76,11 @@ input {
margin-bottom: 12px; margin-bottom: 12px;
} }
.mv-m {
margin-top: 20px;
margin-bottom: 20px;
}
.mt-m { .mt-m {
margin-top: 20px; margin-top: 20px;
} }
@ -130,6 +135,10 @@ input {
padding-right: 12px; padding-right: 12px;
} }
.pt-l {
padding-top: 40px;
}
/** /**
* display forms * display forms
**/ **/
@ -138,6 +147,11 @@ input {
display: flex; display: flex;
} }
.justify-c {
display: flex;
justify-content: center;
}
.d-bl { .d-bl {
display: block; display: block;
} }

@ -1,7 +1,7 @@
.background-logo { .background-logo {
position: absolute; position: absolute;
top: -15px; top: 25px;
left: 20px; left: 20px;
z-index: -1; z-index: -1;
overflow: hidden; overflow: hidden;

@ -34,10 +34,16 @@ header {
width: 20px; width: 20px;
height: 100%; height: 100%;
left: 10px; left: 10px;
top: 15px; top: 55px;
opacity: 0.25; opacity: 0.25;
} }
.main-search-btn-wrapper {
position: absolute;
right: 5px;
top: 43px;
}
.main-search { .main-search {
display: block; display: block;
width: 100%; width: 100%;
@ -47,6 +53,7 @@ header {
border-radius: 14px; border-radius: 14px;
border-style: solid; border-style: solid;
border-width: 1px; border-width: 1px;
padding-right: 200px;
} }
.main-search:hover { .main-search:hover {
@ -67,20 +74,23 @@ header {
.main-search-btn { .main-search-btn {
display: block; display: block;
margin-left: auto; visibility: hidden;
margin-right: auto; max-width: 120px;
max-width: 200px; width: 120px;
width: 200px; height: 44px;
height: 50px;
min-width: 80px; min-width: 80px;
background: var(--main-font-color); background: var(--main-font-color);
color: var(--main-bg-color); color: var(--main-bg-color);
font-size: 21px; font-size: 17px;
line-height: 25px; line-height: 25px;
border-radius: 15px; border-radius: 15px;
cursor: pointer; cursor: pointer;
} }
.main-search-btn.visible {
visibility: visible;
}
.main-search-btn:hover { .main-search-btn:hover {
opacity: 0.9; opacity: 0.9;
} }
@ -96,6 +106,61 @@ header {
margin-right: auto; margin-right: auto;
} }
#fortuneButton {
background-color: transparent;
background-image: url(../assets/fortune.svg);
background-repeat: no-repeat;
width: 40px;
height: 40px;
border: 0;
margin-left: 12px;
margin-top: 3px;
position: relative;
transform-origin: center center;
}
#fortuneButton:hover {
cursor: pointer;
animation: antiClockwiseSpin 1s linear;
transform-origin: center center;
}
#fortuneButton:active {
transform: translateY(2px);
}
@keyframes antiClockwiseSpin {
0% {
transform: rotate(180deg);
}
100% {
transform: rotate(0deg);
}
}
@keyframes antiClockwiseSpin {
0% {
transform: rotate(180deg);
}
100% {
transform: rotate(0deg);
}
}
/*
#fortuneButton:hover:after {
content: "Мне повезет!";
color: var(--main-font-color);
width: 95px;
font-size: 13px;
padding: 5px;
border-radius: 5px;
background: #fff;
position: absolute;
opacity: 1;
z-index: 2;
} */
/*======================================================== /*========================================================
Book Section Book Section
========================================================*/ ========================================================*/
@ -139,6 +204,7 @@ header {
.main-book__card.card_closed { .main-book__card.card_closed {
max-height: 450px; max-height: 450px;
min-height: 285px;
overflow-y: hidden; overflow-y: hidden;
} }
@ -316,7 +382,7 @@ header {
padding-bottom: 4px; padding-bottom: 4px;
background: #fff; background: #fff;
line-height: 28px; line-height: 28px;
width: 200px; width: 230px;
vertical-align: middle; vertical-align: middle;
} }
@ -342,7 +408,7 @@ header {
.main-book__tags_title { .main-book__tags_title {
position: relative; position: relative;
width: 55px; width: 113px;
font-family: Vedi, Verdana, Tahoma; font-family: Vedi, Verdana, Tahoma;
font-size: 14px; font-size: 14px;
line-height: 24px; line-height: 24px;
@ -355,17 +421,23 @@ header {
color: var(--active-color); color: var(--active-color);
} }
.pencil { .pencil {
position: absolute;
top: 4px;
left: 40px;
background-image: url(../assets/pencil.svg); background-image: url(../assets/pencil.svg);
background-repeat: no-repeat; background-repeat: no-repeat;
width: 20px; width: 20px;
height: 100%; height: 20px;
margin-left: 12px;
margin-top: 4px;
} }
.main-book__tags_title:hover, .main-book__pencil {
.main-book__tags_title:active .pencil { position: absolute;
top: 0;
left: 90px;
}
.pencil:hover,
.pencil:active {
cursor: pointer;
filter: brightness(0) saturate(100%) invert(43%) sepia(34%) saturate(7336%) filter: brightness(0) saturate(100%) invert(43%) sepia(34%) saturate(7336%)
hue-rotate(202deg) brightness(82%) contrast(97%); hue-rotate(202deg) brightness(82%) contrast(97%);
} }
@ -486,7 +558,7 @@ header {
box-sizing: border-box; box-sizing: border-box;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 4px; border-radius: 4px;
background-color: #FFF; background-color: #fff;
color: var(--main-font-color); color: var(--main-font-color);
font-size: 14px; font-size: 14px;
font-family: Vedi, Verdana, Tahoma; font-family: Vedi, Verdana, Tahoma;

@ -22,17 +22,21 @@
<body> <body>
<header> <header>
<h1 class="background-logo">Vedi</h1> <h1 class="background-logo">Vedi</h1>
<div class="main-search-wrapper mt-l d-fl"> <div class="main-search-wrapper pt-l d-fl">
<div class="main-search-pic"></div> <div class="main-search-pic"></div>
<input <input
id="search" id="search"
class="main-search pl-l pr-s" class="main-search pl-l"
placeholder="Выбери книгу, и я найду для тебя похожие" placeholder="Выбери книгу, и я найду для тебя похожие"
autocomplete="off" autocomplete="off"
autofocus autofocus
/> />
<div class="main-search-btn-wrapper d-fl">
<button id="searchButton" class="main-search-btn">Найти</button>
<button id="fortuneButton" class="main-fortune-search-btn"></button>
</div>
</div> </div>
<button id="searchButton" class="main-search-btn mt-m">Найти</button>
</div> </div>
</header> </header>
<main> <main>

@ -0,0 +1,112 @@
import { waitForElement } from "../../requests/index.js";
import { getMenu } from "../../constants/index.js";
export default class MenuComponent {
element;
constructor({
isBlocked = false,
hasReadLater = false,
authors = [],
bookid = null,
article,
}) {
this.isBlocked = isBlocked;
this.hasReadLater = hasReadLater;
this.authors = authors;
this.bookid = bookid;
this.article = article;
this.isOpened = false;
this.render();
}
get template() {
return `
<nav class="main-book__menu main-book__menu_closed" data-menu></nav>`;
}
initialize() {
this.initEventListeners();
}
initEventListeners() {
const menuListener = this.article.querySelector(".main-book__menu");
menuListener.addEventListener("click", (event) => {
const isAction = event.target.closest("[data-action]");
if (!!isAction) {
const id = isAction.dataset.action;
this.makeAction({ id });
} else {
this.openMenu();
}
});
document.addEventListener("menu-outside-click", () => this.closeMenu());
}
get actions() {
return getMenu({
isBlocked: this.isBlocked,
hasReadLater: this.hasReadLater,
});
}
getMenuBody() {
return this.actions
.map(({ label, id }) => {
return `
<li class="main-book__action second-text" id="main-book__action" data-action=${id}>
${label}
</li>`;
})
.join("");
}
openMenu() {
this.element.classList.remove("main-book__menu_closed");
const ulElement = document.createElement("ul");
ulElement.innerHTML = this.getMenuBody();
this.element.append(ulElement);
this.element.classList.add("main-book__menu_opened");
this.isOpened = true;
}
closeMenu() {
if (this.isOpened) {
this.element.classList.remove("main-book__menu_opened");
this.element.firstElementChild.remove();
this.element.classList.add("main-book__menu_closed");
this.isOpened = false;
}
}
async makeAction({ id }) {
this.article.classList.add("blur", "spinner");
const { action, value } =
this.actions.find((act) => act.id === Number(id)) || {};
await action({ id, bookid: this.bookid });
if (value) {
const { id, label } = value;
this[`${id}`] = label;
}
this.article.classList.remove("spinner");
this.closeMenu();
}
async waitRendered() {
await waitForElement(".main-book__menu");
this.initialize();
}
async render() {
const divElement = document.createElement("div");
divElement.innerHTML = this.template;
this.element = divElement.firstElementChild;
this.waitRendered();
}
}

@ -11,27 +11,37 @@ export default class TagsComponent {
} }
get template() { get template() {
return ` return `<div class="main-book_edit">
<h6 data-edit-tag class="main-book__tags_title mt-m"> ${
Теги !(this.tags && this.tags.length)
<div class="pencil"></div> ? this.getTitle()
</h6> : this.getTags(this.tags)
<div class="main-book__center main-book__tags d-fl mv-s">${this.getTags(
this.tags
)}</div>
`;
} }
</div>`;
}
getTitle() {
return `<h6 data-tags-editor class="main-book__tags_title mt-s mb-m">
Добавить теги
<div class="main-book__pencil pencil"></div>
</h6> `;
}
getTags(tags) { getTags(tags) {
return (tags || []) return `<div class="main-book__center main-book__tags d-fl mt-s mb-m">
${(tags || [])
.map(({ id, name }) => { .map(({ id, name }) => {
return `<a class="main-book__tag main-book__link" data-tag=${id}>#${name}</a>`; return `<a class="main-book__tag main-book__link" data-tag=${id}>#${name}</a>`;
}) })
.join(""); .join("")}
<div data-tags-editor class="pencil"></div></div>`;
} }
getTextarea(tags) { getTextarea(tags) {
return ` return `
<textarea class="main-book__textarea" data-area>${(tags || []) <textarea data-tags-editor placeholder="Редактировать поле" class="main-book__textarea" data-area>${(
tags || []
)
.map(({ name }) => name) .map(({ name }) => name)
.join(" ")}</textarea> .join(" ")}</textarea>
`; `;
@ -42,15 +52,13 @@ export default class TagsComponent {
} }
initEventListeners() { initEventListeners() {
const tagsEditorListener = this.article.querySelector( const tagsEditorListener = this.article.querySelector(".main-book_edit");
".main-book__tags_title"
);
tagsEditorListener.addEventListener("click", () => { tagsEditorListener.addEventListener("click", () => {
const tagsWrapper = this.article.querySelector(".main-book__tags");
if (!this.isTextareaMode) { if (!this.isTextareaMode) {
const tagsWrapper = this.article.querySelector(".main-book_edit");
tagsWrapper.innerHTML = this.getTextarea(this.tags); tagsWrapper.innerHTML = this.getTextarea(this.tags);
this.article.querySelector(".main-book__textarea").focus(); this.article.querySelector(".main-book__textarea").focus();
this.isTextareaMode = true; this.isTextareaMode = true;
} }
@ -64,7 +72,7 @@ export default class TagsComponent {
} }
}); });
document.addEventListener("outside-click", async () => { document.addEventListener("tag-outside-click", async () => {
if (this.isTextareaMode) { if (this.isTextareaMode) {
this.closeTextarea(); this.closeTextarea();
} }
@ -72,22 +80,31 @@ export default class TagsComponent {
} }
async closeTextarea() { async closeTextarea() {
const tagsWrapper = this.article.querySelector(".main-book__tags"); const tagsWrapper = this.article.querySelector(".main-book_edit");
const area = this.article.querySelector(".main-book__textarea"); const area = this.article.querySelector(".main-book__textarea");
const tags = area.value const tags = area.value
.split(" ") .split(" ")
.map((item) => item.trim()) .map((item) => item.trim())
.filter((i) => i); .filter((i) => i);
if (!!(tags || []).length > 0) {
if (
this.tags?.length !== tags?.length ||
(this.tags || []).some(({ name }, index) => name !== tags[index])
) {
await this.setTags({ bookid: this.bookid, tags }); await this.setTags({ bookid: this.bookid, tags });
} }
if (!!(tags || []).length > 0) {
tagsWrapper.innerHTML = this.getTags(this.tags); tagsWrapper.innerHTML = this.getTags(this.tags);
} else {
tagsWrapper.innerHTML = this.getTitle();
}
this.isTextareaMode = false; this.isTextareaMode = false;
} }
async waitRendered() { async waitRendered() {
await waitForElement(".main-book__tags"); await waitForElement(".main-book_edit");
this.initialize(); this.initialize();
} }

@ -1,40 +1,73 @@
import * as requests from '../requests/index.js'; import * as requests from "../requests/index.js";
export const SUCCESS = "success"; export const SUCCESS = "success";
export const menuEnum = [ export const menuDict = [
{ {
id: 1, id: 1,
label: "Авторов в избранное", label: "В очередь на чтение",
action: requests.addAuthorToFavourites, action: requests.readLater,
value: {
id: 'hasReadLater',
label: true,
}
}, },
{ {
id: 2, id: 2,
label: "В очередь на чтение", label: "Убрать из очереди",
action: requests.readLater, action: requests.removeFromReadLater,
value: {
id: 'hasReadLater',
label: false,
}
}, },
{ {
id: 3, id: 3,
label: "Игнорировать книгу", label: "Игнорировать книгу",
action: requests.ignoreBook, action: requests.ignoreBook,
value: {
id: 'isBlocked',
label: true,
}
}, },
{ {
id: 4, id: 4,
label: "Игнорировать автора", label: "Перестать игнорировать книгу",
action: requests.ignoreAuthors, action: requests.stopIgnoreBook,
value: {
id: 'isBlocked',
label: false,
}
},
{
id: 5,
label: "Авторов в избранное",
action: requests.addAuthorToFavourites,
}, },
{ {
id: 6, id: 6,
label: "Заметка", label: "Игнорировать авторов",
action: requests.ignoreAuthors,
}, },
{ {
id: 7, id: 7,
label: "Заметка",
action: () => {},
},
{
id: 8,
label: "Поделиться", label: "Поделиться",
action: () => {},
}, },
]; ];
export const getMenu = ({ isBlocked, hasReadLater }) =>
menuDict
.filter((item) => (isBlocked ? item.id !== 3 : item.id !== 4))
.filter((item) => (hasReadLater ? item.id !== 1 : item.id !== 2));
export const DEFAULT_AUTHOR = { export const DEFAULT_AUTHOR = {
id: 0, id: 0,
name: 'Неизвестно' name: "Неизвестно",
}; };
export const likeEnum = [ export const likeEnum = [
@ -47,5 +80,5 @@ export const likeEnum = [
id: 1, id: 1,
label: "Не нравится", label: "Не нравится",
action: requests.removeBookToFavourites, action: requests.removeBookToFavourites,
} },
] ];

@ -1,6 +1,7 @@
import { menuEnum, likeEnum, DEFAULT_AUTHOR } from "../constants/index.js"; import { likeEnum, DEFAULT_AUTHOR } from "../constants/index.js";
import { import {
fetchData, fetchData,
fetchRandomData,
downloadBook, downloadBook,
searchByAuthor, searchByAuthor,
searchByTag, searchByTag,
@ -9,6 +10,7 @@ import {
import { stopPropagation } from "../utils/index.js"; import { stopPropagation } from "../utils/index.js";
import TagsComponent from "../components/tags/index.js"; import TagsComponent from "../components/tags/index.js";
import MenuComponent from "../components/menu/index.js";
export default class BookSection { export default class BookSection {
subElements = []; subElements = [];
@ -37,31 +39,22 @@ export default class BookSection {
const booksListener = document.querySelector(".main-book__wrapper"); const booksListener = document.querySelector(".main-book__wrapper");
booksListener.addEventListener("click", (event) => { booksListener.addEventListener("click", (event) => {
let id, title; let id, title;
stopPropagation(event);
const menuEvent = new CustomEvent("menu-outside-click");
const tagEvent = new CustomEvent("tag-outside-click");
const isLike = event.target.closest("[data-like]"); const isLike = event.target.closest("[data-like]");
const isMenu = event.target.closest("[data-menu]");
const isAction = event.target.closest("[data-action]");
const isLink = event.target.closest("[data-link]"); const isLink = event.target.closest("[data-link]");
const isAuthor = event.target.closest("[data-author]"); const isAuthor = event.target.closest("[data-author]");
const isMoreDetails = event.target.closest("[data-details]"); const isMoreDetails = event.target.closest("[data-details]");
const isTagWrapper = event.target.closest("[data-tags-wrapper]"); const isTagWrapper = event.target.closest("[data-tags-editor]");
const isTag = event.target.closest("[data-tag]"); const isTag = event.target.closest("[data-tag]");
const isMenuWrapper = event.target.closest("[data-menu]");
stopPropagation(event);
switch (true) { switch (true) {
case !!isAction:
id = isAction.dataset.action;
const { authorid, bookid } =
isAction.parentNode.parentNode.dataset || {};
this.makeAction({ id, authorid, bookid });
break;
case !!isLike: case !!isLike:
this.makeLike(isLike); this.makeLike(isLike);
break;
case !!isMenu:
this.openMenu(isMenu);
break; break;
case !!isLink: case !!isLink:
@ -80,19 +73,20 @@ export default class BookSection {
this.toggleDetails(isMoreDetails); this.toggleDetails(isMoreDetails);
break; break;
case !isTagWrapper: case !!isMenuWrapper:
const myEvent = new CustomEvent("outside-click");
document.dispatchEvent(myEvent);
this.closeMenu();
break; break;
case !!isTag: case !!isTag:
id = isTag.dataset.tag; id = isTag.dataset.tag;
this.update({ isByTag: true, id }); this.update({ isByTag: true, id });
default: break;
this.closeMenu(); case !isTagWrapper && !isTag && !isMenuWrapper:
document.dispatchEvent(tagEvent);
document.dispatchEvent(menuEvent);
break;
default:
break; break;
} }
}); });
@ -128,10 +122,6 @@ export default class BookSection {
<div class="main-book__menu_like ${ <div class="main-book__menu_like ${
isFavorite ? "liked" : "not-liked" isFavorite ? "liked" : "not-liked"
}" data-like=${isFavorite} data-bookid=${id}></div> }" data-like=${isFavorite} data-bookid=${id}></div>
<nav class="main-book__menu main-book__menu_closed"
data-bookid=${id}
data-menu></nav>
</div> </div>
<div class="main-book__image mr-m"> <div class="main-book__image mr-m">
<div class='d-fl'> <div class='d-fl'>
@ -170,7 +160,7 @@ export default class BookSection {
</p> </p>
</div> </div>
<div class="main-book__body body_closed mb-m mt-s"> <div class="main-book__body body_closed mb-m mt-s">
<div data-tags-wrapper class="main-book__tags_wrapper"></div> <div class="main-book__tags_wrapper"></div>
<div> <div>
<span class="second-text"> <span class="second-text">
${description || "Нет описания"}</span> ${description || "Нет описания"}</span>
@ -197,17 +187,6 @@ export default class BookSection {
</article>`; </article>`;
} }
getMenuBody() {
return menuEnum
.map(({ label, id }) => {
return `
<li class="main-book__action second-text" id="main-book__action" data-action=${id}>
${label}
</li>`;
})
.join("");
}
getAuthors(authors) { getAuthors(authors) {
return (authors || [DEFAULT_AUTHOR]) return (authors || [DEFAULT_AUTHOR])
.map(({ id, name }) => { .map(({ id, name }) => {
@ -217,29 +196,6 @@ export default class BookSection {
.join(""); .join("");
} }
openMenu(element) {
this.closeMenu();
element.classList.remove("main-book__menu_closed");
const divElement = document.createElement("ul");
divElement.innerHTML = this.getMenuBody();
element.append(divElement);
element.classList.add("main-book__menu_opened");
}
closeMenu() {
const elements = document.querySelectorAll(".main-book__menu_opened");
if (elements && elements.length) {
for (const subElement of elements) {
subElement.firstElementChild.remove();
subElement.classList.remove("main-book__menu_opened");
subElement.classList.add("main-book__menu_closed");
}
}
}
toggleDetails(element) { toggleDetails(element) {
const isOpened = element.classList.contains("opened"); const isOpened = element.classList.contains("opened");
const article = element.parentNode.parentNode; const article = element.parentNode.parentNode;
@ -264,13 +220,23 @@ export default class BookSection {
const articles = document.querySelectorAll("[data-card]"); const articles = document.querySelectorAll("[data-card]");
articles.forEach((article, i) => { articles.forEach((article, i) => {
const tagWrapper = article.querySelector(".main-book__tags_wrapper"); const tagWrapper = article.querySelector(".main-book__tags_wrapper");
const menuWrapper = article.querySelector(".main-book__menu_wrapper");
const bookid = article.dataset.bookid; const bookid = article.dataset.bookid;
const { tags } = this.data[i] || []; const { tags, isBlocked, hasReadLater, authors } = this.data[i] || [];
const tagsComponent = new TagsComponent({ tags, article, bookid }); const tagsComponent = new TagsComponent({ tags, article, bookid });
const menuComponent = new MenuComponent({
isBlocked,
hasReadLater,
authors,
bookid,
article,
});
tagWrapper.append(tagsComponent.element); tagWrapper.append(tagsComponent.element);
menuWrapper.append(menuComponent.element);
// console.log('article.scrollHeight', article.scrollHeight);
if (article.scrollHeight > 502) { if (article.scrollHeight > 424) {
const arrow = article.querySelector(".main-book__arrow_wrapper"); const arrow = article.querySelector(".main-book__arrow_wrapper");
arrow.classList.remove("hidden"); arrow.classList.remove("hidden");
} }
@ -295,27 +261,26 @@ export default class BookSection {
const { bookid: likedBookId, like } = element.dataset || {}; const { bookid: likedBookId, like } = element.dataset || {};
const isLiked = like === "true"; const isLiked = like === "true";
if (!isLiked) { if (isLiked) {
await likeEnum[0].action({ bookid: likedBookId });
element.classList.remove("not-liked");
element.classList.add("liked");
} else {
await likeEnum[1].action({ bookid: likedBookId }); await likeEnum[1].action({ bookid: likedBookId });
element.classList.remove("liked"); element.classList.remove("liked");
element.classList.add("not-liked"); element.classList.add("not-liked");
} else {
await likeEnum[0].action({ bookid: likedBookId });
element.classList.remove("not-liked");
element.classList.add("liked");
} }
element.dataset.like = !isLiked; element.dataset.like = !isLiked;
this.data = this.data.map(({ isFavorite, id, ...rest }) => this.data = this.data.map(({ isFavorite, id, ...rest }) =>
likedBookId === id likedBookId === id
? { id, isFavorite: !isFavorite, ...rest } ? { id, ...rest, isFavorite: !isFavorite }
: { : {
id, id,
isFavorite, isFavorite,
...rest, ...rest,
} }
); );
console.log("new data", this.data);
this.element.classList.remove("spinner"); this.element.classList.remove("spinner");
} }
@ -326,6 +291,8 @@ export default class BookSection {
this.data = await searchByAuthor({ id: params.id }); this.data = await searchByAuthor({ id: params.id });
} else if (params?.isByTag) { } else if (params?.isByTag) {
this.data = await searchByTag({ id: params.id }); this.data = await searchByTag({ id: params.id });
} else if (params?.isByRandom) {
this.data = await fetchRandomData();
} else { } else {
const query = params; const query = params;
this.data = await fetchData({ query, url: this.url }); this.data = await fetchData({ query, url: this.url });
@ -335,10 +302,11 @@ export default class BookSection {
if (this.data && Object.values(this.data).length) { if (this.data && Object.values(this.data).length) {
this.subElements.body.innerHTML = this.getBookBody(this.data); this.subElements.body.innerHTML = this.getBookBody(this.data);
this.initialize(); this.initialize();
await this.countHeight();
} else { } else {
this.subElements.body.innerHTML = this.getEmptyBody(); this.subElements.body.innerHTML = this.getEmptyBody();
} }
await this.countHeight();
this.element.classList.remove("spinner"); this.element.classList.remove("spinner");
} }
@ -375,48 +343,50 @@ export default class BookSection {
} }
} }
// this.data = [ const testData = [
// { {
// id: "2", id: "2",
// authors: [{ id: "1", name: "123" }], authors: [{ id: "1", name: "123" }],
// description: description:
// "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
// format: "123", format: "123",
// genres: [], genres: [],
// imageUrl: "", imageUrl: "",
// title: "What is Lorem Ipsum?", title: "What is Lorem Ipsum?",
// series: [], series: [],
// subseries: [], subseries: [],
// year: 1992, year: 1992,
// tags: [ tags: [
// { id: 1, name: "Интересно" }, { id: 1, name: "Интересно" },
// { id: 22, name: "Почитать" }, { id: 22, name: "Почитать" },
// { id: 155, name: "Рекомендовали" }, { id: 155, name: "Рекомендовали" },
// { id: 166, name: "завтра" }, { id: 166, name: "завтра" },
// { id: 11, name: "наверное" }, { id: 11, name: "наверное" },
// { id: 221, name: "Почитданетать" }, { id: 221, name: "Почитданетать" },
// { id: 1515, name: "раздватри" }, { id: 1515, name: "раздватри" },
// { id: 1661, name: "возможно" }, { id: 1661, name: "возможно" },
// ], ],
// isFavorite: true, isFavorite: true,
// }, hasReadLater: true,
// { isBlocked: true,
// id: "22", },
// authors: [{ id: "1", name: "123" }], {
// description: id: "22",
// "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", authors: [{ id: "1", name: "123" }],
// format: "123", description:
// genres: [], "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
// imageUrl: "", format: "123",
// title: "dsfwqedwqefrwef", genres: [],
// series: [], imageUrl: "",
// subseries: [], title: "dsfwqedwqefrwef",
// year: 1992, series: [],
// tags: [ subseries: [],
// { id: 1, name: "Интересно" }, year: 1992,
// { id: 22, name: "Почитать" }, tags: [
// { id: 155, name: "Рекомендовали" }, { id: 1, name: "Интересно" },
// ], { id: 22, name: "Почитать" },
// isFavorite: true, { id: 155, name: "Рекомендовали" },
// }, ],
// ]; isFavorite: true,
},
];

@ -20,6 +20,24 @@ export const fetchData = ({ query, url }) => {
}); });
}; };
export const fetchRandomData = () => {
return $.ajax({
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "POST",
url: "../api/books/qsearch",
success: function (data, textStatus, jqXHR) {
if (textStatus === SUCCESS) {
return data;
}
return [];
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.statusText);
},
});
};
export const addBookToFavourites = ({ bookid }) => { export const addBookToFavourites = ({ bookid }) => {
return $.ajax({ return $.ajax({
type: "POST", type: "POST",
@ -221,10 +239,6 @@ export const changeTags = ({ bookid, tags }) => {
console.log(jqXHR.statusText); console.log(jqXHR.statusText);
}, },
}); });
// return [
// {id: "6611598e1468849d1b00570d", name: "шиза"}
// ];
}; };
export const searchByTag = ({ id }) => { export const searchByTag = ({ id }) => {

@ -1,4 +1,4 @@
export const stopPropagation = event => { export const stopPropagation = (event) => {
event.stopImmediatePropagation(); event.stopImmediatePropagation();
event.stopPropagation(); event.stopPropagation();
} };

@ -1,14 +1,17 @@
import BookSection from "./js/main/index.js"; import BookSection from "./js/main/index.js";
import ButtonScroll from './js/scroll/index.js'; import ButtonScroll from "./js/scroll/index.js";
const input = document.getElementById("search"); const input = document.getElementById("search");
const books = document.getElementById("books"); const books = document.getElementById("books");
const content = document.getElementById("content"); const content = document.getElementById("content");
const searchButton = document.getElementById("searchButton");
const fortuneButton = document.getElementById("fortuneButton");
const booksSection = new BookSection({ const booksSection = new BookSection({
url: "../api/books/search", url: "../api/books/search",
label: "books", label: "books",
}); });
const click = () => { const click = () => {
const query = document.getElementById("search").value; const query = document.getElementById("search").value;
if (query) { if (query) {
@ -16,8 +19,19 @@ const click = () => {
} }
}; };
searchButton.addEventListener("click", click); const fortuneClick = () => {
booksSection.update({ isByRandom: true });
};
searchButton.addEventListener("click", click);
fortuneButton.addEventListener("click", fortuneClick);
input.addEventListener("input", function (e) {
if (e.target.value && e.target.value.length !== 0) {
searchButton.classList.add("visible");
} else {
searchButton.classList.remove("visible");
}
});
input.addEventListener("keypress", function (event) { input.addEventListener("keypress", function (event) {
if (event.key === "Enter") { if (event.key === "Enter") {
click(); click();
@ -25,5 +39,5 @@ input.addEventListener("keypress", function (event) {
}); });
books.append(booksSection.element); books.append(booksSection.element);
const scroll = new ButtonScroll() const scroll = new ButtonScroll();
content.append(scroll.element) content.append(scroll.element);

@ -1,52 +0,0 @@
const path = require('path');
const { createProxyMiddleware } = require('http-proxy-middleware');
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const router = require('express').Router()
const options = {
target: 'https://book.ogoun.name/', // target host
changeOrigin: true, // needed for virtual hosted sites
ws: true, // proxy websockets
logLevel: 'debug',
secure: false,
cookieDomainRewrite: {
'*': 'localhost',
},
onProxyRes(proxyRes, req, _res) {
if (proxyRes.headers['set-cookie'] !== undefined) {
req.cookie = proxyRes.headers['set-cookie'];
}
},
onProxyReq(proxyReq, req, _res) {
if (req && req.cookie !== undefined) {
proxyReq.setHeader('Cookie', req.cookie[0]);
}
},
};
const myLogger = function (req, res, next) {
next()
}
app.use(myLogger)
app.use(express.static(__dirname));
app.use(express.static(__dirname + '/js'));
app.use(express.static(__dirname + '/css'));
app.use(express.static(__dirname + '/constants'));
// app.get('/login', function (req, res) {
// res.sendFile(path.join(__dirname, '/login.html'));
// });
app.use('/', cors({
credentials: true,
origin: 'http://localhost:3000',
}), createProxyMiddleware(options));
server.listen(3001);

@ -2,6 +2,7 @@
using BukiVedi.Shared.Models; using BukiVedi.Shared.Models;
using BukiVedi.Shared.Services; using BukiVedi.Shared.Services;
using BukiVedi.Shared.Services.Mappers; using BukiVedi.Shared.Services.Mappers;
using ZeroLevel.Patterns.Queries;
using ZeroLevel.Services.FileSystem; using ZeroLevel.Services.FileSystem;
namespace BukiVedi.Shared.Apps namespace BukiVedi.Shared.Apps
@ -176,6 +177,12 @@ namespace BukiVedi.Shared.Apps
return Enumerable.Empty<BookInfo>(); return Enumerable.Empty<BookInfo>();
} }
public async Task<IEnumerable<BookInfo>> SearchAI(OperationContext context)
{
var books = (await _library.SearchBooksAI(context.OperationInitiator.Id)).ToArray();
return await BookEntityMapper.Map(books, context);
}
public async Task UnblockBook(string id, OperationContext context) public async Task UnblockBook(string id, OperationContext context)
{ {
var account_id = context.OperationInitiator.Id; var account_id = context.OperationInitiator.Id;

@ -5,6 +5,7 @@ namespace BukiVedi.Shared.Apps
public interface IBooksHandler public interface IBooksHandler
{ {
Task<IEnumerable<BookInfo>> Search(string query, string? tag, OperationContext context); Task<IEnumerable<BookInfo>> Search(string query, string? tag, OperationContext context);
Task<IEnumerable<BookInfo>> SearchAI(OperationContext context);
Task AddToFavorite(string id, OperationContext context); Task AddToFavorite(string id, OperationContext context);
Task AddAuthorsToFavorite(string id, OperationContext context); Task AddAuthorsToFavorite(string id, OperationContext context);
Task BlockBook(string id, OperationContext context); Task BlockBook(string id, OperationContext context);

@ -16,7 +16,7 @@ namespace BukiVedi.Shared
Task<long> Count(FilterDefinition<T> predicate); Task<long> Count(FilterDefinition<T> predicate);
Task<bool> Exists(FilterDefinition<T> filter); Task<bool> Exists(FilterDefinition<T> filter);
Task<bool> ExistById(string id); Task<bool> ExistById(string id);
T[] GetRandomDocuments(int count);
Task<T> Write(T obj); Task<T> Write(T obj);

@ -13,6 +13,7 @@ namespace BukiVedi.Shared.Services
{ {
Task<IEnumerable<BookEntity>> SearchBooksByAuthor(string author_id); Task<IEnumerable<BookEntity>> SearchBooksByAuthor(string author_id);
Task<IEnumerable<BookEntity>> SearchBooks(string title); Task<IEnumerable<BookEntity>> SearchBooks(string title);
Task<BookEntity[]> SearchBooksAI(string accountId);
Task<IEnumerable<BookEntity>> SearchByTagBooks(string accountId, string tagId); Task<IEnumerable<BookEntity>> SearchByTagBooks(string accountId, string tagId);
Task<IEnumerable<BookEntity>> SearchTaggedBooks(string accountId, string tag = null!); Task<IEnumerable<BookEntity>> SearchTaggedBooks(string accountId, string tag = null!);
Task<IEnumerable<BookEntity>> SearchFavoritesBooks(string accountId); Task<IEnumerable<BookEntity>> SearchFavoritesBooks(string accountId);
@ -439,5 +440,27 @@ namespace BukiVedi.Shared.Services
await Tables.Books.Write(book); await Tables.Books.Write(book);
} }
} }
public Task<BookEntity[]> SearchBooksAI(string accountId)
{
var books = Tables.Books.GetRandomDocuments(50);
var result = new BookEntity[books.Length];
int index = 0;
foreach (var b in books)
{
result[index] = new BookEntity
{
Authors = GetAuthors(b),
Title = b.Title,
Year = b.Year,
Description = b.Description,
Format = b.Format,
Genre = new Genre(),
Id = b.Id,
};
index++;
}
return Task.FromResult(result);
}
} }
} }

@ -1,6 +1,7 @@
using BukiVedi.Shared.Entities; using BukiVedi.Shared.Entities;
using MongoDB.Bson; using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using MongoDB.Driver.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using ZeroLevel.Services.FileSystem; using ZeroLevel.Services.FileSystem;
@ -104,6 +105,12 @@ namespace BukiVedi.Shared.Services.MongoDB
return result.ToEnumerable().ToArray(); return result.ToEnumerable().ToArray();
} }
public T[] GetRandomDocuments(int count)
{
var result = _collection.AsQueryable().Sample(count);
return result.ToArray();
}
public async Task<long> Count(FilterDefinition<T> filter) public async Task<long> Count(FilterDefinition<T> filter)
{ {
return await _collection.CountDocumentsAsync(filter); return await _collection.CountDocumentsAsync(filter);

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("BukiVedi.Shared")] [assembly: System.Reflection.AssemblyCompanyAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+78ef654d3cca93dcdff7557d9a44da30b9d10a6a")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+708729b3f0a4a46b4ed8277753e30266f9b02ae4")]
[assembly: System.Reflection.AssemblyProductAttribute("BukiVedi.Shared")] [assembly: System.Reflection.AssemblyProductAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyTitleAttribute("BukiVedi.Shared")] [assembly: System.Reflection.AssemblyTitleAttribute("BukiVedi.Shared")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

@ -1 +1 @@
43fea615f27b115ca71adae9d28aa42c583a4dce3ecf8ac2e68c45249fa1eb8e 47f2ecfa029d676b8f2f23a9542e5f91afdb2a5aba3b39b9691101443bb7f9e8

Loading…
Cancel
Save

Powered by TurnKey Linux.