SeemGen/Components/Partials/MenuItemEditor.razor

250 lines
10 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">Suggest New by AI</button>
</div> *@
@if (isLoading)
{
<p>Loading suggestions...</p>
}
else if (extractedMenuItems.Any())
{
<h4>Menu Items Editor</h4>
<div class="row">
<div class="rz-p-sm-12">
<RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Right">
<RadzenButton Click="ToggleReorder">
@(allowReorder ? "Done Reordering" : "Reorder")
</RadzenButton>
</RadzenStack>
@if (allowReorder)
{
<RadzenDataGrid @ref="dataGrid" TItem="MenuItem" RowSelect=@OnRowSelect AllowFiltering="true" AllowColumnResize="true" AllowSorting="true" PageSize="20" AllowPaging="true"
Data="@menuItems" ColumnWidth="300px" SelectionMode="DataGridSelectionMode.Single" RowRender="@RowRender">
<Columns>
<RadzenDataGridColumn Property="@nameof(MenuItem.SortOrder)" Title="Sort Order" Width="40px" />
<RadzenDataGridColumn Property="@nameof(MenuItem.Name)" Title="Menu Name" Frozen="true" Width="200px" />
<RadzenDataGridColumn Property="@nameof(MenuItem.ShowInMainMenu)" Title="Visible" Width="40px" />
</Columns>
</RadzenDataGrid>
}
else
{
<RadzenAccordion class="admin-accordion" Multiple="false">
<Items>
@foreach (var item in extractedMenuItems)
{
<RadzenAccordionItem Text="@item.MenuItem.Name" Icon="menu">
<input @bind="item.MenuItem.Name" class="form-control mb-2" placeholder="Menu item name" />
<label>Parent Menu (optional):</label>
<select class="form-control mb-2" @bind="item.MenuItem.ParentId">
<option value="">-- No Parent --</option>
@foreach (var parent in extractedMenuItems)
{
if (parent != item)
{
<option value="@parent.MenuItem.Id">@parent.MenuItem.Name</option>
}
}
</select>
<label>Attach Content Item:</label>
<select class="form-control mb-2" @bind="item.MenuItem.ContentItemId">
<option value="">-- Select --</option>
@foreach (var contentItem in allContentItems)
{
<option value="@contentItem.Id">@contentItem.Title</option>
}
</select>
<textarea class="form-control mt-2" @bind="item.Content" placeholder="Optional inline content"></textarea>
<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-3" @onclick="() => AddMenuItem()">Add Menu Item</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 = new();
IList<MenuItem> selectedMenuItems;
private List<MenuItemModel> extractedMenuItems = new();
private List<ContentItem> allContentItems = 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()
{
var site = await ContentEditorService.GetSiteInfoByIdAsync(SiteId);
subject = site.SiteDescription ?? string.Empty;
menuItems = new ObservableCollection<MenuItem>((await ContentEditorService.GetMenuItemsBySiteIdAsync(SiteId)).OrderBy(x => x.SortOrder));
allContentItems = await ContentEditorService.GetAllContentItemsBySiteIdAsync(SiteId);
var collectionResult = await QDrantService.GetCollectionBySiteIdAsync(SiteId);
hasCollection = !string.IsNullOrEmpty(collectionResult);
if (menuItems.Count > 0)
{
foreach (var menuItem in menuItems)
{
var model = new MenuItemModel("") { MenuItem = menuItem };
if (menuItem.ContentItemId != null)
{
var contentItem = await ContentEditorService.GetContentItemByIdAsync(menuItem.ContentItemId.Value);
if (contentItem != null)
{
model.Content = contentItem.Content;
model.ContentDescription = contentItem.Description;
}
}
extractedMenuItems.Add(model);
}
MenuItemsSaved = true;
}
}
// private async Task GenerateMenuItems()
// {
// if (string.IsNullOrWhiteSpace(subject))
// {
// errorMessage = "Please enter a subject.";
// return;
// }
// isLoading = true;
// 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);
// extractedMenuItems = response.Select(name => new MenuItemModel(name)).ToList();
// }
// catch
// {
// errorMessage = "An error occurred while generating menu items.";
// }
// finally { isLoading = false; }
// }
private async Task AddMenuItem()
{
MenuItemModel newModel = new MenuItemModel("New Menu Item");
MenuItem newItem = new MenuItem();
newItem.SiteInfoId = SiteId;
newItem.Name = "New Menu Item";
newItem.SortOrder = extractedMenuItems.Count+1;
var result = await ContentEditorService.AddMenuItemAsync(newItem);
newModel.MenuItem = result;
extractedMenuItems.Add(newModel);
if(result == null)
{
extractedMenuItems.Remove(newModel);
}
}
private async Task RemoveMenuItem(MenuItemModel item){
await ContentEditorService.DeleteMenuItemAsync(item.MenuItem.Id);
extractedMenuItems.Remove(item);
}
private async Task SaveMenuItems(bool updateVectorDatabase)
{
//var result = await ContentEditorAIService.ProcessMenuItems(SiteId, hasCollection, extractedMenuItems, subject, MenuItemsSaved, updateVectorDatabase);
try
{
foreach (var menuItemToUpdate in extractedMenuItems)
{
var result2 = await ContentEditorService.UpdateMenuItemAsync(menuItemToUpdate.MenuItem);
}
}
catch (Exception ex)
{
errorMessage = "Some error occured: " + ex;
}
finally
{
MenuItemsSaved = true;
hasCollection = true;
errorMessage = "Menu saved";
}
}
void RowRender(RowRenderEventArgs<MenuItem> args)
{
if (!allowReorder) return;
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);
var draggedModel = extractedMenuItems[draggedIndex];
menuItems.RemoveAt(draggedIndex);
extractedMenuItems.RemoveAt(draggedIndex);
menuItems.Insert(droppedIndex, draggedItem);
extractedMenuItems.Insert(droppedIndex, draggedModel);
for (int i = 0; i < menuItems.Count; i++)
{
menuItems[i].SortOrder = i;
extractedMenuItems[i].MenuItem.SortOrder = i;
}
JSRuntime.InvokeVoidAsync("eval", "document.querySelector('.my-class').classList.remove('my-class')");
}));
}
void ToggleReorder()
{
if (allowReorder) _ = SaveMenuItems(false);
allowReorder = !allowReorder;
}
void OnRowSelect(MenuItem item)
{
SelectedMenuItemModel = extractedMenuItems.FirstOrDefault(x => x.MenuItem.Id == item.Id) ?? new("");
}
}