Menu fix, do not modify fix content fix, simplified content display from static menuitems

This commit is contained in:
Adam 2025-05-18 10:20:49 +02:00
parent fb6283628f
commit 03b1995771
59 changed files with 5169 additions and 817 deletions

View File

@ -1,6 +1,7 @@
@page
@using Sidio.Sitemap.Blazor
@model LoginModel
@attribute [Sitemap]
@{
ViewData["Title"] = "Log in";
}

View File

@ -1,5 +1,7 @@
@page
@using Sidio.Sitemap.Blazor
@model RegisterModel
@attribute [Sitemap]
@{
ViewData["Title"] = "Register";
}

View File

@ -31,6 +31,7 @@
<PackageReference Include="PdfPig" Version="0.1.10" />
<PackageReference Include="Qdrant.Client" Version="1.13.0" />
<PackageReference Include="Radzen.Blazor" Version="6.4.0" />
<PackageReference Include="Sidio.Sitemap.Blazor" Version="1.1.2" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="9.0.3" />
</ItemGroup>
@ -41,7 +42,9 @@
</ItemGroup>
<ItemGroup>
<None Include="wwwroot\video\GR Production Services.mp4" />
<None Include="wwwroot\video\GR Production Services.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
@ -60,6 +63,189 @@
<Content Update="wwwroot\default.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\10262403.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\267111581_6537457352993553_2093941074766316375_n.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\464609293_8553833781365611_797678058825756959_n.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\464702374_8571192746296381_2492674641604205759_n.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\464847960_8560471694035153_8000699131803786124_n.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\464867041_8570940996321556_6613785466010075519_n.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\464947949_8580789888670000_2158336133679231152_n.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\5.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\58441485_2159856217430098_8842486812262793216_n.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\all moods.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\article-1-header-cover.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\article-in-content-image.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Collaboration_1.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Collections22-23.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Daige_logo.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\darkstar.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\growtika-nGoCBxiaRO0-unsplash.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\halfscreen-parallax-img-1.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\halfscreen-parallax-img-2.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\hero-image-03_b.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\knitwear.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\linkedin-sales-solutions-oFMI6CdD7yU-unsplash.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\logo_social.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\makita4190D.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\makita4190D_figure_1.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Melinda.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Multicategory brand.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\original_prints.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\press_1.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\press_2.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\press_3.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\press_4.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\press_5.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\press_6.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\ribi1_bg.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\ribi1_brighter.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\ribi1_front.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\salespower_2.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\salespower_logo.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\stocklist.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\The_atelier.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-1.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-10.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-11.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-12.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-13.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-14.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-2.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-3.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-4.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-6.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-8.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-9.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-news-1.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-news-2.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-news-3-b.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-news-3.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe-news-4.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\Vhembe_logo.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\images\webshop.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\uploads\0988758e-e16c-4c2c-8c1e-efa3ac5f0274\videos\Lovereels.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\VG3law.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@ -105,6 +291,57 @@
<Content Update="wwwroot\ToyoTanso.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\adamg.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\ai.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\ai_old.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\Arts.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\Cleary Gottlieb.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\default.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\fratellino.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\lovebits.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\LoveBits_2.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\poppixel.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\salespower.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\salespower_old.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\TNS Corporation.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\toyotanso.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\vg3law.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\vhembe.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\video\video %2855%29.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@ -48,6 +48,18 @@
};
</script>
<script>
function collapseNavbar() {
const navbar = document.getElementById('navbarSupportedContent');
if (navbar && navbar.classList.contains('show')) {
const bsCollapse = bootstrap.Collapse.getInstance(navbar);
if (bsCollapse) {
bsCollapse.hide();
}
}
}
</script>
@code{
}

View File

@ -140,8 +140,8 @@ else
await JSRuntime.InvokeVoidAsync("setSessionId", SessionId);
await JSRuntime.InvokeVoidAsync("setHtmlEditorSourceMode");
await LoadTemplate();
var cssPath = await CssTemplateService.SaveTempCssFileAsync(currentCssTemplate.CssContent, SessionId);
await JSRuntime.InvokeVoidAsync("seemgen.injectCssFile", cssPath);
//var cssPath = await CssTemplateService.SaveTempCssFileAsync(currentCssTemplate.CssContent, SessionId);
//await JSRuntime.InvokeVoidAsync("seemgen.injectCssFile", cssPath);
}
}

View File

