288 lines
11 KiB
Plaintext
288 lines
11 KiB
Plaintext
@using BLAIzor.Models
|
|
@using BLAIzor.Services
|
|
@using Newtonsoft.Json
|
|
@using BLAIzor.Components.Partials
|
|
@using System.Collections.ObjectModel
|
|
@inject ContentEditorService ContentEditorService
|
|
@inject ContentEditorAIService ContentEditorAIService
|
|
@inject HtmlSnippetProcessor HtmlSnippetProcessor
|
|
@inject QDrantService QDrantService
|
|
@inject IJSRuntime JSRuntime
|
|
|
|
<div>
|
|
<label for="subject">Enter the subject of your website:</label>
|
|
<input id="subject" @bind="subject" class="form-control" placeholder="e.g., Web Design Company" />
|
|
<button class="btn btn-primary mt-2" @onclick="GenerateMenuItems">Generate Menu Items</button>
|
|
</div>
|
|
|
|
@if (isLoading)
|
|
{
|
|
<p>Loading suggestions...</p>
|
|
}
|
|
else if (extractedMenuItems.Any())
|
|
{
|
|
<h4>Suggested 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>
|
|
}
|
|
|
|
</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>
|
|
|
|
</div>
|
|
}
|
|
}
|
|
</RadzenAccordionItem>
|
|
|
|
}
|
|
|
|
</Items>
|
|
</RadzenAccordion>
|
|
|
|
}
|
|
</div>
|
|
|
|
</div>
|
|
<button class="btn btn-default btn-sm mt-2" @onclick="() => AddMenuItem()">Add a new menu item after this one</button>
|
|
|
|
<button class="btn btn-success mt-3" @onclick="() => SaveMenuItems(true)">Save All</button>
|
|
}
|
|
else if (!string.IsNullOrEmpty(errorMessage))
|
|
{
|
|
<p class="text-danger">@errorMessage</p>
|
|
}
|
|
|
|
@code {
|
|
[Parameter]
|
|
public int SiteId { get; set; }
|
|
[Parameter]
|
|
public string SessionId { get; set; }
|
|
private string subject = string.Empty;
|
|
|
|
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 allowReorder = false;
|
|
private RadzenDataGrid<MenuItem> dataGrid;
|
|
MenuItem draggedItem;
|
|
MenuItemModel SelectedMenuItemModel = new("");
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
menuItems = new ObservableCollection<MenuItem>((await ContentEditorService.GetMenuItemsBySiteIdAsync(SiteId)).OrderBy(x => x.SortOrder));
|
|
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)
|
|
{
|
|
|
|
List<WebPageContent> content;
|
|
MenuItemModel model = new MenuItemModel("");
|
|
//try to get content from qDrant
|
|
if (menuItem.ContentGroupId != null && menuItem.ContentItemId != null) ////FIXXXXXXX
|
|
{
|
|
ContentItem contentItem = await ContentEditorService.GetContentItemByIdAsync((int)menuItem.ContentItemId);
|
|
|
|
/* content = await QDrantService.GetPointFromQdrantAsyncByPointId(SiteId, contentItem.Chunks); */
|
|
//var selectedPoint = JsonConvert.DeserializeObject<QDrantGetContentPointResult>(content)!;
|
|
if (contentItem != null)
|
|
{
|
|
foreach (var vector in contentItem.Chunks)
|
|
{
|
|
//get vectors to compare
|
|
}
|
|
model.Content = contentItem.Content;
|
|
model.ContentDescription = contentItem.Description;
|
|
}
|
|
|
|
}
|
|
model.MenuItem = menuItem;
|
|
extractedMenuItems.Add(model);
|
|
// UpdateMenuItem(model);
|
|
}
|
|
MenuItemsSaved = true;
|
|
}
|
|
//get menu content from QDrant for each menu item
|
|
}
|
|
|
|
private async Task GenerateMenuItems()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(subject))
|
|
{
|
|
errorMessage = "Please enter a subject.";
|
|
return;
|
|
}
|
|
|
|
isLoading = true;
|
|
errorMessage = null;
|
|
|
|
try
|
|
{
|
|
var prompt = $"Suggest a list of menu items for a website about: {subject}. Please do not attach any explanation.";
|
|
var response = await ContentEditorAIService.GetMenuSuggestionsAsync(SessionId, prompt);
|
|
var valami = response.Split('\n', StringSplitOptions.RemoveEmptyEntries)
|
|
.Select(line => line.Trim('-').Trim())
|
|
.ToList() ?? new List<string>();
|
|
extractedMenuItems = valami.Select(name => new MenuItemModel(name)).ToList();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = "An error occurred while generating menu items.";
|
|
}
|
|
finally
|
|
{
|
|
isLoading = false;
|
|
}
|
|
}
|
|
|
|
private async Task AddMenuItem()
|
|
{
|
|
|
|
isLoading = true;
|
|
errorMessage = null;
|
|
var newItem = new MenuItemModel("New menu item", "");
|
|
//TODO Fix
|
|
extractedMenuItems.Add(newItem);
|
|
isLoading = false;
|
|
|
|
}
|
|
|
|
private void RemoveMenuItem(MenuItemModel item)
|
|
{
|
|
extractedMenuItems.Remove(item);
|
|
}
|
|
|
|
private void UpdateMenuItem(MenuItemModel updatedItem)
|
|
{
|
|
Console.Write("Updating menu item");
|
|
var item = extractedMenuItems.FirstOrDefault(i => i.MenuItem.Name == updatedItem.MenuItem.Name);
|
|
if (item != null)
|
|
{
|
|
item.Content = updatedItem.Content;
|
|
}
|
|
else
|
|
{
|
|
Console.Write("Not found");
|
|
}
|
|
}
|
|
|
|
private async Task SaveMenuItems(bool updateVectorDatabase)
|
|
{
|
|
var result = await ContentEditorAIService.ProcessMenuItems(SiteId, hasCollection, extractedMenuItems, subject, MenuItemsSaved, updateVectorDatabase);
|
|
if (result == "OK")
|
|
{
|
|
MenuItemsSaved = true;
|
|
hasCollection = true;
|
|
errorMessage = "Menu saved";
|
|
}
|
|
else
|
|
{
|
|
errorMessage = result;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
}
|