@ -6,6 +6,7 @@
@using Microsoft.AspNetCore.Identity.UI.Services
@using System.Text
@using System.Text.Json
@using Sidio.Sitemap.Blazor
@inject AIService ChatGptService
@rendermode InteractiveServer
@inject IJSRuntime jsRuntime;
@ -19,7 +20,7 @@
@inject DesignTemplateService DesignTemplateService
@inject CssTemplateService CssTemplateService
@inject CssInjectorService CssService
@attribute [Sitemap]
<div class="page" style="z-index: 1">
<NavMenu MenuString="@Menu" OnMenuClicked=@MenuClick></NavMenu>
@ -31,7 +32,7 @@
@* <HeadContent>
<style id="seemgen-style">@dynamicallyLoadedCss</style>
</HeadContent> *@
<div id="maincontrol">
@ -516,14 +517,22 @@
{
HtmlContent.Clear();
var menu = await GetMenuList();
await ChatGptService.ProcessContentRequest(sessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, collectionName, menu, forceUnmodified);
var menuItem = (await GetMenuItems()).Where(m => m.Name == input).FirstOrDefault();
if(menuItem == null)
{
await ChatGptService.ProcessContentRequest(sessionId, input, SiteId, (int)SiteInfo.TemplateId!, collectionName, menu, forceUnmodified);
}
else
{
await ChatGptService.ProcessContentRequest(sessionId, menuItem, SiteId, (int)SiteInfo.TemplateId!, collectionName, menu, forceUnmodified);
}
UserInput = string.Empty;
}
}
private async Task<string> GetMenuList()
{
List<MenuItem> menuItems = await _contentEditorService.GetMenuItemsBySiteIdAsync(SiteId);
List<MenuItem> menuItems = (await _contentEditorService.GetMenuItemsBySiteIdAsync(SiteId)).Where(m => m.ShowInMainMenu == true).OrderBy(m => m.SortOrder).ToList();
string menuList = "";
foreach (MenuItem item in menuItems)
{
@ -532,6 +541,12 @@
return menuList;
}
private async Task<List<MenuItem>> GetMenuItems()
{
List<MenuItem> menuItems = (await _contentEditorService.GetMenuItemsBySiteIdAsync(SiteId)).Where(m => m.ShowInMainMenu == true).OrderBy(m => m.SortOrder).ToList();
return menuItems;
}
private async void HandleBrandNameChanged()
{
selectedBrandName = _scopedContentService.SelectedBrandName;

View File

@ -289,7 +289,7 @@
if (_instances.TryGetValue(sessionId, out var instance))
{
await instance.HandleJsCall("Please search for me: " + input, sessionId, forceUnmodified);
await instance.HandleJsCall(input, sessionId, forceUnmodified);
}
Console.Write("Button clicked:" + input);
}
@ -505,14 +505,22 @@
{
HtmlContent.Clear();
var menu = await GetMenuList();
await ChatGptService.ProcessContentRequest(sessionId, UserInput, siteid, (int)SiteInfo.TemplateId!, collectionName, menu, forceUnmodified);
var menuItem = (await GetMenuItems()).Where(m => m.Name == input).FirstOrDefault();
if (menuItem == null)
{
await ChatGptService.ProcessContentRequest(sessionId, input, siteid, (int)SiteInfo.TemplateId!, collectionName, menu, forceUnmodified);
}
else
{
await ChatGptService.ProcessContentRequest(sessionId, menuItem, siteid, (int)SiteInfo.TemplateId!, collectionName, menu, forceUnmodified);
}
UserInput = string.Empty;
}
}
private async Task<string> GetMenuList()
{
List<MenuItem> menuItems = await _contentEditorService.GetMenuItemsBySiteIdAsync(siteid);
List<MenuItem> menuItems = (await _contentEditorService.GetMenuItemsBySiteIdAsync(siteid)).Where(m => m.ShowInMainMenu == true).OrderBy(m => m.SortOrder).ToList();
string menuList = "";
foreach (MenuItem item in menuItems)
{
@ -521,6 +529,12 @@
return menuList;
}
private async Task<List<MenuItem>> GetMenuItems()
{
List<MenuItem> menuItems = (await _contentEditorService.GetMenuItemsBySiteIdAsync(siteid)).Where(m => m.ShowInMainMenu == true).OrderBy(m => m.SortOrder).ToList();
return menuItems;
}
private async void HandleBrandNameChanged()
{
selectedBrandName = _scopedContentService.SelectedBrandName;

View File

@ -0,0 +1,220 @@
@page "/reordergridtest/{siteId:int}"
@using BLAIzor.Components.Layout
@using BLAIzor.Components.Partials
@using BLAIzor.Models
@using BLAIzor.Services
@using System.Collections.ObjectModel
@using Microsoft.JSInterop
@using Newtonsoft.Json
@inject ScopedContentService scopedContentService
@inject ContentEditorService contentEditorService
@inject QDrantService qDrantService
@layout AdminLayout
@* @inherits DbContextPage *@
@inject IJSRuntime JSRuntime;
<style>
.my-class td {
border-top: 1px solid black;
border-bottom: 1px solid black;
}
</style>
@if (menuItems == null)
{
<p><em>Loading...</em></p>
}
else
{
<RadzenRow Gap="1rem">
<RadzenColumn Size="12" SizeMD="2">
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Right">
@{
<RadzenButton Click="ToggleReorder">
@(allowReorder? "Cancel" : "Reorder")
</RadzenButton>
}
</RadzenStack>
<RadzenDataGrid @ref="dataGrid" TItem="MenuItem" RowSelect=@OnRowSelect AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false" FilterMode="FilterMode.Advanced" AllowSorting="true" PageSize="@pagesize" AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true"
Data="@menuItems" ColumnWidth="300px" LogicalFilterOperator="LogicalFilterOperator.Or" SelectionMode="DataGridSelectionMode.Single"
@bind-Value=@selectedMenuItems RowRender="@RowRender">
<Columns>
<RadzenDataGridColumn Property="@nameof(MenuItem.SortOrder)" Title="Sort order" Width="30px" />
@* <RadzenDataGridColumn Property="@nameof(MenuItem.Id)" Filterable="false" Title="ID" Frozen="true" Width="55px" TextAlign="TextAlign.Center" /> *@
<RadzenDataGridColumn Property="@nameof(MenuItem.Name)" Title="Name" Frozen="true" Width="130px" />
@* <RadzenDataGridColumn Property="@nameof(MenuItem.PointId)" Title="Point Id" Width="200px" /> *@
<RadzenDataGridColumn Property="@nameof(MenuItem.ShowInMainMenu)" Title="Show in menu" Width="30px" />
</Columns>
</RadzenDataGrid>
</RadzenColumn>
<RadzenColumn Size="12" SizeMD="10">
<RadzenCard Variant="Variant.Outlined" Style="height: 100%;">
<RadzenStack Gap="1rem">
<RadzenCard Variant="Variant.Text" class="rz-background-color-primary-lighter rz-color-on-primary-lighter">
Site:
@* <b>@selectedMenuItems.FirstOrDefault()?.SiteInfo.SiteName</b> *@
</RadzenCard>
<RadzenTabs>
<Tabs>
<RadzenTabsItem Text="MenuItems Details">
<MenuItemContentEditor Subject=@subject MenuItem="SelectedMenuItemModel" WordFile=@document SessionId="SessionId" OnContentUpdated="UpdateMenuItem" />
@* <RadzenDataGrid AllowFiltering="true" AllowPaging="true" AllowSorting="true" Data="@(selectedMenuItems.FirstOrDefault()?.Content)">
<Columns>
<RadzenDataGridColumn Property="Order.CustomerID" Title="Order" />
<RadzenDataGridColumn Property="Product.ProductName" Title="Product" />
<RadzenDataGridColumn Property="UnitPrice" Title="Unit Price">
<Template Context="detail">
@String.Format(new System.Globalization.CultureInfo("en-US"), "{0:C}", detail.UnitPrice)
</Template>
</RadzenDataGridColumn>
<RadzenDataGridColumn Property="@nameof(OrderDetail.Quantity)" Title="Quantity" />
<RadzenDataGridColumn Property="@nameof(OrderDetail.Discount)" Title="Discount">
<Template Context="detail">
@String.Format("{0}%", detail.Discount * 100)
</Template>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid> *@
</RadzenTabsItem>
</Tabs>
</RadzenTabs>
</RadzenStack>
</RadzenCard>
</RadzenColumn>
</RadzenRow>
}
@code {
[Parameter]
public int siteId { get; set; }
ObservableCollection<MenuItem> menuItems;
IList<MenuItem> selectedMenuItems;
private string document = "";
private string subject = "";
public bool hasCollection = false;
public bool MenuItemsSaved = false;
private bool allowReorder = false;
private int pagesize = 5;
private List<MenuItemModel> ExtractedMenuItems = new();
MenuItem draggedItem;
MenuItemModel SelectedMenuItemModel = new("");
private RadzenDataGrid<MenuItem> dataGrid;
protected override async Task OnParametersSetAsync()
{
await base.OnParametersSetAsync();
var siteInfo = await scopedContentService.GetSiteInfoByIdAsync(siteId);
// var menuItems1 = await contentEditorService.GetMenuItemsBySiteIdAsync(1);
menuItems = new ObservableCollection<MenuItem>(await contentEditorService.GetMenuItemsBySiteIdAsync(siteId));
selectedMenuItems = new List<MenuItem>() { menuItems.FirstOrDefault() };
var collectionResult = await qDrantService.GetCollectionBySiteIdAsync(siteId);
if (!string.IsNullOrEmpty(collectionResult))
{
//create colection
hasCollection = true;
Console.Write("Has collection already");
}
if (menuItems.Count() > 0)
{
foreach (var menuItem in menuItems)
{
string content;
MenuItemModel model = new MenuItemModel("");
//try to get content from qDrant
if (menuItem.QdrantPointId != null)
{
content = await qDrantService.GetContentAsync(siteId, menuItem.SortOrder);
var selectedPoint = JsonConvert.DeserializeObject<QDrantGetContentPointResult>(content)!;
if (selectedPoint != null)
{
model.Content = selectedPoint.result.payload.content;
Console.Write($"Found point: {selectedPoint.result.payload.content}");
}
}
model.MenuItem.Name = menuItem.Name;
ExtractedMenuItems.Add(model);
// UpdateMenuItem(model);
}
SelectedMenuItemModel.MenuItem.Name = selectedMenuItems.FirstOrDefault().Name;
SelectedMenuItemModel.Content = (ExtractedMenuItems.Where(x => x.MenuItem.Name == selectedMenuItems.FirstOrDefault().Name).FirstOrDefault()).Content;
MenuItemsSaved = true;
}
}
async void ToggleReorder()
{
if (!allowReorder)
{
pagesize = 20;
}
else
{
pagesize = 5;
}
allowReorder = !allowReorder;
}
void Select(MenuItem menuItem)
{
SelectedMenuItemModel.MenuItem.Name = menuItem.Name;
SelectedMenuItemModel.Content = ExtractedMenuItems.Where(x => x.MenuItem.Name == menuItem.Name).FirstOrDefault().Content;
}
void OnRowSelect(MenuItem menuItem)
{
Select(menuItem);
}
private void UpdateMenuItem(MenuItemModel updatedItem)
{
var item = ExtractedMenuItems!.FirstOrDefault(i => i.MenuItem.Name == updatedItem.MenuItem.Name);
if (item != null)
{
item.Content = updatedItem.Content;
}
}
void RowRender(RowRenderEventArgs<MenuItem> args)
{
if(allowReorder)
{
args.Attributes.Add("title", "Drag row to reorder");
args.Attributes.Add("style", "cursor:grab");
args.Attributes.Add("draggable", "true");
args.Attributes.Add("ondragover", "event.preventDefault();event.target.closest('.rz-data-row').classList.add('my-class')");
args.Attributes.Add("ondragleave", "event.target.closest('.rz-data-row').classList.remove('my-class')");
args.Attributes.Add("ondragstart", EventCallback.Factory.Create<DragEventArgs>(this, () => draggedItem = args.Data));
args.Attributes.Add("ondrop", EventCallback.Factory.Create<DragEventArgs>(this, () =>
{
var draggedIndex = menuItems.IndexOf(draggedItem);
var droppedIndex = menuItems.IndexOf(args.Data);
menuItems.Remove(draggedItem);
menuItems.Insert(draggedIndex <= droppedIndex ? droppedIndex++ : droppedIndex, draggedItem);
foreach (var menuItemToReorder in menuItems)
{
menuItemToReorder.SortOrder = menuItems.IndexOf(menuItemToReorder);
}
JSRuntime.InvokeVoidAsync("eval", $"document.querySelector('.my-class').classList.remove('my-class')");
}));
}
}
}

View File

@ -2,9 +2,11 @@
@using Microsoft.AspNetCore.Components.Forms
@using BLAIzor.Services
@using Newtonsoft.Json
@using System.Collections.ObjectModel
@inject ContentEditorService ContentEditorService
@inject HtmlSnippetProcessor HtmlSnippetProcessor
@inject QDrantService QDrantService
@inject IJSRuntime JSRuntime
<h3>Upload Document to Generate Menu Items</h3>
@ -19,78 +21,57 @@
}
else if (ExtractedMenuItems.Any())
{
<h4>Suggested Menu Items</h4>
<h4>Menu Items</h4>
<div class="row">
<div class="rz-p-sm-12">
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Right">
@{
<RadzenButton Click="ToggleReorder">
@(allowReorder ? "Done" : "Reorder")
</RadzenButton>
}
<RadzenPanel AllowCollapse="true" class="rz-my-10 rz-mx-auto" Style="width: 100%"
Expand=@(() => Change("Panel expanded")) Collapse=@(() => Change("Panel collapsed"))>
<HeaderTemplate>
<RadzenText TextStyle="TextStyle.H6" class="rz-display-flex rz-align-items-center rz-m-0">
<RadzenIcon Icon="account_box" class="rz-me-1" /><b>Orders</b>
</RadzenText>
</HeaderTemplate>
<ChildContent>
<RadzenCard class="rz-mt-4">
<RadzenDataList PageSize="1" WrapItems="true" AllowPaging="true"
Data="@ExtractedMenuItems" TItem="MenuItemModel">
<Template Context="item">
<RadzenCard Style="width: 100%">
<h3>@item.Name</h3>
<hr style="border: none; background-color: var(--rz-text-disabled-color); height: 1px; margin: 1rem 0;" />
@{
if (MenuItemsSaved)
{
<RadzenStack Orientation="Orientation.Vertical" AlignItems="AlignItems.Center" Gap="1rem">
<input @bind="item.Name" class="form-control border-0" placeholder="Menu item name" />
<MenuItemContentEditor Subject=@subject MenuItem="item" WordFile=@document SessionId="SessionId" OnContentUpdated="UpdateMenuItem" />
</RadzenStack>
}
<RadzenStack Orientation="@Orientation.Horizontal" Gap="10px" Reverse="false" JustifyContent="@JustifyContent.Center" AlignItems="@AlignItems.Center" Wrap="@FlexWrap.Wrap" Style="height: fit-content">
<button class="btn btn-default btn-sm mt-2" @onclick="() => AddMenuItem()">Add a new menu item after this one</button>
<button class="btn btn-danger btn-sm mt-2" @onclick="() => RemoveMenuItem(item)">Remove</button>
</RadzenStack>
</RadzenStack>
@if(allowReorder)
{
<RadzenDataGrid @ref="dataGrid" TItem="MenuItem" RowSelect=@OnRowSelect AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false" FilterMode="FilterMode.Advanced" AllowSorting="true" PageSize="20" AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true"
Data="@menuItems" ColumnWidth="300px" LogicalFilterOperator="LogicalFilterOperator.Or" SelectionMode="DataGridSelectionMode.Single"
@bind-Value=@selectedMenuItems RowRender="@RowRender">
<Columns>
<RadzenDataGridColumn Property="@nameof(MenuItem.SortOrder)" Title="Sort order" Width="30px" />
@* <RadzenDataGridColumn Property="@nameof(MenuItem.Id)" Filterable="false" Title="ID" Frozen="true" Width="55px" TextAlign="TextAlign.Center" /> *@
<RadzenDataGridColumn Property="@nameof(MenuItem.Name)" Title="Name" Frozen="true" Width="130px" />
@* <RadzenDataGridColumn Property="@nameof(MenuItem.PointId)" Title="Point Id" Width="200px" /> *@
<RadzenDataGridColumn Property="@nameof(MenuItem.ShowInMainMenu)" Title="Show in menu" Width="30px" />
</Columns>
</RadzenDataGrid>
}
else
{
<RadzenAccordion Multiple="true">
<Items>
@foreach (var item in ExtractedMenuItems)
{
<RadzenAccordionItem Text="@item.MenuItem.Name" Icon="account_balance_wallet">
@{
if (MenuItemsSaved)
{
<input @bind="item.MenuItem.Name" class="form-control border-0" placeholder="Menu item name" />
<MenuItemContentEditor Subject=@subject MenuItem="item" WordFile=@document SessionId="SessionId" OnContentUpdated="UpdateMenuItem" />
}
</RadzenCard>
</Template>
</RadzenDataList>
</RadzenCard>
</ChildContent>
<SummaryTemplate>
<RadzenCard class="rz-mt-4">
<b>@ExtractedMenuItems.Count() menu items</b>
</RadzenCard>
</SummaryTemplate>
</RadzenPanel>
@* <RadzenAccordion Multiple="true">
<Items>
@foreach (var item in ExtractedMenuItems)
{
<RadzenAccordionItem Text="@item.Name" Icon="account_balance_wallet">
@{
if (MenuItemsSaved)
{
<input @bind="item.Name" class="form-control border-0" placeholder="Menu item name" />
<MenuItemContentEditor Subject=@subject MenuItem="item" WordFile=@document SessionId="SessionId" OnContentUpdated="UpdateMenuItem" />
<div class="card-footer">
<button class="btn btn-default btn-sm mt-2" @onclick="() => AddMenuItem()">Add a new menu item after this one</button>
<button class="btn btn-danger btn-sm mt-2" @onclick="() => RemoveMenuItem(item)">Remove</button>
</div>
}
<div class="card-footer">
<button class="btn btn-default btn-sm mt-2" @onclick="() => AddMenuItem()">Add a new menu item after this one</button>
<button class="btn btn-danger btn-sm mt-2" @onclick="() => RemoveMenuItem(item)">Remove</button>
</div>
}
</RadzenAccordionItem>
</RadzenAccordionItem>
}
}
</Items>
</RadzenAccordion>
}
</Items>
</RadzenAccordion> *@
</div>
@* @foreach (var item in menuItems)
{
@ -121,7 +102,7 @@ else if (ExtractedMenuItems.Any())
</div>
<button class="btn btn-success mt-3" @onclick="SaveMenuItems">Save All</button>
<button class="btn btn-success mt-3" @onclick="() => SaveMenuItems(true)">Save All</button>
}
else if (!string.IsNullOrEmpty(ErrorMessage))
{
@ -137,11 +118,20 @@ else if (!string.IsNullOrEmpty(ErrorMessage))
private bool IsLoading = false;
private string? ErrorMessage;
private bool MenuItemsSaved = false;
ObservableCollection<MenuItem> menuItems;
IList<MenuItem> selectedMenuItems;
private string subject;
private string document;
private bool hasCollection;
private List<MenuItemModel> ExtractedMenuItems = new();
private bool allowReorder = false;
private RadzenDataGrid<MenuItem> dataGrid;
MenuItem draggedItem;
MenuItemModel SelectedMenuItemModel = new("");
void Change(string text)
{
Console.Write($"{text}");
@ -150,7 +140,7 @@ else if (!string.IsNullOrEmpty(ErrorMessage))
protected override async Task OnParametersSetAsync()
{
//get menu items from DB
List<MenuItem> Site = await ContentEditorService.GetMenuItemsBySiteIdAsync(SiteId);
menuItems = new ObservableCollection<MenuItem>((await ContentEditorService.GetMenuItemsBySiteIdAsync(SiteId)).OrderBy(x => x.SortOrder));
var collectionResult = await QDrantService.GetCollectionBySiteIdAsync(SiteId);
if (!string.IsNullOrEmpty(collectionResult))
{
@ -158,13 +148,13 @@ else if (!string.IsNullOrEmpty(ErrorMessage))
hasCollection = true;
Console.Write("Has collection already");
}
if (Site.Count() > 0)
if (menuItems.Count() > 0)
{
foreach (var menuItem in Site)
foreach (var menuItem in menuItems)
{
string content;
MenuItemModel model = new MenuItemModel();
MenuItemModel model = new MenuItemModel("");
//try to get content from qDrant
if (menuItem.QdrantPointId != null)
{
@ -177,8 +167,7 @@ else if (!string.IsNullOrEmpty(ErrorMessage))
}
}
model.Name = menuItem.Name;
model.MenuItem = menuItem;
ExtractedMenuItems.Add(model);
// UpdateMenuItem(model);
}
@ -219,7 +208,7 @@ else if (!string.IsNullOrEmpty(ErrorMessage))
{
var prompt2 = $"Analyze the following text and based on the sections suggest a list of menu items for a website. Do not attach any explanation. Text:\n\n`{document}`.";
var response2 = await ContentEditorService.GetMenuSuggestionsAsync(SessionId, prompt2);
ExtractedMenuItems = response2.Select(name => new MenuItemModel { Name = name }).ToList();
ExtractedMenuItems = response2.Select(name => new MenuItemModel(name)).ToList();
}
// Send the content to ChatGPT
}
@ -244,23 +233,25 @@ else if (!string.IsNullOrEmpty(ErrorMessage))
IsLoading = true;
ErrorMessage = null;
ExtractedMenuItems.Add(new MenuItemModel { Name = "New menu item", Content = "" });
ExtractedMenuItems.Add(new MenuItemModel ("New menu item", "" ));
IsLoading = false;
}
private void UpdateMenuItem(MenuItemModel updatedItem)
{
var item = ExtractedMenuItems!.FirstOrDefault(i => i.Name == updatedItem.Name);
var item = ExtractedMenuItems!.FirstOrDefault(i => i.MenuItem.Id == updatedItem.MenuItem.Id);
if (item != null)
{
//item.MenuItem.
item.Content = updatedItem.Content;
}
}
private async Task SaveMenuItems()
private async Task SaveMenuItems(bool updateVectorDatabase)
{
var result = await ContentEditorService.ProcessMenuItems(SiteId, hasCollection, ExtractedMenuItems, subject, MenuItemsSaved);
//bool valami = updateVectorDatabase;
var result = await ContentEditorService.ProcessMenuItems(SiteId, hasCollection, ExtractedMenuItems, subject, MenuItemsSaved, updateVectorDatabase);
if (result == "OK")
{
MenuItemsSaved = true;
@ -271,4 +262,61 @@ else if (!string.IsNullOrEmpty(ErrorMessage))
//Error
}
}
void RowRender(RowRenderEventArgs<MenuItem> args)
{
if (allowReorder)
{
args.Attributes.Add("title", "Drag row to reorder");
args.Attributes.Add("style", "cursor:grab");
args.Attributes.Add("draggable", "true");
args.Attributes.Add("ondragover", "event.preventDefault();event.target.closest('.rz-data-row').classList.add('my-class')");
args.Attributes.Add("ondragleave", "event.target.closest('.rz-data-row').classList.remove('my-class')");
args.Attributes.Add("ondragstart", EventCallback.Factory.Create<DragEventArgs>(this, () => draggedItem = args.Data));
args.Attributes.Add("ondrop", EventCallback.Factory.Create<DragEventArgs>(this, () =>
{
var draggedIndex = menuItems.IndexOf(draggedItem);
MenuItemModel draggedExtractedMenuItem = ExtractedMenuItems[draggedIndex];
var droppedIndex = menuItems.IndexOf(args.Data);
menuItems.Remove(draggedItem);
menuItems.Insert(draggedIndex <= droppedIndex ? droppedIndex++ : droppedIndex, draggedItem);
ExtractedMenuItems.Remove(draggedExtractedMenuItem);
ExtractedMenuItems.Insert(draggedIndex <= droppedIndex ? droppedIndex++ : droppedIndex, draggedExtractedMenuItem);
foreach (var menuItemToReorder in menuItems)
{
menuItemToReorder.SortOrder = menuItems.IndexOf(menuItemToReorder);
}
foreach (var extractedMenuItemToReorder in ExtractedMenuItems)
{
extractedMenuItemToReorder.MenuItem.SortOrder = ExtractedMenuItems.IndexOf(extractedMenuItemToReorder);
}
JSRuntime.InvokeVoidAsync("eval", $"document.querySelector('.my-class').classList.remove('my-class')");
}));
}
}
void Select(MenuItem menuItem)
{
SelectedMenuItemModel.MenuItem.Name = menuItem.Name;
SelectedMenuItemModel.Content = ExtractedMenuItems.Where(x => x.MenuItem.Name == menuItem.Name).FirstOrDefault().Content;
SelectedMenuItemModel.MenuItem.SortOrder = menuItem.SortOrder;
SelectedMenuItemModel.MenuItem.ShowInMainMenu = menuItem.ShowInMainMenu;
}
void OnRowSelect(MenuItem menuItem)
{
Select(menuItem);
}
async void ToggleReorder()
{
if(allowReorder)
{
await SaveMenuItems(false);
}
allowReorder = !allowReorder;
await InvokeAsync(StateHasChanged);
}
}

View File

@ -2,9 +2,11 @@
@using BLAIzor.Services
@using Newtonsoft.Json
@using BLAIzor.Components.Partials
@using System.Collections.ObjectModel
@inject ContentEditorService ContentEditorService
@inject HtmlSnippetProcessor HtmlSnippetProcessor
@inject QDrantService QDrantService
@inject IJSRuntime JSRuntime
<div>
<label for="subject">Enter the subject of your website:</label>
@ -16,39 +18,68 @@
{
<p>Loading suggestions...</p>
}
else if (menuItems.Any())
else if (extractedMenuItems.Any())
{
<h4>Suggested Menu Items</h4>
<div class="row">
<div class="rz-p-sm-12">
<RadzenAccordion Multiple="true">
<Items>
@foreach (var item in menuItems)
{
<RadzenAccordionItem Text="@item.Name" Icon="account_balance_wallet">
@{
if (MenuItemsSaved)
{
<input @bind="item.Name" class="form-control border-0" placeholder="Menu item name" />
<MenuItemContentEditor Subject=@subject MenuItem="item" OnContentUpdated="UpdateMenuItem" SessionId="SessionId" />
<div class="card-footer">
<button class="btn btn-danger btn-sm mt-2" @onclick="() => RemoveMenuItem(item)">Remove</button>
<button class="btn btn-default btn-sm mt-2" @onclick="() => AddMenuItem()">Add a new menu item after this one</button>
</div>
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Right">
@{
<RadzenButton Click="ToggleReorder">
@(allowReorder ? "Done" : "Reorder")
</RadzenButton>
}
</RadzenStack>
@if (allowReorder)
{
<RadzenDataGrid @ref="dataGrid" TItem="MenuItem" RowSelect=@OnRowSelect AllowFiltering="true" AllowColumnResize="true" AllowAlternatingRows="false" FilterMode="FilterMode.Advanced" AllowSorting="true" PageSize="20" AllowPaging="true" PagerHorizontalAlign="HorizontalAlign.Left" ShowPagingSummary="true"
Data="@menuItems" ColumnWidth="300px" LogicalFilterOperator="LogicalFilterOperator.Or" SelectionMode="DataGridSelectionMode.Single"
@bind-Value=@selectedMenuItems RowRender="@RowRender">
<Columns>
<RadzenDataGridColumn Property="@nameof(MenuItem.SortOrder)" Title="Sort order" Width="30px" />
@* <RadzenDataGridColumn Property="@nameof(MenuItem.Id)" Filterable="false" Title="ID" Frozen="true" Width="55px" TextAlign="TextAlign.Center" /> *@
<RadzenDataGridColumn Property="@nameof(MenuItem.Name)" Title="Name" Frozen="true" Width="130px" />
@* <RadzenDataGridColumn Property="@nameof(MenuItem.PointId)" Title="Point Id" Width="200px" /> *@
<RadzenDataGridColumn Property="@nameof(MenuItem.ShowInMainMenu)" Title="Show in menu" Width="30px" />
</Columns>
</RadzenDataGrid>
}
else
{
<RadzenAccordion Multiple="true">
<Items>
@foreach (var item in extractedMenuItems)
{
<RadzenAccordionItem Text="@item.MenuItem.Name" Icon="account_balance_wallet">
@{
if (MenuItemsSaved)
{
<input @bind="item.MenuItem.Name" class="form-control border-0" placeholder="Menu item name" />
<MenuItemContentEditor Subject=@subject MenuItem="item" OnContentUpdated="UpdateMenuItem" SessionId="SessionId" />
<div class="card-footer">
<button class="btn btn-danger btn-sm mt-2" @onclick="() => RemoveMenuItem(item)">Remove</button>
<button class="btn btn-default btn-sm mt-2" @onclick="() => AddMenuItem()">Add a new menu item after this one</button>
</div>
}
}
}
</RadzenAccordionItem>
</RadzenAccordionItem>
}
}
</Items>
</RadzenAccordion>
</Items>
</RadzenAccordion>
}
</div>
</div>
<button class="btn btn-success mt-3" @onclick="SaveAllContent">Save All</button>
<button class="btn btn-success mt-3" @onclick="() => SaveMenuItems(true)">Save All</button>
}
else if (!string.IsNullOrEmpty(errorMessage))
{
@ -61,15 +92,24 @@ else if (!string.IsNullOrEmpty(errorMessage))
[Parameter]
public string SessionId { get; set; }
private string subject = string.Empty;
private List<MenuItemModel> menuItems = new();
ObservableCollection<MenuItem> menuItems;
IList<MenuItem> selectedMenuItems;
private List<MenuItemModel> extractedMenuItems = new();
private bool MenuItemsSaved = false;
private bool isLoading = false;
private string? errorMessage;
private bool hasCollection = false;
private bool hasCollection = false;
private bool allowReorder = false;
private RadzenDataGrid<MenuItem> dataGrid;
MenuItem draggedItem;
MenuItemModel SelectedMenuItemModel = new("");
protected override async Task OnParametersSetAsync()
{
List<MenuItem> Site = await ContentEditorService.GetMenuItemsBySiteIdAsync(SiteId);
menuItems = new ObservableCollection<MenuItem>((await ContentEditorService.GetMenuItemsBySiteIdAsync(SiteId)).OrderBy(x => x.SortOrder));
var collectionResult = await QDrantService.GetCollectionBySiteIdAsync(SiteId);
if (!string.IsNullOrEmpty(collectionResult))
{
@ -77,13 +117,13 @@ else if (!string.IsNullOrEmpty(errorMessage))
hasCollection = true;
Console.Write("Has collection already");
}
if (Site.Count() > 0)
if (menuItems.Count() > 0)
{
foreach (var menuItem in Site)
foreach (var menuItem in menuItems)
{
string content;
MenuItemModel model = new MenuItemModel();
MenuItemModel model = new MenuItemModel("");
//try to get content from qDrant
if (menuItem.QdrantPointId != null)
{
@ -97,9 +137,9 @@ else if (!string.IsNullOrEmpty(errorMessage))
}
}
model.Name = menuItem.Name;
model.MenuItem = menuItem;
menuItems.Add(model);
extractedMenuItems.Add(model);
// UpdateMenuItem(model);
}
MenuItemsSaved = true;
@ -122,7 +162,7 @@ else if (!string.IsNullOrEmpty(errorMessage))
{
var prompt = $"Suggest a list of menu items for a website about: {subject}. Please do not attach any explanation.";
var response = await ContentEditorService.GetMenuSuggestionsAsync(SessionId, prompt);
menuItems = response.Select(name => new MenuItemModel { Name = name }).ToList();
extractedMenuItems = response.Select(name => new MenuItemModel(name)).ToList();
}
catch (Exception ex)
{
@ -139,31 +179,32 @@ else if (!string.IsNullOrEmpty(errorMessage))
isLoading = true;
errorMessage = null;
menuItems.Add(new());
extractedMenuItems.Add(new("New menu item"));
}
private void RemoveMenuItem(MenuItemModel item)
{
menuItems.Remove(item);
extractedMenuItems.Remove(item);
}
private void UpdateMenuItem(MenuItemModel updatedItem)
{
Console.Write("Updating menu item");
var item = menuItems.FirstOrDefault(i => i.Name == updatedItem.Name);
var item = extractedMenuItems.FirstOrDefault(i => i.MenuItem.Name == updatedItem.MenuItem.Name);
if (item != null)
{
item.Content = updatedItem.Content;
}
else{
else
{
Console.Write("Not found");
}
}
private async Task SaveAllContent()
private async Task SaveMenuItems(bool updateVectorDatabase)
{
var result = await ContentEditorService.ProcessMenuItems(SiteId, hasCollection, menuItems, subject, MenuItemsSaved);
var result = await ContentEditorService.ProcessMenuItems(SiteId, hasCollection, extractedMenuItems, subject, MenuItemsSaved, updateVectorDatabase);
if (result == "OK")
{
MenuItemsSaved = true;
@ -176,4 +217,60 @@ else if (!string.IsNullOrEmpty(errorMessage))
}
}
void RowRender(RowRenderEventArgs<MenuItem> args)
{
if (allowReorder)
{
args.Attributes.Add("title", "Drag row to reorder");
args.Attributes.Add("style", "cursor:grab");
args.Attributes.Add("draggable", "true");
args.Attributes.Add("ondragover", "event.preventDefault();event.target.closest('.rz-data-row').classList.add('my-class')");
args.Attributes.Add("ondragleave", "event.target.closest('.rz-data-row').classList.remove('my-class')");
args.Attributes.Add("ondragstart", EventCallback.Factory.Create<DragEventArgs>(this, () => draggedItem = args.Data));
args.Attributes.Add("ondrop", EventCallback.Factory.Create<DragEventArgs>(this, () =>
{
var draggedIndex = menuItems.IndexOf(draggedItem);
MenuItemModel draggedExtractedMenuItem = extractedMenuItems[draggedIndex];
var droppedIndex = menuItems.IndexOf(args.Data);
menuItems.Remove(draggedItem);
menuItems.Insert(draggedIndex <= droppedIndex ? droppedIndex++ : droppedIndex, draggedItem);
extractedMenuItems.Remove(draggedExtractedMenuItem);
extractedMenuItems.Insert(draggedIndex <= droppedIndex ? droppedIndex++ : droppedIndex, draggedExtractedMenuItem);
foreach (var menuItemToReorder in menuItems)
{
menuItemToReorder.SortOrder = menuItems.IndexOf(menuItemToReorder);
}
foreach (var extractedMenuItemToReorder in extractedMenuItems)
{
extractedMenuItemToReorder.MenuItem.SortOrder = extractedMenuItems.IndexOf(extractedMenuItemToReorder);
}
JSRuntime.InvokeVoidAsync("eval", $"document.querySelector('.my-class').classList.remove('my-class')");
}));
}
}
void Select(MenuItem menuItem)
{
SelectedMenuItemModel.MenuItem.Name = menuItem.Name;
SelectedMenuItemModel.Content = extractedMenuItems.Where(x => x.MenuItem.Name == menuItem.Name).FirstOrDefault().Content;
SelectedMenuItemModel.MenuItem.SortOrder = menuItem.SortOrder;
SelectedMenuItemModel.MenuItem.ShowInMainMenu = menuItem.ShowInMainMenu;
}
void OnRowSelect(MenuItem menuItem)
{
Select(menuItem);
}
async void ToggleReorder()
{
if (allowReorder)
{
await SaveMenuItems(false);
}
allowReorder = !allowReorder;
await InvokeAsync(StateHasChanged);
}
}

View File

@ -35,7 +35,7 @@
[Parameter] public string Subject { get; set; } = string.Empty;
[Parameter] public string WordFile { get; set; } = string.Empty;
[Parameter] public string SessionId { get; set; } = string.Empty;
[Parameter] public MenuItemModel MenuItem { get; set; } = new();
[Parameter] public MenuItemModel MenuItem { get; set; } = new("");
[Parameter] public EventCallback<MenuItemModel> OnContentUpdated { get; set; }
private bool IsLoading = false;
@ -63,7 +63,7 @@
try
{
Console.Write($"Subject: {Subject}");
var prompt = $"Generate website content for a page titled '{MenuItem.Name}' of a '{Subject}' website. Please do not attach any explanation.";
var prompt = $"Generate website content for a page titled '{MenuItem.MenuItem.Name}' of a '{Subject}' website. Please do not attach any explanation.";
GeneratedContent = await ContentEditorService.GetGeneratedContentAsync(SessionId, prompt);
MenuItem.Content = GeneratedContent;
await OnContentUpdated.InvokeAsync(MenuItem);
@ -84,7 +84,7 @@
try
{
Console.Write($"Subject: {Subject}");
var prompt = $"This is the provided text: {WordFile}. Look for the relevant content for a page titled '{MenuItem.Name}' of a '{Subject}' website. Please do not attach any explanation.";
var prompt = $"This is the provided text: {WordFile}. Look for the relevant content for a page titled '{MenuItem.MenuItem.Name}' of a '{Subject}' website. Please do not attach any explanation.";
GeneratedContent = await ContentEditorService.GetGeneratedContentAsync(SessionId, prompt);
MenuItem.Content = GeneratedContent;
await OnContentUpdated.InvokeAsync(MenuItem);

View File

@ -29,7 +29,7 @@
{
<li class="nav-item">
<a class="nav-link active" aria-current="page" @onclick="()=>MenuClicked(menu)">@menu</a>
<a class="nav-link active" aria-current="page" @onclick="()=>MenuClickedAsync(menu)">@menu</a>
</li>
}
}
@ -70,9 +70,10 @@
"Hungarian", "English", "German"
};
public void MenuClicked(string menuName)
public async Task MenuClickedAsync(string menuName)
{
OnMenuClicked?.Invoke(menuName);
await JS.InvokeVoidAsync("collapseNavbar");
}
public void HomeClick()
@ -102,34 +103,7 @@
MenuList = MenuString.Split(",");
}
await base.OnParametersSetAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if(firstRender)
{
// var subdomain = HttpContextAccessor.HttpContext?.Items["Subdomain"]?.ToString();
// var SiteInfo = await _scopedContentService.GetSiteInfoByNameAsync(subdomain);
// if (SiteInfo != null && SiteInfo.IsPublished)
// {
// SiteId = SiteInfo.Id;
// }
// else
// {
// SiteId = 1;
// }
// MenuString = await GetMenuList();
// if (MenuString != null)
// {
// MenuList = MenuString.Split(",");
// }
}
await base.OnAfterRenderAsync(firstRender);
}
}
public void OnLanguageSelected(ChangeEventArgs e)
{
@ -140,19 +114,6 @@
Console.WriteLine($"Language selected: {SelectedLanguage}");
_scopedContentService.SelectedLanguage = SelectedLanguage;
}
}
// private async Task<string> GetMenuList()
// {
// RenderCounter++;
// Console.Write($"\n \n Render:{RenderCounter} \n \n");
// List<MenuItem> menuItems = await _contentEditorService.GetMenuItemsBySiteIdAsync(SiteId);
// string menuList = "";
// foreach (MenuItem item in menuItems)
// {
// menuList += item.Name + ",";
// }
// return menuList;
// }
}
}

View File

@ -1,6 +1,25 @@
<video style="opacity:0.3; z-index: -1" autoplay muted loop id="myVideo" @key="SelectedBrandName">
<source src="@("/video/" + SelectedBrandName + ".mp4")" type="video/mp4">
</video>
<style>
.parent-element-to-video {
overflow: hidden;
width: 120vw;
height: auto;
}
video {
position: fixed;
right: 0;
top: 0;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
</style>
<div class="parent-element-to-video">
<video style="opacity:0.3; z-index: -1" autoplay muted loop id="myVideo" @key="SelectedBrandName">
<source src="@("/video/" + SelectedBrandName + ".mp4")" type="video/mp4">
</video>
</div>
<script>
$(document).ready(function () {

View File

@ -0,0 +1,610 @@
// <auto-generated />
using System;
using BLAIzor.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace BLAIzor.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20250429074005_FixSortOrder")]
partial class FixSortOrder
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BLAIzor.Models.CssTemplate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("CssContent")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("DesignTemplateId")
.HasColumnType("int");
b.Property<DateTime>("LastUpdated")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("DesignTemplateId")
.IsUnique();
b.ToTable("CssTemplates");
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeprecated")
.HasColumnType("bit");
b.Property<bool>("IsPrivate")
.HasColumnType("bit");
b.Property<bool>("IsPublished")
.HasColumnType("bit");
b.Property<string>("QDrandCollectionName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Tags")
.HasColumnType("nvarchar(max)");
b.Property<string>("TemplateName")
.HasColumnType("nvarchar(max)");
b.Property<string>("TemplatePhotoUrl")
.HasColumnType("nvarchar(max)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime2");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("DesignTemplates");
b.HasData(
new
{
Id = 1,
CreatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "The default template",
IsDeprecated = false,
IsPrivate = false,
IsPublished = false,
QDrandCollectionName = "html_snippets",
Status = "Draft",
Tags = "system",
TemplateName = "Default Site",
TemplatePhotoUrl = "/images/default-logo.png",
UserId = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274",
Version = 1
});
});
modelBuilder.Entity("BLAIzor.Models.FormDefinition", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("JsonDefinition")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("SiteInfoId")
.HasColumnType("int");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("SiteInfoId", "Slug")
.IsUnique();
b.ToTable("FormDefinitions");
});
modelBuilder.Entity("BLAIzor.Models.MenuItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PointId")
.HasColumnType("int");
b.Property<Guid?>("QdrantPointId")
.HasColumnType("uniqueidentifier");
b.Property<int>("SiteInfoId")
.HasColumnType("int");
b.Property<int>("SortOrder")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("SiteInfoId");
b.ToTable("MenuItems");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("BrandLogoUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("DefaultColor")
.HasColumnType("nvarchar(max)");
b.Property<string>("DefaultUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("DomainUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsPublished")
.HasColumnType("bit");
b.Property<string>("SiteName")
.HasColumnType("nvarchar(max)");
b.Property<int?>("TemplateId")
.HasColumnType("int");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("TemplateId");
b.HasIndex("UserId");
b.ToTable("SiteInfos");
b.HasData(
new
{
Id = 1,
BrandLogoUrl = "/images/default-logo.png",
DefaultColor = "#FFFFFF",
DefaultUrl = "https://ai.poppixel.cloud",
DomainUrl = "poppixel.cloud",
IsPublished = false,
SiteName = "Default Site",
TemplateId = 1,
UserId = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274"
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
b.HasData(
new
{
Id = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274",
AccessFailedCount = 0,
ConcurrencyStamp = "a2836246-0303-4370-b283-e53a9a3f2813",
Email = "adam.g@aycode.com",
EmailConfirmed = true,
LockoutEnabled = false,
NormalizedEmail = "ADAM.G@AYCODE.COM",
NormalizedUserName = "ADAM.G@AYCODE.COM",
PasswordHash = "AQAAAAIAAYagAAAAEChxKCu+ReGvcZFR/6kPASbpnQdMp1MJuepeRyR4bfHTkUk8SfNAqmckGXvuw+GaGA==",
PhoneNumberConfirmed = false,
SecurityStamp = "7ecf121a-b0e7-4e30-a1f1-299eeaf0a9cc",
TwoFactorEnabled = false,
UserName = "adam.g@aycode.com"
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderKey")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("BLAIzor.Models.CssTemplate", b =>
{
b.HasOne("BLAIzor.Models.DesignTemplate", "DesignTemplate")
.WithOne("CssTemplate")
.HasForeignKey("BLAIzor.Models.CssTemplate", "DesignTemplateId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("DesignTemplate");
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("BLAIzor.Models.FormDefinition", b =>
{
b.HasOne("BLAIzor.Models.SiteInfo", "SiteInfo")
.WithMany("FormDefinitions")
.HasForeignKey("SiteInfoId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("SiteInfo");
});
modelBuilder.Entity("BLAIzor.Models.MenuItem", b =>
{
b.HasOne("BLAIzor.Models.SiteInfo", "SiteInfo")
.WithMany("MenuItems")
.HasForeignKey("SiteInfoId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("SiteInfo");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.HasOne("BLAIzor.Models.DesignTemplate", "Template")
.WithMany("Sites")
.HasForeignKey("TemplateId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Template");
b.Navigation("User");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.Navigation("CssTemplate")
.IsRequired();
b.Navigation("Sites");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.Navigation("FormDefinitions");
b.Navigation("MenuItems");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BLAIzor.Migrations
{
/// <inheritdoc />
public partial class FixSortOrder : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "PointId",
table: "MenuItems",
type: "int",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PointId",
table: "MenuItems");
}
}
}

View File

@ -0,0 +1,610 @@
// <auto-generated />
using System;
using BLAIzor.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace BLAIzor.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20250429121256_AddShowInMainMenu")]
partial class AddShowInMainMenu
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BLAIzor.Models.CssTemplate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("CssContent")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("DesignTemplateId")
.HasColumnType("int");
b.Property<DateTime>("LastUpdated")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("DesignTemplateId")
.IsUnique();
b.ToTable("CssTemplates");
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeprecated")
.HasColumnType("bit");
b.Property<bool>("IsPrivate")
.HasColumnType("bit");
b.Property<bool>("IsPublished")
.HasColumnType("bit");
b.Property<string>("QDrandCollectionName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Tags")
.HasColumnType("nvarchar(max)");
b.Property<string>("TemplateName")
.HasColumnType("nvarchar(max)");
b.Property<string>("TemplatePhotoUrl")
.HasColumnType("nvarchar(max)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime2");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("DesignTemplates");
b.HasData(
new
{
Id = 1,
CreatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "The default template",
IsDeprecated = false,
IsPrivate = false,
IsPublished = false,
QDrandCollectionName = "html_snippets",
Status = "Draft",
Tags = "system",
TemplateName = "Default Site",
TemplatePhotoUrl = "/images/default-logo.png",
UserId = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274",
Version = 1
});
});
modelBuilder.Entity("BLAIzor.Models.FormDefinition", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("JsonDefinition")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("SiteInfoId")
.HasColumnType("int");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("SiteInfoId", "Slug")
.IsUnique();
b.ToTable("FormDefinitions");
});
modelBuilder.Entity("BLAIzor.Models.MenuItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PointId")
.HasColumnType("int");
b.Property<Guid?>("QdrantPointId")
.HasColumnType("uniqueidentifier");
b.Property<int>("SiteInfoId")
.HasColumnType("int");
b.Property<int>("SortOrder")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("SiteInfoId");
b.ToTable("MenuItems");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("BrandLogoUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("DefaultColor")
.HasColumnType("nvarchar(max)");
b.Property<string>("DefaultUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("DomainUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsPublished")
.HasColumnType("bit");
b.Property<string>("SiteName")
.HasColumnType("nvarchar(max)");
b.Property<int?>("TemplateId")
.HasColumnType("int");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("TemplateId");
b.HasIndex("UserId");
b.ToTable("SiteInfos");
b.HasData(
new
{
Id = 1,
BrandLogoUrl = "/images/default-logo.png",
DefaultColor = "#FFFFFF",
DefaultUrl = "https://ai.poppixel.cloud",
DomainUrl = "poppixel.cloud",
IsPublished = false,
SiteName = "Default Site",
TemplateId = 1,
UserId = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274"
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
b.HasData(
new
{
Id = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274",
AccessFailedCount = 0,
ConcurrencyStamp = "a2836246-0303-4370-b283-e53a9a3f2813",
Email = "adam.g@aycode.com",
EmailConfirmed = true,
LockoutEnabled = false,
NormalizedEmail = "ADAM.G@AYCODE.COM",
NormalizedUserName = "ADAM.G@AYCODE.COM",
PasswordHash = "AQAAAAIAAYagAAAAEChxKCu+ReGvcZFR/6kPASbpnQdMp1MJuepeRyR4bfHTkUk8SfNAqmckGXvuw+GaGA==",
PhoneNumberConfirmed = false,
SecurityStamp = "7ecf121a-b0e7-4e30-a1f1-299eeaf0a9cc",
TwoFactorEnabled = false,
UserName = "adam.g@aycode.com"
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderKey")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("BLAIzor.Models.CssTemplate", b =>
{
b.HasOne("BLAIzor.Models.DesignTemplate", "DesignTemplate")
.WithOne("CssTemplate")
.HasForeignKey("BLAIzor.Models.CssTemplate", "DesignTemplateId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("DesignTemplate");
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("BLAIzor.Models.FormDefinition", b =>
{
b.HasOne("BLAIzor.Models.SiteInfo", "SiteInfo")
.WithMany("FormDefinitions")
.HasForeignKey("SiteInfoId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("SiteInfo");
});
modelBuilder.Entity("BLAIzor.Models.MenuItem", b =>
{
b.HasOne("BLAIzor.Models.SiteInfo", "SiteInfo")
.WithMany("MenuItems")
.HasForeignKey("SiteInfoId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("SiteInfo");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.HasOne("BLAIzor.Models.DesignTemplate", "Template")
.WithMany("Sites")
.HasForeignKey("TemplateId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Template");
b.Navigation("User");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.Navigation("CssTemplate")
.IsRequired();
b.Navigation("Sites");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.Navigation("FormDefinitions");
b.Navigation("MenuItems");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BLAIzor.Migrations
{
/// <inheritdoc />
public partial class AddShowInMainMenu : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@ -0,0 +1,613 @@
// <auto-generated />
using System;
using BLAIzor.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace BLAIzor.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20250429121857_FixingWrongMigrations")]
partial class FixingWrongMigrations
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BLAIzor.Models.CssTemplate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("CssContent")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("DesignTemplateId")
.HasColumnType("int");
b.Property<DateTime>("LastUpdated")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("DesignTemplateId")
.IsUnique();
b.ToTable("CssTemplates");
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeprecated")
.HasColumnType("bit");
b.Property<bool>("IsPrivate")
.HasColumnType("bit");
b.Property<bool>("IsPublished")
.HasColumnType("bit");
b.Property<string>("QDrandCollectionName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Tags")
.HasColumnType("nvarchar(max)");
b.Property<string>("TemplateName")
.HasColumnType("nvarchar(max)");
b.Property<string>("TemplatePhotoUrl")
.HasColumnType("nvarchar(max)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime2");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("DesignTemplates");
b.HasData(
new
{
Id = 1,
CreatedAt = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "The default template",
IsDeprecated = false,
IsPrivate = false,
IsPublished = false,
QDrandCollectionName = "html_snippets",
Status = "Draft",
Tags = "system",
TemplateName = "Default Site",
TemplatePhotoUrl = "/images/default-logo.png",
UserId = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274",
Version = 1
});
});
modelBuilder.Entity("BLAIzor.Models.FormDefinition", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("JsonDefinition")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("SiteInfoId")
.HasColumnType("int");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("SiteInfoId", "Slug")
.IsUnique();
b.ToTable("FormDefinitions");
});
modelBuilder.Entity("BLAIzor.Models.MenuItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PointId")
.HasColumnType("int");
b.Property<Guid?>("QdrantPointId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("ShowInMainMenu")
.HasColumnType("bit");
b.Property<int>("SiteInfoId")
.HasColumnType("int");
b.Property<int>("SortOrder")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("SiteInfoId");
b.ToTable("MenuItems");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("BrandLogoUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("DefaultColor")
.HasColumnType("nvarchar(max)");
b.Property<string>("DefaultUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("DomainUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsPublished")
.HasColumnType("bit");
b.Property<string>("SiteName")
.HasColumnType("nvarchar(max)");
b.Property<int?>("TemplateId")
.HasColumnType("int");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("TemplateId");
b.HasIndex("UserId");
b.ToTable("SiteInfos");
b.HasData(
new
{
Id = 1,
BrandLogoUrl = "/images/default-logo.png",
DefaultColor = "#FFFFFF",
DefaultUrl = "https://ai.poppixel.cloud",
DomainUrl = "poppixel.cloud",
IsPublished = false,
SiteName = "Default Site",
TemplateId = 1,
UserId = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274"
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
b.HasData(
new
{
Id = "0988758e-e16c-4c2c-8c1e-efa3ac5f0274",
AccessFailedCount = 0,
ConcurrencyStamp = "a2836246-0303-4370-b283-e53a9a3f2813",
Email = "adam.g@aycode.com",
EmailConfirmed = true,
LockoutEnabled = false,
NormalizedEmail = "ADAM.G@AYCODE.COM",
NormalizedUserName = "ADAM.G@AYCODE.COM",
PasswordHash = "AQAAAAIAAYagAAAAEChxKCu+ReGvcZFR/6kPASbpnQdMp1MJuepeRyR4bfHTkUk8SfNAqmckGXvuw+GaGA==",
PhoneNumberConfirmed = false,
SecurityStamp = "7ecf121a-b0e7-4e30-a1f1-299eeaf0a9cc",
TwoFactorEnabled = false,
UserName = "adam.g@aycode.com"
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderKey")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("BLAIzor.Models.CssTemplate", b =>
{
b.HasOne("BLAIzor.Models.DesignTemplate", "DesignTemplate")
.WithOne("CssTemplate")
.HasForeignKey("BLAIzor.Models.CssTemplate", "DesignTemplateId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("DesignTemplate");
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("BLAIzor.Models.FormDefinition", b =>
{
b.HasOne("BLAIzor.Models.SiteInfo", "SiteInfo")
.WithMany("FormDefinitions")
.HasForeignKey("SiteInfoId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("SiteInfo");
});
modelBuilder.Entity("BLAIzor.Models.MenuItem", b =>
{
b.HasOne("BLAIzor.Models.SiteInfo", "SiteInfo")
.WithMany("MenuItems")
.HasForeignKey("SiteInfoId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("SiteInfo");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.HasOne("BLAIzor.Models.DesignTemplate", "Template")
.WithMany("Sites")
.HasForeignKey("TemplateId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Template");
b.Navigation("User");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("BLAIzor.Models.DesignTemplate", b =>
{
b.Navigation("CssTemplate")
.IsRequired();
b.Navigation("Sites");
});
modelBuilder.Entity("BLAIzor.Models.SiteInfo", b =>
{
b.Navigation("FormDefinitions");
b.Navigation("MenuItems");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace BLAIzor.Migrations
{
/// <inheritdoc />
public partial class FixingWrongMigrations : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "ShowInMainMenu",
table: "MenuItems",
type: "bit",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ShowInMainMenu",
table: "MenuItems");
}
}
}

View File

@ -177,9 +177,15 @@ namespace BLAIzor.Migrations
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("PointId")
.HasColumnType("int");
b.Property<Guid?>("QdrantPointId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("ShowInMainMenu")
.HasColumnType("bit");
b.Property<int>("SiteInfoId")
.HasColumnType("int");

View File

@ -12,8 +12,11 @@ namespace BLAIzor.Models
[Required]
public string Name { get; set; } = string.Empty;
public int PointId { get; set; }
public int SortOrder { get; set; }
public bool ShowInMainMenu { get; set; } = false;
public Guid? QdrantPointId { get; set; }
[ForeignKey("SiteInfo")]

View File

@ -5,7 +5,21 @@ namespace BLAIzor.Models
{
public class MenuItemModel
{
public string Name { get; set; } = string.Empty;
public MenuItem MenuItem { get; set; }
public string Content { get; set; } = string.Empty;
public MenuItemModel(string name)
{
MenuItem = new MenuItem();
MenuItem.Name = name;
}
public MenuItemModel(string name, string content)
{
MenuItem = new MenuItem();
MenuItem.Name = name;
Content = content;
}
}
}

View File

@ -9,6 +9,9 @@ using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.EntityFrameworkCore;
using Radzen;
using Sidio.Sitemap.AspNetCore;
using Sidio.Sitemap.Blazor;
using Sidio.Sitemap.Core.Services;
var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
@ -46,7 +49,9 @@ builder.Services.AddScoped<ScopedContentService>();
builder.Services.AddScoped<QDrantService>();
builder.Services.AddScoped<OpenAIEmbeddingService>();
builder.Services.AddScoped<HtmlSnippetProcessor>();
builder.Services.AddHttpContextAccessor();
builder.Services
.AddHttpContextAccessor()
.AddDefaultSitemapServices<HttpContextBaseUrlProvider>();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
builder.Services.AddScoped<CustomAuthenticationStateProvider>();
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp"));
@ -86,5 +91,5 @@ app.MapRazorPages();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.UseMiddleware<SubdomainMiddleware>();
app.UseSitemap();
app.Run();

View File

@ -222,48 +222,78 @@ namespace BLAIzor.Services
/// <param name="collectionName"></param>
/// <param name="menuList"></param>
/// <returns></returns>
public async Task ProcessContentRequest(string sessionId, string requestedMenuName, int siteId, int templateId, string collectionName, string menuList = "", bool forceUnmodified = false)
public async Task ProcessContentRequest(string sessionId, MenuItem requestedMenu, int siteId, int templateId, string collectionName, string menuList = "", bool forceUnmodified = false)
{
Console.Write($"\n\n SessionId: {sessionId}\n\n");
//string rootpath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot/Documents/" + _contentService.SelectedDocument);
float[] vector = [];
OnStatusChangeReceived?.Invoke(sessionId, "Determining search vectors");
vector = await _openAIEmbeddingService.GenerateEmbeddingAsync(requestedMenuName);
OnStatusChangeReceived?.Invoke(sessionId, "Looking up content in the knowledge database");
var pointId = await _qDrantService.QueryContentAsync(siteId, vector, 1);
string extractedText = "";
if (pointId.Length > 0)
{
foreach (var item in pointId)
if (requestedMenu != null) {
string qDrantData = await _qDrantService.GetContentAsync(siteId, requestedMenu.PointId);
QDrantGetContentPointResult _selectedPoint = new QDrantGetContentPointResult();
if (qDrantData != null)
{
string qDrantData = await _qDrantService.GetContentAsync(siteId, item);
QDrantGetContentPointResult _selectedPoint = new QDrantGetContentPointResult();
if (qDrantData != null)
{
_selectedPoint = JsonConvert.DeserializeObject<QDrantGetContentPointResult>(qDrantData)!;
}
extractedText += _selectedPoint.result.payload.name + ": " + _selectedPoint.result.payload.content + ", ";
_selectedPoint = JsonConvert.DeserializeObject<QDrantGetContentPointResult>(qDrantData)!;
}
extractedText = _selectedPoint.result.payload.name + ": " + _selectedPoint.result.payload.content + ", ";
}
else
{
extractedText = "VECTOR ERROR: ZERO INFORMATION FOUND";
}
string contentJson = await GetContentFromQuery(sessionId,
"Enhance this text if needed, making its style and grammar suitable to be displayed as the content of a webpage",
extractedText,
forceUnmodified);
string contentJson = await GetContentFromQuery(sessionId,
"Enhance this text if needed, making its style and grammar suitable to be displayed as the content of a webpage",
extractedText,
forceUnmodified);
await ProcessContent(sessionId, contentJson, templateId, collectionName);
}
public async Task ProcessContentRequest(string sessionId, string requestedMenu, int siteId, int templateId, string collectionName, string menuList = "", bool forceUnmodified = false)
{
Console.Write($"\n\n SessionId: {sessionId}\n\n");
//string rootpath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot/Documents/" + _contentService.SelectedDocument);
string extractedText = "";
float[] vector = [];
OnStatusChangeReceived?.Invoke(sessionId, "Determining search vectors");
vector = await _openAIEmbeddingService.GenerateEmbeddingAsync(requestedMenu);
OnStatusChangeReceived?.Invoke(sessionId, "Looking up content in the knowledge database");
var pointId = await _qDrantService.QueryContentAsync(siteId, vector, 1);
if (pointId.Length > 0)
{
foreach (var item in pointId)
{
string qDrantData = await _qDrantService.GetContentAsync(siteId, item);
QDrantGetContentPointResult _selectedPoint = new QDrantGetContentPointResult();
if (qDrantData != null)
{
_selectedPoint = JsonConvert.DeserializeObject<QDrantGetContentPointResult>(qDrantData)!;
}
extractedText += _selectedPoint.result.payload.name + ": " + _selectedPoint.result.payload.content + ", ";
}
}
else
{
extractedText = "VECTOR ERROR: ZERO INFORMATION FOUND";
}
string contentJson = await GetContentFromQuery(sessionId,
"Enhance this text if needed, making its style and grammar suitable to be displayed as the content of a webpage",
extractedText,
forceUnmodified);
await ProcessContent(sessionId, contentJson, templateId, collectionName);
}
// Refactored helper methods
@ -441,8 +471,9 @@ namespace BLAIzor.Services
"Step 1: Start with defining above mentioned key topics of the initial document, and making the list of them. " +
"Step 2: After that add the above mentioned relevant image urls list." +
"Step 3: " +
"- Turn the following content into a nice informative webpage content. " +
"- Structure it nicely without leaving out any information. " +
"- Turn the following content into a nice informative webpage content.\r\n " +
"- Start with the page title.\r\n" +
"- Structure it nicely without leaving out any information.\r\n " +
"*** CONTENT START *** {" + extractedText + "} *** CONTENT END ***.\r\n" +
"**Style and Image Handling**:\r\n" +
"- Make sure the json is valid json." +
@ -840,7 +871,7 @@ namespace BLAIzor.Services
{
foreach (var vector in vectorsList)
{
var qDrantresult = await _qDrantService.QuerySnippetAsync(vector, 1, collectionName);
var qDrantresult = await _qDrantService.QuerySnippetAsync(vector, 3, collectionName);
pointIds.Add(qDrantresult);
}
@ -978,7 +1009,8 @@ namespace BLAIzor.Services
"### Using Provided Snippets:\n" +
"- You have been given **multiple HTML snippets**:\n \n " + htmlToUse + ". \n \n **DO NOT merge them into one**.\n" +
"- Use each snippet **as a separate section** inside its own `div.row`.\n" +
"- Maintain their order and **DO NOT omit any snippet**.\n" +
"- Using the snippets is NOT mandatory, use them only if you identified content that fits in a specific snippet.\n" +
//"- Maintain their order and **DO NOT omit any snippet**.\n" +
"- Example structure:\n\n" +
" ```html\n" +
" <div class='container'>\n" +
@ -1018,8 +1050,8 @@ namespace BLAIzor.Services
"### Generating Topic Buttons:\n" +
"Start this section with a title `Related` " +
"- Create a **separate button** for each topic.\n" +
$"- Make sure the topics are in {_scopedContentService.SelectedLanguage}, if not, translate them." +
"- Each button should use `btn btn-primary` and call `callAI('{topicName}')` on click.\n" +
$"- Make sure the topics are in {_scopedContentService.SelectedLanguage}, if not, translate the name of them." +
"- Each button should use `btn btn-primary` and call `callAI('{original_non_translated_topicName}')` on click.\n" +
"- List of topics:\n" +
" " + string.Join(", ", topics) + "\n\n" +
"- Example:\n" +

View File

@ -115,6 +115,8 @@ namespace BLAIzor.Services
existingMenuItem.Name = menuItem.Name;
existingMenuItem.QdrantPointId = menuItem.QdrantPointId;
existingMenuItem.SortOrder = menuItem.SortOrder;
existingMenuItem.ShowInMainMenu = menuItem.ShowInMainMenu;
_context.MenuItems.Update(existingMenuItem);
await _context.SaveChangesAsync();
@ -146,7 +148,7 @@ namespace BLAIzor.Services
}
public async Task<string> ProcessMenuItems(int SiteId, bool hasCollection, List<MenuItemModel> ExtractedMenuItems, string subject, bool menuItemsSaved)
public async Task<string> ProcessMenuItems(int SiteId, bool hasCollection, List<MenuItemModel> ExtractedMenuItems, string subject, bool menuItemsSaved, bool updateVectorDatabase)
{
try
{
@ -163,42 +165,54 @@ namespace BLAIzor.Services
for (int i = 0; i < ExtractedMenuItems.Count(); i++)
{
MenuItem menuItem = new MenuItem();
if (!string.IsNullOrEmpty(ExtractedMenuItems[i].Content))
if (!string.IsNullOrEmpty(ExtractedMenuItems[i].Content)) //if we have content in the menuItem, let's update the vector DB
{
Guid guid = Guid.NewGuid();
WebPageContent content = new WebPageContent();
content.Id = i;
content.UId = guid.ToString();
content.Type = "page";
content.SiteId = SiteId;
content.Name = ExtractedMenuItems[i].Name;
content.Description = $"A section called {ExtractedMenuItems[i].Name} of a website of {subject}";
content.Content = ExtractedMenuItems[i].Content;
content.LastUpdated = DateTime.UtcNow;
if(updateVectorDatabase)
{
Guid guid = Guid.NewGuid();
WebPageContent content = new WebPageContent();
content.Id = i;
content.UId = guid.ToString();
content.Type = "page";
content.SiteId = SiteId;
content.Name = ExtractedMenuItems[i].MenuItem.Name;
content.Description = $"A section called {ExtractedMenuItems[i].MenuItem.Name} of a website of {subject}";
content.Content = ExtractedMenuItems[i].Content;
content.LastUpdated = DateTime.UtcNow;
menuItem.QdrantPointId = guid;
menuItem.QdrantPointId = guid;
await _htmlSnippetProcessor.ProcessAndStoreWebContentAsync(i, content, SiteId);
await _htmlSnippetProcessor.ProcessAndStoreWebContentAsync(i, content, SiteId);
}
else
{
menuItem.QdrantPointId = ExtractedMenuItems[i].MenuItem.QdrantPointId;
}
}
if (!menuItemsSaved)
if (!menuItemsSaved) //menuItems just extracted, no content yet because that can be generated only after menuItems have been saved first
{
menuItem.Name = ExtractedMenuItems[i].Name;
menuItem.Name = ExtractedMenuItems[i].MenuItem.Name;
menuItem.SortOrder = i;
menuItem.SiteInfoId = SiteId;
menuItem.ShowInMainMenu = true;
await AddMenuItemAsync(menuItem);
}
else
else //menuItems available already
{
var menuItems = await GetMenuItemsBySiteIdAsync(SiteId);
var thisItem = menuItems.FirstOrDefault(x => x.SiteInfoId == SiteId && x.Name == ExtractedMenuItems[i].Name);
var thisItem = menuItems.FirstOrDefault(x => x.SiteInfoId == SiteId && x.Id == ExtractedMenuItems[i].MenuItem.Id);
if (thisItem == null)
{
//new menu item?
await AddMenuItemAsync(menuItem);
}
else
{
thisItem.QdrantPointId = menuItem.QdrantPointId;
thisItem.SortOrder = ExtractedMenuItems[i].MenuItem.SortOrder;
thisItem.ShowInMainMenu = ExtractedMenuItems[i].MenuItem.ShowInMainMenu;
await UpdateMenuItemAsync(thisItem);
}
}

View File

@ -25,28 +25,32 @@ namespace BLAIzor.Services
private string GetApiKey() =>
_configuration?.GetSection("OpenAI")?.GetValue<string>("ApiKey") ?? string.Empty;
private string GetModelName() =>
_configuration?.GetSection("OpenAI")?.GetValue<string>("Model") ?? string.Empty;
public void RegisterCallback(Action<string, string> callback, Action<string> onCompleteCallback, Action<string, string> onErrorCallback)
{
_callback = callback;
_onComplete = onCompleteCallback;
_onError = onErrorCallback;
}
public async Task<string> GetSimpleChatGPTResponse(string sessionId, string systemMessage, string userMessage, string? assistantMessage = null, int mode = -1)
{
string modelName = "";
if (mode >= 0)
{
if (mode == 0)
{
modelName = "gpt-4o";
}
}
else
{
modelName = "gpt-4o-mini";
}
string modelName = GetModelName();
//string modelName = "";
//if (mode >= 0)
//{
// if (mode == 0)
// {
// modelName = "gpt-4o";
// }
//}
//else
//{
// modelName = "gpt-4o-mini";
//}
var requestBody = new ChatGPTRequest
{
@ -89,18 +93,19 @@ namespace BLAIzor.Services
public async Task<string> GetSimpleChatGPTResponseNoSession(string systemMessage, string userMessage, string? assistantMessage = null, int mode = -1)
{
string modelName = "";
if (mode >= 0)
{
if (mode == 0)
{
modelName = "gpt-4o";
}
}
else
{
modelName = "gpt-4o-mini";
}
string modelName = GetModelName();
//string modelName = "";
//if (mode >= 0)
//{
// if (mode == 0)
// {
// modelName = "gpt-4o";
// }
//}
//else
//{
// modelName = "gpt-4o-mini";
//}
var requestBody = new ChatGPTRequest
{
@ -143,37 +148,38 @@ namespace BLAIzor.Services
public async Task<string> GetChatGPTStreamedResponse(string sessionId, string systemMessage, string userMessage, string? assistantMessage = null, int mode = -1)
{
string modelName = "";
if(mode >= 0)
{
if(mode == 0)
{
modelName = "gpt-4o";
}
}
else
{
modelName = "gpt-4o-mini";
}
string modelName = GetModelName();
//string modelName = "";
//if(mode >= 0)
//{
// if(mode == 0)
// {
// modelName = "gpt-4o";
// }
//}
//else
//{
// modelName = "gpt-4o-mini";
//}
var requestBody = new ChatGPTRequest
{
Model = modelName,
Temperature = 0.2,
Messages = assistantMessage == null
? new[]
{
var requestBody = new ChatGPTRequest
{
Model = modelName,
Temperature = 0.2,
Messages = assistantMessage == null
? new[]
{
new Message { Role = "system", Content = systemMessage },
new Message { Role = "user", Content = userMessage }
}
: new[]
{
}
: new[]
{
new Message { Role = "system", Content = systemMessage },
new Message { Role = "assistant", Content = assistantMessage },
new Message { Role = "user", Content = userMessage }
},
Stream = true
};
},
Stream = true
};
var requestJson = JsonSerializer.Serialize(requestBody, new JsonSerializerOptions
{

View File

@ -31,11 +31,16 @@
"ApiKey": "csk-3pwm3pjjrpcmmt6rm6k8f43n6rhh3h5pjn6jn9m9j4pyevrp",
"Model": "llama-3.3-70b"
//"Model": "llama-4-scout-17b-16e-instruct"
//"Model": "qwen-3-32b"
//"Model": "llama3.1-8b"
},
"OpenAI": {
//"CredentialsPath": "D:\\GOOGLECREDENTIALS\\client_secret_359861037120-m3mjvr3kg51i2c2qb38dav62uuqoqs5k.apps.googleusercontent.com.json"
"ApiKey": "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"
"ApiKey": "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",
//"ApiKey": "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" //VG3Law
//"Model": "gpt-4.1-mini"
//"Model": "gpt-4o-mini"
"Model": "gpt-4.1-nano"
},
"QDrant": {
//"CredentialsPath": "D:\\GOOGLECREDENTIALS\\client_secret_359861037120-m3mjvr3kg51i2c2qb38dav62uuqoqs5k.apps.googleusercontent.com.json"

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3) !important;
backdrop-filter: blur(2px) !important;
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3) !important;
backdrop-filter: blur(2px) !important;
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -56,7 +56,7 @@ h1 {
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.986rem;
font-size: 2.488rem;
}
h2 {
@ -66,7 +66,7 @@ h2 {
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.488rem;
font-size: 2.288rem;
}
h3 {
@ -82,6 +82,15 @@ h3 {
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
@ -97,4 +106,39 @@ p {
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}

View File

@ -1,23 +1,11 @@
/*@import url('https://fonts.googleapis.com/css2?family=Quicksand&display=swap');*/
@import url('https://fonts.googleapis.com/css?family=Comfortaa:400,700,300');
@import url('https://fonts.googleapis.com/css2?family=Quicksand&display=swap');
.rz-html-editor-content {
background-color: #00000033;
}
.form-group {
margin-bottom: 5px;
}
/*search*/
p {
font-size: large;
/*text-align: justify;*/
}
li {
list-style: none;
p {
font-size: x-large;
}
label {
@ -31,22 +19,17 @@ label {
/* width: 98%; */
font-weight: bold;
border-radius: 20px;
/*min-height: 50px;*/
min-height: 50px;
transition: all 0.2s ease;
padding: 10px;
margin-top: 10px;
}
.btn:hover{
background: #e5b984;
color:#000000;
}
.menubtn {
background: rgba(255, 255, 255, 0.5);
border: 0;
color: #000000;
width: fit-content;
/* width: 98%; */
font-weight: bold;
border-radius: 20px;
height: 40px;
@ -243,6 +226,14 @@ input[type=search]::-webkit-search-cancel-button {
cursor: pointer;
}
.btn:hover {
background: #441CFF;
}
.btn:focus {
background: #441CFF;
outline: 0;
}
/*card design*/
/*bg*/
@ -253,14 +244,14 @@ input[type=search]::-webkit-search-cancel-button {
}
body {
font-family: 'Comfortaa', 'Arial Narrow', Arial, sans-serif;
/*font-family: 'Quicksand', sans-serif;*/
font-family: 'Quicksand', sans-serif;
margin: 0;
min-height: 100vh;
background-color: #e493d0;
background-image: radial-gradient(closest-side, rgba(235, 105, 78, 1), rgba(235, 105, 78, 0)), radial-gradient(closest-side, rgba(243, 11, 164, 1), rgba(243, 11, 164, 0)), radial-gradient(closest-side, rgba(254, 234, 131, 1), rgba(254, 234, 131, 0)), radial-gradient(closest-side, rgba(170, 142, 245, 1), rgba(170, 142, 245, 0)), radial-gradient(closest-side, rgba(248, 192, 147, 1), rgba(248, 192, 147, 0));
background-size: 130vmax 130vmax, 80vmax 80vmax, 90vmax 90vmax, 110vmax 110vmax, 90vmax 90vmax;
background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax;
background-color: #e6e6e6;
/*background-image: radial-gradient(closest-side, rgba(235, 105, 78, 1), rgba(235, 105, 78, 0)), radial-gradient(closest-side, rgba(243, 11, 164, 1), rgba(243, 11, 164, 0)), radial-gradient(closest-side, rgba(254, 234, 131, 1), rgba(254, 234, 131, 0)), radial-gradient(closest-side, rgba(170, 142, 245, 1), rgba(170, 142, 245, 0)), radial-gradient(closest-side, rgba(248, 192, 147, 1), rgba(248, 192, 147, 0));*/
/*background-size: 130vmax 130vmax, 80vmax 80vmax, 90vmax 90vmax, 110vmax 110vmax, 90vmax 90vmax;*/
/*background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax;*/
background-repeat: no-repeat;
/*animation: 10s movement linear infinite;*/
}
@ -320,9 +311,9 @@ body {
background-color: rgba(255, 255, 255, 0.3);
backdrop-filter: blur(20px);
padding: 10px;
border-radius: 25px !important;
border-radius: 10px;
border-width: 0px;
height: unset !important;
height: unset !important;
}
.mytextarea:active {
@ -344,6 +335,7 @@ body {
.navbar-brand {
font-size: 1.7rem;
color: #000;
}
.form-select {
@ -370,10 +362,14 @@ body {
.form-control {
background-color: rgba(255,255,255,0.4);
border-radius: 25px;
border-radius: 5px;
height: 50px;
}
.form-control::placholder {
color: #fff;
}
.contactform-close-overlay {
position: relative;
height: 10vh;
@ -426,11 +422,6 @@ body {
min-width: 100%;
min-height: 100%;
}
.form-select {
display: unset !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
@ -438,7 +429,6 @@ body {
justify-content: center;*/
text-align: center !important;
align-content: center;
overflow-y: scroll;
}
.navbar-collapse .nav-link {
@ -447,12 +437,12 @@ body {
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 1px solid gray;
border-bottom: 0px solid white;
padding: 0.2em 4em;
}
.navbar {
background-color: #ffffff;
background-color: #fff;
color: #000;
}
@ -460,10 +450,6 @@ body {
color: #000;
}
.voicebutton {
width: 42.5px;
}
.content {
top: 60px;
}

View File

@ -483,4 +483,8 @@ body {
.content {
top: 60px;
}
.row {
margin-bottom: 10px;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
margin: 5px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
margin: 5px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
margin: 5px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -483,4 +483,8 @@ body {
.content {
top: 60px;
}
.row {
margin-bottom: 10px;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3) !important;
backdrop-filter: blur(2px) !important;
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3) !important;
backdrop-filter: blur(2px) !important;
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3) !important;
backdrop-filter: blur(2px) !important;
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -1,5 +1,10 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
@ -56,7 +61,7 @@ h1 {
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.986rem;
font-size: 2.488rem;
}
h2 {
@ -66,7 +71,7 @@ h2 {
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.488rem;
font-size: 2.288rem;
}
h3 {
@ -82,6 +87,15 @@ h3 {
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
@ -93,8 +107,49 @@ p {
color: #fff;
background-color: #086262;
border: 0px;
margin: 5px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

View File

@ -1,486 +0,0 @@
/*@import url('https://fonts.googleapis.com/css2?family=Quicksand&display=swap');
@import url('https://fonts.googleapis.com/css?family=Comfortaa:400,700,300');*/
/*search*/
p {
font-size: x-large;
}
li {
list-style: none;
}
label {
color: #000;
/* display: none; */
}
.btn {
background: rgba(255, 255, 255, 0.5);
border: 0;
color: #000000;
width: fit-content;
font-weight: bold;
transition: all 0.2s ease;
margin: 15px;
}
.voicebutton {
border-radius: 50% !important;
padding: 10px !important;
width: 40px;
height:40px;
}
.menubtn {
background: rgba(255, 255, 255, 0.5);
border: 0;
color: #000000;
/* width: 98%; */
font-weight: bold;
border-radius: 20px;
height: 40px;
transition: all 0.2s ease;
padding: 10px;
margin: 10px;
}
.btn:active {
background: rgba(255, 255, 255, 1);
}
.btn:hover {
background: rgba(255, 255, 255, 0.8);
}
img {
border-radius: 20px !important;
}
input.search_bar{
border: none;
outline: none;
width: 75px;
border-radius: 55px;
margin: 0 auto;
font-size: 1.3em;
color: #0d2840;
padding: 15px 30px 15px 45px;
transition: all .3s cubic-bezier(0,0,.5,1.5);
box-shadow: 0 3px 10px -2px rgba(0,0,0,.1);
background: rgba(255, 255, 255, 0.3) url(https://i.imgur.com/seveWIw.png) no-repeat center center;
}
input.search_bar:focus{
width: 100%;
background-position: calc(100% - 35px) center
}
/*Removes default x in search fields (webkit only i guess)*/
input[type=search]::-webkit-search-cancel-button {
-webkit-appearance: none;
}
/*Changes the color of the placeholder*/
::-webkit-input-placeholder {
color: #0d2840;
opacity: .5;
}
:-moz-placeholder {
color: #0d2840;
opacity: .5;
}
::-moz-placeholder {
color: #0d2840;
opacity: .5;
}
:-ms-input-placeholder {
color: #0d2840;
opacity: .5;
}
/*search*/
/*Search2*/
.searchBox {
width: 60px;
background: rgba(255, 255, 255, 0.3);
height: 60px;
border-radius: 40px;
padding: 10px;
margin: 0 auto;
transition: 0.8s;
}
.searchInput:active > .searchBox{
width:100%
}
.searchInput:focus > .searchBox {
width: 100%
}
.searchInput::placeholder {
color:#fff;
}
.searchBox:hover {
width: 100%;
}
.searchBox:hover > .searchInput {
width: calc(100% - 60px);
padding: 0 6px;
}
.searchBox:hover > .searchButton {
background: white;
color: #2f3640;
}
.searchButton {
color: white;
float: right;
width: 40px;
height: 40px;
border-radius: 50px;
background-color: #e493d0;
background-image: radial-gradient(closest-side, rgba(235, 105, 78, 1), rgba(235, 105, 78, 0)), radial-gradient(closest-side, rgba(243, 11, 164, 1), rgba(243, 11, 164, 0)), radial-gradient(closest-side, rgba(254, 234, 131, 1), rgba(254, 234, 131, 0)), radial-gradient(closest-side, rgba(170, 142, 245, 1), rgba(170, 142, 245, 0)), radial-gradient(closest-side, rgba(248, 192, 147, 1), rgba(248, 192, 147, 0));
background-size: 130vmax 130vmax, 80vmax 80vmax, 90vmax 90vmax, 110vmax 110vmax, 90vmax 90vmax;
background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax;
background-repeat: no-repeat;
animation: 10s movement linear infinite;
display: flex;
justify-content: center;
align-items: center;
}
.searchInput {
border: none;
background: none;
outline: none;
font-size: 1.3em !important;
color: #0d2840 !important;
float: left;
padding: 0;
color: white;
font-size: 16px;
transition: 0.4s;
line-height: 40px;
width: 0px;
}
/*Search2*/
.event {
border-radius: 20px !important;
background-color: rgba(255, 255, 255, 0.2) !important;
backdrop-filter: blur(20px);
border: 0;
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.06), 0 2px 4px rgba(0, 0, 0, 0.07);
transition: all 0.15s ease;
}
/*card design*/
.card {
border-radius: 20px !important;
overflow: hidden;
background-color: rgba(255, 255, 255, 0.2) !important;
backdrop-filter: blur(20px);
border: 0;
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.06), 0 2px 4px rgba(0, 0, 0, 0.07);
transition: all 0.15s ease;
}
.card:hover {
box-shadow: 0 6px 30px rgba(0, 0, 0, 0.1), 0 10px 8px rgba(0, 0, 0, 0.015);
}
.card-body .card-title {
font-family: 'Lato', sans-serif;
font-weight: 700;
letter-spacing: 0.3px;
font-size: 24px;
color: #121212;
}
.card-text {
font-family: 'Lato', sans-serif;
font-weight: 400;
font-size: 15px;
letter-spacing: 0.3px;
color: #4E4E4E;
}
.card .container {
width: 88%;
/*background: #F0EEF8;*/
border-radius: 30px;
/*height: 140px;*/
display: flex;
align-items: center;
justify-content: center;
}
.container:hover > img {
transform: scale(1.2);
}
.container img {
/*padding: 75px;*/
/*margin-top: -40px;
margin-bottom: -40px;*/
transition: 0.4s ease;
cursor: pointer;
}
.btn:hover {
background-color: #e493d0;
background-image: radial-gradient(closest-side, rgba(235, 105, 78, 1), rgba(235, 105, 78, 0)), radial-gradient(closest-side, rgba(243, 11, 164, 1), rgba(243, 11, 164, 0)), radial-gradient(closest-side, rgba(254, 234, 131, 1), rgba(254, 234, 131, 0)), radial-gradient(closest-side, rgba(170, 142, 245, 1), rgba(170, 142, 245, 0)), radial-gradient(closest-side, rgba(248, 192, 147, 1), rgba(248, 192, 147, 0));
background-size: 130vmax 130vmax, 80vmax 80vmax, 90vmax 90vmax, 110vmax 110vmax, 90vmax 90vmax;
background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax;
background-repeat: no-repeat;
animation: 10s movement linear infinite;
}
.btn:focus {
background-color: #e493d0;
background-image: radial-gradient(closest-side, rgba(235, 105, 78, 1), rgba(235, 105, 78, 0)), radial-gradient(closest-side, rgba(243, 11, 164, 1), rgba(243, 11, 164, 0)), radial-gradient(closest-side, rgba(254, 234, 131, 1), rgba(254, 234, 131, 0)), radial-gradient(closest-side, rgba(170, 142, 245, 1), rgba(170, 142, 245, 0)), radial-gradient(closest-side, rgba(248, 192, 147, 1), rgba(248, 192, 147, 0));
background-size: 130vmax 130vmax, 80vmax 80vmax, 90vmax 90vmax, 110vmax 110vmax, 90vmax 90vmax;
background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax;
background-repeat: no-repeat;
animation: 10s movement linear infinite;
}
/*card design*/
/*bg*/
:root {
font-size: 15px;
}
body {
/*font-family: 'Comfortaa', 'Arial Narrow', Arial, sans-serif;*/
/*font-family: 'Quicksand', sans-serif;*/
color: #fff !important;
margin: 0;
min-height: 100vh;
background-color: #000;
/*background-image: radial-gradient(closest-side, rgba(235, 105, 78, 1), rgba(235, 105, 78, 0)), radial-gradient(closest-side, rgba(243, 11, 164, 1), rgba(243, 11, 164, 0)), radial-gradient(closest-side, rgba(254, 234, 131, 1), rgba(254, 234, 131, 0)), radial-gradient(closest-side, rgba(170, 142, 245, 1), rgba(170, 142, 245, 0)), radial-gradient(closest-side, rgba(248, 192, 147, 1), rgba(248, 192, 147, 0));*/
/*background-size: 130vmax 130vmax, 80vmax 80vmax, 90vmax 90vmax, 110vmax 110vmax, 90vmax 90vmax;*/
/*background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax;*/
background-repeat: no-repeat;
/*animation: 10s movement linear infinite;*/
}
body::after {
content: '';
display: block;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.myspan {
position: relative;
z-index: 10;
display: flex;
min-height: 100vh;
width: 100%;
justify-content: center;
align-items: center;
font-size: 5rem;
color: transparent;
text-shadow: 0px 0px 1px rgba(255, 255, 255, .6), 0px 4px 4px rgba(0, 0, 0, .05);
letter-spacing: .2rem;
}
@keyframes movement {
0%, 100% {
background-size: 130vmax 130vmax, 80vmax 80vmax, 90vmax 90vmax, 110vmax 110vmax, 90vmax 90vmax;
background-position: -80vmax -80vmax, 60vmax -30vmax, 10vmax 10vmax, -30vmax -10vmax, 50vmax 50vmax;
}
25% {
background-size: 100vmax 100vmax, 90vmax 90vmax, 100vmax 100vmax, 90vmax 90vmax, 60vmax 60vmax;
background-position: -60vmax -90vmax, 50vmax -40vmax, 0vmax -20vmax, -40vmax -20vmax, 40vmax 60vmax;
}
50% {
background-size: 80vmax 80vmax, 110vmax 110vmax, 80vmax 80vmax, 60vmax 60vmax, 80vmax 80vmax;
background-position: -50vmax -70vmax, 40vmax -30vmax, 10vmax 0vmax, 20vmax 10vmax, 30vmax 70vmax;
}
75% {
background-size: 90vmax 90vmax, 90vmax 90vmax, 100vmax 100vmax, 90vmax 90vmax, 70vmax 70vmax;
background-position: -50vmax -40vmax, 50vmax -30vmax, 20vmax 0vmax, -10vmax 10vmax, 40vmax 60vmax;
}
}
/*bg*/
.mytextarea {
background-color: rgba(255, 255, 255, 0.3);
backdrop-filter: blur(20px);
padding: 10px;
border-radius: 10px;
border-width: 0px;
height: unset !important;
}
.mytextarea:active {
border-width: 0px;
}
.mytextarea:focus-visible {
background-color: rgba(255, 255, 255, 0.5);
border-width: 0px !important;
outline: -webkit-focus-ring-color auto 0px;
outline-color: transparent;
}
.navbar-toggler {
color: #fff;
}
.navbar-brand {
font-size: 1.7rem;
color:#fff;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.form-select > option {
background-color: rgba(255, 255, 255, 0.2)
}
.contactform-overlay {
position: fixed;
z-index: 100;
height: 100vh;
width: 100%;
padding: 100px;
top: 0px;
left: 0px;
/* padding-top: 10vh; */
backdrop-filter: blur(20px);
/* background-color: rgba(1, 1, 1, .4); */
}
.form-control {
background-color: rgba(255,255,255,0.4);
border-radius: 5px;
height: 50px;
}
.form-control::placeholder {
color:#fff;
}
.contactform-close-overlay {
position: relative;
height: 10vh;
}
.contactform-popup-content {
height: 80vh;
margin: 0px;
padding: 0px;
}
.contactform-popup-close {
position: relative;
height: 10vh;
z-index: 80;
}
.calendly-overlay {
position: absolute;
z-index: 100;
height: 100vh;
width: 100%;
top: 0px;
/* padding-top: 10vh; */
backdrop-filter: blur(20px);
/* background-color: rgba(1, 1, 1, .4); */
}
.calendly-close-overlay {
position: relative;
height: 10vh;
}
.calendly-popup-content {
height: 80vh;
margin: 0px;
padding: 0px;
}
.calendly-popup-close {
position: relative;
height: 10vh;
z-index: 80;
}
#myVideo {
position: fixed;
right: 0;
bottom: 0;
min-width: 100%;
min-height: 100%;
opacity: 0.2;
}
.table {
color: #fff !important;
padding-top: 10px;
padding-bottom: 10px;
background-color: transparent;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.5em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 4em;
}
.navbar {
background-color: #040206;
color: #fff;
}
.nav-link {
color: #fff !important;
}
.content {
top: 60px;
}

View File

@ -1,5 +1,10 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
@ -56,7 +61,7 @@ h1 {
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.986rem;
font-size: 2.488rem;
}
h2 {
@ -66,7 +71,7 @@ h2 {
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.488rem;
font-size: 2.288rem;
}
h3 {
@ -82,6 +87,15 @@ h3 {
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
@ -97,4 +111,44 @@ p {
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}

View File

@ -483,4 +483,8 @@ body {
.content {
top: 60px;
}
.row {
margin-bottom: 10px;
}

View File

@ -1,5 +1,10 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
@ -56,7 +61,7 @@ h1 {
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.986rem;
font-size: 2.488rem;
}
h2 {
@ -66,7 +71,7 @@ h2 {
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.488rem;
font-size: 2.288rem;
}
h3 {
@ -82,6 +87,15 @@ h3 {
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
@ -97,4 +111,44 @@ p {
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}

View File

@ -483,4 +483,8 @@ body {
.content {
top: 60px;
}
.row {
margin-bottom: 10px;
}

View File

@ -0,0 +1,160 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
.card {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.table {
color: #f2d8bb !important;
}
.navbar-collapse {
height: 100vh;
/*display: flex;
align-items: center;
justify-content: center;*/
text-align: center !important;
align-content: center;
}
.navbar-collapse .nav-link {
font-size: 1.4em;
letter-spacing: 2px;
}
.navbar-collapse .nav-item:not(:last-child) {
border-bottom: 0px solid white;
padding: 0.2em 1em;
}
.navbar {
background-color: #022c28;
color: #d0eae9;
}
.nav-link {
color: #d0eae9 !important;
}
.content {
top: 60px;
}
body {
/*background-image: url('/uploads/0988758e-e16c-4c2c-8c1e-efa3ac5f0274/images/ribi1_brighter.png') !important;*/
background-color: #022c28;
background-attachment: fixed;
background-position: center;
background-size: cover;
color: aqua;
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 300;
font-style: normal;
}
h1 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 700;
font-style: bold;
padding-top: 30px;
padding-bottom: 10px;
font-size: 2.488rem;
}
h2 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
padding-top: 15px;
padding-bottom: 10px;
font-size: 2.288rem;
}
h3 {
font-family: "Montserrat", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
padding-top: 10px;
padding-bottom: 10px;
font-size: 2.074rem;
}
p {
color: #fff;
font-size: x-large;
text-align: justify;
text-justify: auto;
}
li {
color: #fff;
font-size: large;
text-align: center;
text-justify: auto;
}
.btn-primary {
color: #d0eae9;
background-color: #014d4e;
border: 0px;
margin: 5px;
}
.btn-primary:hover {
color: #fff;
background-color: #086262;
border: 0px;
}
.row {
padding-bottom: 30px;
}
.searchInput::placeholder {
color:#d0eae9;
}
#myVideo {
position: fixed;
right: 0;
top: -100px;
min-width: 100%;
min-height: 100%;
transform: translateX(calc((100% - 100vw) / 2));
}
.img-fluid {
max-height: 50vh;
width: auto;
border-radius: 5px;
}
.col {
align-items: center;
display: flex;
}
.form-select {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
display: unset !important;
color: #fff;
}
.list-group-item {
background-color: rgba(255,255,255,0.3);
backdrop-filter: blur(2px);
}
.bg-light {
background-color: rgba(255,255,255,0.3) !important;
backdrop-filter: blur(2px) !important;
}
.text-primary {
--bs-text-opacity: 1;
color: aqua;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

Binary file not shown.

85
wwwroot/vjs.html Normal file
View File

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<!-- Add this where you want AI responses to appear -->
<div id="aiResponseContainer" class="container my-4"></div>
<!-- Sticky Input Area -->
<style>
#aiStickyInputArea {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 12px;
background: #f8f9fa;
border-top: 1px solid #ccc;
display: flex;
z-index: 9999;
box-shadow: 0 -2px 5px rgba(0,0,0,0.05);
}
#aiUserInput {
flex: 1;
border: 1px solid #ced4da;
padding: 10px;
font-size: 16px;
border-radius: 4px;
margin-right: 8px;
}
#aiSendBtn {
background-color: #0d6efd;
color: white;
border: none;
padding: 10px 16px;
border-radius: 4px;
cursor: pointer;
}
</style>
<div id="aiStickyInputArea">
<input type="text" id="aiUserInput" placeholder="Ask something..." />
<button id="aiSendBtn">Send</button>
</div>
<script>
const input = document.getElementById('aiUserInput');
const sendBtn = document.getElementById('aiSendBtn');
const responseContainer = document.getElementById('aiResponseContainer');
sendBtn.onclick = async () => {
const msg = input.value.trim();
if (!msg) return;
input.value = '';
// Optional: Show loading state
const loadingDiv = document.createElement('div');
loadingDiv.innerHTML = `<div class="text-muted">⏳ Thinking...</div>`;
responseContainer.appendChild(loadingDiv);
responseContainer.scrollIntoView({ behavior: 'smooth', block: 'end' });
try {
const res = await fetch('https://your-backend.com/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: msg })
});
const data = await res.json(); // expecting { response: "<div class='card'>...</div>" }
// Replace loading div with the actual HTML response
loadingDiv.outerHTML = data.response || "<div class='text-danger'>❌ Error: No response from AI.</div>";
} catch (err) {
loadingDiv.outerHTML = "<div class='text-danger'>❌ Failed to contact server.</div>";
}
};
</script>
</body>
</html>