1110 lines
42 KiB
Plaintext
1110 lines
42 KiB
Plaintext
@page "/preview/{siteid:int}"
|
|
@page "/preview/{siteid:int}/{topic?}"
|
|
@inherits MainPageBase
|
|
@using BLAIzor.Models
|
|
@using BLAIzor.Services
|
|
@using Google.Cloud.Speech.V1
|
|
@using Microsoft.AspNetCore.Identity.UI.Services
|
|
@using BLAIzor.Components.Partials
|
|
@using System.Text
|
|
@using System.Text.Json
|
|
@using System.Net
|
|
@using Radzen.Blazor.Rendering
|
|
|
|
@* @rendermode InteractiveServer *@
|
|
@inject IEmailSender _emailService
|
|
@inject NavigationManager _navigationManager
|
|
@inject IHttpContextAccessor HttpContextAccessor
|
|
@inject DesignTemplateService DesignTemplateService
|
|
@inject CssTemplateService CssTemplateService
|
|
@inject CssInjectorService CssService
|
|
@inject DialogService DialogService
|
|
|
|
<div class="page" style="z-index: 1">
|
|
|
|
|
|
<div class="top-panel-outer">
|
|
<RadzenStack class="top-panel px-2 animate__animated animate__slideInDown" JustifyContent="JustifyContent.Center" Orientation="Orientation.Horizontal" style="margin: auto; align-content:center;" Visible=@displayTopPanel>
|
|
@{if(displayOptions) {
|
|
<div class="rz-p-2 rz-text-align-center align-content-center">
|
|
<strong>@currentMenuItem.Name</strong>
|
|
</div>
|
|
<div class="rz-p-2 rz-text-align-center align-content-center">
|
|
<span>Happy with this look?</span>
|
|
<RadzenButton Size="ButtonSize.ExtraSmall" class="btn m-0" Text="@(IsContentSaved ? "Overwrite" : "Save")" Click="@(args => SaveCurrentLayout(currentMenuItem))" />
|
|
</div>
|
|
<div class="rz-p-2 rz-text-align-center align-content-center">
|
|
<span>Not happy?</span>
|
|
<RadzenButton Size="ButtonSize.ExtraSmall" class="btn m-0" @ref=button Text="Regenerate" Click="@(args => MenuClick(currentMenuItem.Name))" />
|
|
</div>
|
|
<div class="rz-p-2 rz-text-align-center align-content-center">
|
|
<span>Typos?</span>
|
|
<RadzenButton Size="ButtonSize.ExtraSmall" class="btn m-0" @ref=button Text="Manual edit" Click="@(args => OpenContentEditor(currentMenuItem))" />
|
|
</div>
|
|
<div class="rz-p-2 rz-text-align-center align-content-center">
|
|
<span>Cancel</span>
|
|
<RadzenButton Size="ButtonSize.ExtraSmall" class="btn m-0" @ref=button Text="x" Click="@(args => ToggleSavedContentEdit())" />
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<p class="text-center">If you navigate to a menu item, you can save it's actual design for consitent looks, and faster load for the visitors</p>
|
|
|
|
}
|
|
}
|
|
</RadzenStack>
|
|
</div>
|
|
|
|
<RadzenButton Click="@(args => ToggleSavedContentEdit())" Visible="@(currentMenuItem == null ? false : true)" style="position: fixed;
|
|
z-index: 10005;
|
|
top: 100px;
|
|
left: 10px;
|
|
height: 40px;
|
|
border-bottom-left-radius: 20px;
|
|
border-top-left-radius: 20px;
|
|
border-bottom-right-radius: 20px;
|
|
background: linear-gradient(307deg, rgba(12, 37, 51, 0.83) 7%, rgb(152 87 199 / 73%) 96%);
|
|
border-top-right-radius: 20px;">
|
|
<i class="fa-solid fa-pencil"></i>
|
|
</RadzenButton>
|
|
|
|
<RadzenButton Click="@(args => ToggleSettings())" style="position: fixed;
|
|
z-index: 10005;
|
|
top: 150px;
|
|
left: 10px;
|
|
height: 40px;
|
|
border-bottom-left-radius: 20px;
|
|
border-top-left-radius: 20px;
|
|
border-bottom-right-radius: 20px;
|
|
background: linear-gradient(307deg, rgba(12, 37, 51, 0.83) 7%, rgb(152 87 199 / 73%) 96%);
|
|
border-top-right-radius: 20px;">
|
|
<i class="fa-solid fa-wrench"></i>
|
|
</RadzenButton>
|
|
|
|
<RadzenStack class="editor-window animate__animated animate__slideInLeft" Orientation="Orientation.Vertical" style="" Visible=@displaySettingsPanel>
|
|
<button class="pointer bg-transparent border-0" style="width:100%; text-align: left; " @onclick="EditSite">
|
|
<div class="px-3 py-2 reference-button bg-panel-gradient pointer">
|
|
<div class="text-content">
|
|
<strong>Edit site</strong>
|
|
<br />
|
|
<small class="text-muted">Edit basic settings</small>
|
|
</div>
|
|
<div class="icon-buttons">
|
|
|
|
<div class="icon-circle"><i class="fa-regular fa-circle-question"></i></div>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
|
|
@*<button class="pointer bg-transparent border-0" style="width:100%; text-align: left; " @onclick="EditSite">
|
|
<div class="px-3 py-2 reference-button bg-panel-gradient pointer">
|
|
<div class="text-content">
|
|
<strong>AI settings</strong>
|
|
<br />
|
|
<small class="text-muted">Edit AI settings</small>
|
|
</div>
|
|
<div class="icon-buttons">
|
|
|
|
<div class="icon-circle"><i class="fa-solid fa-hexagon-nodes-bolt"></i></div>
|
|
</div>
|
|
</div>
|
|
</button>*@
|
|
<button class="pointer bg-transparent border-0" style="width:100%; text-align: left; " @onclick="OpenManageContentGroups">
|
|
<div class="px-3 py-2 reference-button bg-panel-gradient pointer">
|
|
<div class="text-content">
|
|
<strong>Edit content</strong>
|
|
<br />
|
|
<small class="text-muted">Manage content</small>
|
|
</div>
|
|
<div class="icon-buttons">
|
|
|
|
<div class="icon-circle"><i class="fa-solid fa-file-lines"></i></div>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
<button class="pointer bg-transparent border-0" style="width:100%; text-align: left; " @onclick="EditMenu">
|
|
<div class="px-3 py-2 reference-button bg-panel-gradient pointer">
|
|
<div class="text-content">
|
|
<strong>Setup menu</strong>
|
|
<br />
|
|
<small class="text-muted">Link content to the menu</small>
|
|
</div>
|
|
<div class="icon-buttons">
|
|
|
|
<div class="icon-circle"><i class="fa-solid fa-bars"></i></div>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
<button class="pointer bg-transparent border-0" style="width:100%; text-align: left; " @onclick="EditMenu">
|
|
<div class="px-3 py-2 reference-button bg-panel-gradient pointer">
|
|
<div class="text-content">
|
|
<strong>Edit looks</strong>
|
|
<br />
|
|
<small class="text-muted">Select design</small>
|
|
</div>
|
|
<div class="icon-buttons">
|
|
|
|
<div class="icon-circle"><i class="fa-solid fa-eye"></i></div>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
<button class="pointer bg-transparent border-0" style="width:100%; text-align: left; " @onclick="OpenManageUploads">
|
|
<div class="px-3 py-2 reference-button bg-panel-gradient pointer">
|
|
<div class="text-content">
|
|
<strong>Media</strong>
|
|
<br />
|
|
<small class="text-muted">Manage your media</small>
|
|
</div>
|
|
<div class="icon-buttons">
|
|
|
|
<div class="icon-circle"><i class="fa-solid fa-photo-film"></i></div>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
|
|
@* <RadzenStack Orientation="Orientation.Vertical" style="">
|
|
<div class="rz-p-2 rz-text-align-center">
|
|
<h3>Basic information</h3>
|
|
<p>@SiteInfo.SiteName</p>
|
|
<RadzenButton class="btn" Text="Edit basic info" Click="@EditSite" />
|
|
</div>
|
|
</RadzenStack>
|
|
|
|
<RadzenStack Orientation="Orientation.Vertical" style="">
|
|
<div class="rz-p-2 rz-text-align-center">
|
|
<h3>Site menu</h3>
|
|
<RadzenButton class="btn" Text="Edit menu" Click="@EditMenu" />
|
|
</div>
|
|
</RadzenStack>
|
|
|
|
<RadzenStack Orientation="Orientation.Vertical" style="">
|
|
<div class="rz-p-2 rz-text-align-center">
|
|
<h5>Manage content</h5>
|
|
<RadzenButton class="btn" Text="Manage content" Click="@OpenManageContentGroups" />
|
|
</div>
|
|
|
|
|
|
</RadzenStack>
|
|
<RadzenStack Orientation="Orientation.Vertical" style="">
|
|
<div class="rz-p-2 rz-text-align-center">
|
|
<h5>Manage design</h5>
|
|
<p>Template: @SiteInfo.TemplateId</p>
|
|
</div>
|
|
|
|
|
|
</RadzenStack>
|
|
|
|
<RadzenStack Orientation="Orientation.Vertical" Visible=@displayOptions style="">
|
|
<div class="rz-p-2 rz-text-align-center">
|
|
<h5>Page</h5>
|
|
<p>@currentMenuItem.Name</p>
|
|
</div>
|
|
<div class="rz-p-2 rz-text-align-center">
|
|
<p>Happy with this page?</p>
|
|
<RadzenButton class="btn" Text="@(isContentSaved ? "Update layout" : "Save layout")" Click="@(args => SaveCurrentLayout(currentMenuItem))" />
|
|
</div>
|
|
<div class="rz-p-2 rz-text-align-center">
|
|
<RadzenButton class="btn" @ref=button Text="Regenerate" Click="@(args => MenuClick(currentMenuItem.Name))" />
|
|
</div>
|
|
</RadzenStack>
|
|
<RadzenStack Orientation="Orientation.Vertical" style="">
|
|
<div class="rz-p-2 rz-text-align-center">
|
|
<h5>Media</h5>
|
|
<RadzenButton class="btn" Text="Open library" Click="@OpenManageUploads" />
|
|
</div>
|
|
|
|
</RadzenStack>*@
|
|
</RadzenStack>
|
|
|
|
|
|
<NewNavMenu Menu="@MenuItems" BrandName="@SelectedBrandName" SiteId="siteid" OnMenuClicked=@MenuClick></NewNavMenu>
|
|
<main>
|
|
|
|
<article class="content text-center" style="position: relative; z-index: 4;">
|
|
<PageTitle>Home</PageTitle>
|
|
@{
|
|
if (SiteInfo != null)
|
|
{
|
|
if (SiteInfo.BackgroundVideo != null)
|
|
{
|
|
<VideoComponent site="SiteInfo" />
|
|
}
|
|
}
|
|
}
|
|
@* <HeadContent>
|
|
|
|
@if (!string.IsNullOrEmpty(dynamicallyLoadedCss))
|
|
{
|
|
<style>@dynamicallyLoadedCss</style>
|
|
}
|
|
|
|
</HeadContent> *@
|
|
|
|
<div id="maincontrol">
|
|
|
|
@* <div class="hoverslide"> *@
|
|
|
|
<div class="displaysearch">
|
|
<div class="searchBox">
|
|
|
|
<input @oninput="(e) => UserInput = e.Value.ToString()"
|
|
@onkeydown="@Enter" class="searchInput" type="text" name="" value="@UserInput" placeholder="Ask any question">
|
|
<button data-hint="ask anything" class="searchButton border-0" @onclick="SendUserQuery" href="#">
|
|
<i class="fa-solid fa-hexagon-nodes-bolt" style="font-size:20px"></i>
|
|
</button>
|
|
</div>
|
|
|
|
@{
|
|
if (VoiceEnabled)
|
|
{
|
|
|
|
if (STTEnabled)
|
|
{
|
|
<button data-hint="talk" id="recButton" class="btn btn-primary voicebutton" onclick="startRecording()"><i class="fa-solid fa-microphone"></i></button>
|
|
<button id="stopButton" class="btn btn-primary voicebutton" onclick="stopRecording()" hidden><i class="fa-solid fa-microphone-slash"></i></button>
|
|
}
|
|
|
|
if (TTSEnabled)
|
|
{
|
|
if (!AiVoicePermitted)
|
|
{
|
|
<button data-hint="listen" class="btn btn-primary voicebutton" @onclick="AllowAIVoice">
|
|
<i class="fa-solid fa-volume-xmark"></i>
|
|
|
|
</button>
|
|
}
|
|
else
|
|
{
|
|
<button data-hint="listen" class="btn btn-primary voicebutton" @onclick="MuteAI"><i class="fa-solid fa-volume-high"></i></button>
|
|
}
|
|
<audio id="audioPlayer" hidden style="display: none;"></audio>
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
@* Type anything *@
|
|
|
|
@* </div> *@
|
|
</div>
|
|
|
|
<p id="recordingText"></p>
|
|
|
|
<div id="currentContent">
|
|
@{
|
|
if (!string.IsNullOrEmpty(HtmlContent.ToString()))
|
|
{
|
|
|
|
if (isEmailFormVisible)
|
|
{
|
|
<div class="conteiner-fluid">
|
|
<div class="row">
|
|
<div class="pt-5 @FirstColumnClass">
|
|
@((MarkupString)HtmlContent.ToString())
|
|
</div>
|
|
<div class="pt-5 col-12 col-md-6">
|
|
<ContactFormComponent ContactFormModel="@ContactFormModel" DocumentEmailAddress="@DocumentEmailAddress" OnDataChanged="@ContentChangedInForm"></ContactFormComponent>
|
|
<button @onclick="CancelEmail" class="btn btn-primary">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
}
|
|
else
|
|
{
|
|
<div class="pt-5 @FirstColumnClass">
|
|
@((MarkupString)HtmlContent.ToString())
|
|
</div>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<div class="text-center row" style="height: 70vh;">
|
|
<p>@StatusContent</p>
|
|
<div class="mydiv"></div>
|
|
<div class="mydiv"></div>
|
|
<div class="mydiv"></div>
|
|
<div class="mydiv"></div>
|
|
<div class="mydiv"></div>
|
|
|
|
</div>
|
|
}
|
|
|
|
|
|
}
|
|
</div>
|
|
<button class="btn btn-primary" @onclick="HomeClick"><i class="fa-solid fa-rotate"></i></button>
|
|
</article>
|
|
</main>
|
|
<FooterComponent MenuString="@Menu" OnMenuClicked=@MenuClick></FooterComponent>
|
|
</div>
|
|
|
|
<script>
|
|
|
|
var sessionId = null;
|
|
|
|
function setSessionId(id) {
|
|
sessionId = id;
|
|
console.log("Session ID set:", sessionId);
|
|
}
|
|
|
|
function callAI(inputString) {
|
|
console.log(sessionId);
|
|
DotNet.invokeMethodAsync('BLAIzor', 'CallCSharpMethod2', inputString, sessionId, false)
|
|
.then(response => console.log(response))
|
|
.catch(error => console.error(error));
|
|
}
|
|
|
|
|
|
</script>
|
|
<script>
|
|
function openCalendar(calendlyUserName) {
|
|
console.log(calendlyUserName);
|
|
Calendly.initPopupWidget({
|
|
url: 'https://calendly.com/' + calendlyUserName + '?name=JohnDoe&email=john.doe@example.com'
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
function openContactForm(emailAddress) {
|
|
console.log(emailAddress);
|
|
|
|
if (emailAddress) {
|
|
DotNet.invokeMethodAsync('BLAIzor', 'OpenEmailForm2', emailAddress)
|
|
|
|
}
|
|
}
|
|
</script>
|
|
|
|
|
|
@code {
|
|
// public static Preview myHome;
|
|
private string? Subdomain;
|
|
[Parameter]
|
|
public int siteid { get; set; }
|
|
[Parameter]
|
|
public string? topic { get; set; }
|
|
|
|
private string ChatGptResponse = string.Empty;
|
|
private bool isRecording = false;
|
|
|
|
// private string dynamicallyLoadedCss = string.Empty;
|
|
|
|
private bool displaySettingsPanel = false;
|
|
private bool displayTopPanel = false;
|
|
private bool displayOptions = false;
|
|
private bool forceRegenerate = false;
|
|
|
|
private RadzenButton button;
|
|
|
|
public string DialogKey { get; set; } = "DefaultDialog";
|
|
private Dictionary<string, EditSiteInfoDialogSettings> _dialogSettings = new();
|
|
private readonly Dictionary<string, bool> _hasInitialized = new();
|
|
|
|
private void ToggleSettings()
|
|
{
|
|
displaySettingsPanel = !displaySettingsPanel;
|
|
}
|
|
|
|
private void ToggleSavedContentEdit()
|
|
{
|
|
displayTopPanel = !displayTopPanel;
|
|
}
|
|
|
|
async Task SaveCurrentLayout(MenuItem menuItem)
|
|
{
|
|
//Save current layout called
|
|
menuItem.StoredHtml = HtmlContent.ToString();
|
|
await _logger.InfoAsync($"Preview Component: Saving layout!", $"Content length: {HtmlContent.Length}");
|
|
|
|
await _logger.InfoAsync($"Preview Component: Saving layout!", $"Content length: {menuItem.StoredHtml}");
|
|
var result = await _contentEditorService.UpdateMenuItemAsync(menuItem);
|
|
var message = NotificationHelper.CreateNotificationMessage("Page design saved", 2, "Success", $"Page design for {result.Name} updated successfully");
|
|
ShowNotification(message);
|
|
await _logger.InfoAsync($"Preview Component: Saved layout for page!", $"MenuItem updated with new design: {result.Id}, {result.Name}");
|
|
|
|
}
|
|
|
|
private void AllowAIVoice()
|
|
{
|
|
AiVoicePermitted = true;
|
|
}
|
|
private void MuteAI()
|
|
{
|
|
AiVoicePermitted = false;
|
|
}
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (firstRender)
|
|
{
|
|
await jsRuntime.InvokeVoidAsync("setSessionId", SessionId);
|
|
await jsRuntime.InvokeVoidAsync("initHints");
|
|
|
|
}
|
|
|
|
if (_initVoicePending)
|
|
{
|
|
Console.WriteLine("PENDING VOICE--------------------------------------------------");
|
|
_initVoicePending = false;
|
|
await jsRuntime.InvokeVoidAsync("initVoiceRecorder", "ProcessAudio2");
|
|
}
|
|
}
|
|
|
|
protected override Task OnInitializedAsync()
|
|
{
|
|
VoiceEnabled = configuration?.GetSection("AiSettings")?.GetValue<bool>("VoiceActivated") ?? false;
|
|
return base.OnInitializedAsync();
|
|
}
|
|
|
|
public async void MenuClick(string menuName)
|
|
{
|
|
await CallCSharpMethod2(menuName, SessionId, true);
|
|
}
|
|
|
|
public void HomeClick()
|
|
{
|
|
//ChatGptService.OnContentReceived -= UpdateContent;
|
|
ChatGptService.OnContentReceived -= UpdateContent;
|
|
_navigationManager.Refresh(true);
|
|
}
|
|
|
|
private void CancelEmail()
|
|
{
|
|
FirstColumnClass = "";
|
|
isEmailFormVisible = false;
|
|
StateHasChanged();
|
|
}
|
|
|
|
public Preview()
|
|
{
|
|
myHome = this; // Set the static reference to the current instance
|
|
}
|
|
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
SessionId = _scopedContentService.SessionId;
|
|
SiteId = siteid;
|
|
_instances[SessionId] = this;
|
|
_scopedContentService.OnBrandNameChanged += HandleBrandNameChanged;
|
|
SelectedBrandName = _scopedContentService.SelectedBrandName;
|
|
// Subdomain = HttpContextAccessor.HttpContext?.Items["Subdomain"]?.ToString();
|
|
SiteInfo = await _contentEditorService.GetSiteInfoByIdAsync(SiteId);
|
|
if (SiteInfo != null)
|
|
{
|
|
|
|
// SiteId = SiteInfo.Id;
|
|
|
|
_scopedContentService.SelectedBrandName = SiteInfo.SiteName.ToLower();
|
|
TTSEnabled = SiteInfo.TTSActive;
|
|
STTEnabled = SiteInfo.STTActive;
|
|
|
|
Console.Write("Selected brand name:" + _scopedContentService.SelectedBrandName);
|
|
}
|
|
else
|
|
{
|
|
// SiteId = 1;
|
|
_scopedContentService.SelectedBrandName = "default";
|
|
TTSEnabled = false;
|
|
STTEnabled = false;
|
|
|
|
}
|
|
_scopedContentService.SelectedSiteId = SiteId;
|
|
ContentCollectionName = SiteInfo.VectorCollectionName;
|
|
|
|
Console.Write("------------------------");
|
|
// Load the CSS template for the selected brand from the database
|
|
var designTemplate = await DesignTemplateService.GetByIdAsync((int)SiteInfo.TemplateId!);
|
|
var cssTemplate = await CssTemplateService.GetByDesignTemplateIdAsync((int)SiteInfo.TemplateId);
|
|
TemplateCollectionName = designTemplate.QDrandCollectionName;
|
|
|
|
if (cssTemplate != null)
|
|
{
|
|
dynamicallyLoadedCss = cssTemplate.CssContent; // Assuming Content holds the CSS string
|
|
var cssPath = await CssTemplateService.SaveTempCssFileAsync(dynamicallyLoadedCss, SessionId);
|
|
await jsRuntime.InvokeVoidAsync("seemgen.injectCssFile", cssPath);
|
|
}
|
|
|
|
|
|
Console.Write("------------------------");
|
|
|
|
// ChatGptService.OnContentReceived += UpdateContent;
|
|
ChatGptService.OnContentReceived += UpdateContent;
|
|
// ChatGptService.OnStatusChangeReceived += UpdateStatus;
|
|
ChatGptService.OnStatusChangeReceived += UpdateStatus;
|
|
ChatGptService.OnTextContentAvailable += UpdateTextContentForVoice;
|
|
|
|
Menu = await GetMenuList(SiteId);
|
|
MenuItems = await GetMenuItems(SiteId);
|
|
if (string.IsNullOrEmpty(HtmlContent.ToString()))
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(topic))
|
|
{
|
|
UserInput = topic;
|
|
await ChatGptService.ProcessContentRequest(SessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, ContentCollectionName, Menu, true);
|
|
}
|
|
else
|
|
{
|
|
await ChatGptService.GetChatGptWelcomeMessage(SessionId, SiteId, TemplateCollectionName, Menu);
|
|
// SiteModel = await ChatGptService.InitSite(SessionId, SiteId, TemplateCollectionName, Menu);
|
|
//await ChatGptService.ProcessContentRequest(SessionId, MenuItems.FirstOrDefault(), SiteId, (int)SiteInfo.TemplateId!, TemplateCollectionName, Menu, true);
|
|
}
|
|
|
|
}
|
|
UserInput = string.Empty;
|
|
_initVoicePending = true;
|
|
}
|
|
|
|
private async void UpdateContent(string receivedSessionId, string content, MenuItem menuItem)
|
|
{
|
|
if (receivedSessionId == SessionId) // Only accept messages meant for this tab
|
|
{
|
|
HtmlContent.Clear();
|
|
HtmlContent.Append(content);
|
|
//TODO SAVE TO DB
|
|
if (menuItem != null)
|
|
{
|
|
currentMenuItem = menuItem;
|
|
// IsContentSaved = string.IsNullOrEmpty(currentMenuItem.StoredHtml) ? false : true;
|
|
// _logger.InfoAsync($"Preview - UpdateContent: {IsContentSaved}");
|
|
displayOptions = true;
|
|
StateHasChanged();
|
|
}
|
|
//InvokeAsync(StateHasChanged); // Ensures UI updates dynamically
|
|
await InvokeAsync(() =>
|
|
{
|
|
StateHasChanged();
|
|
});
|
|
var result = await jsRuntime.InvokeAsync<object>("getDivContent", "currentContent");
|
|
_scopedContentService.CurrentDOM = JsonSerializer.Serialize(result);
|
|
//_scopedContentService.CurrentDOM = await jsRuntime.InvokeAsync<string>("getDivContent", "currentContent");
|
|
}
|
|
}
|
|
|
|
// private async void UpdateTextContentForVoice(string receivedSessionId, string content)
|
|
// {
|
|
// if (receivedSessionId == SessionId) // Only accept messages meant for this tab
|
|
// {
|
|
|
|
// TextContent = content;
|
|
// await ConvertTextToSpeech(content);
|
|
// //_scopedContentService.CurrentDOM = await jsRuntime.InvokeAsync<string>("getDivContent", "currentContent");
|
|
// }
|
|
// }
|
|
|
|
private async void UpdateFinished(string receivedSessionId)
|
|
{
|
|
if (receivedSessionId == SessionId) // Only accept messages meant for this tab
|
|
{
|
|
Console.WriteLine("Content update finished");
|
|
var result = await jsRuntime.InvokeAsync<object>("getDivContent", "currentContent");
|
|
_scopedContentService.CurrentDOM = JsonSerializer.Serialize(result);
|
|
Console.Write(_scopedContentService.CurrentDOM);
|
|
}
|
|
}
|
|
|
|
private async Task ContentChangedInForm()
|
|
{
|
|
var result = await jsRuntime.InvokeAsync<object>("getDivContent", "currentContent");
|
|
_scopedContentService.CurrentDOM = JsonSerializer.Serialize(result);
|
|
Console.Write(_scopedContentService.CurrentDOM);
|
|
}
|
|
|
|
private async void UpdateStatus(string receivedSessionId, string content)
|
|
{
|
|
if (receivedSessionId == SessionId) // Only accept messages meant for this tab
|
|
{
|
|
StatusContent = content;
|
|
//InvokeAsync(StateHasChanged); // Ensures UI updates dynamically
|
|
await InvokeAsync(() =>
|
|
{
|
|
StateHasChanged();
|
|
});
|
|
}
|
|
}
|
|
|
|
public async Task Enter(KeyboardEventArgs e)
|
|
{
|
|
if (e.Code == "Enter" || e.Code == "NumpadEnter")
|
|
{
|
|
HtmlContent.Clear();
|
|
var menu = await GetMenuList(SiteId);
|
|
await ChatGptService.ProcessUserIntent(SessionId, UserInput, SiteId, (int)SiteInfo.TemplateId!, ContentCollectionName, menu);
|
|
UserInput = string.Empty;
|
|
}
|
|
}
|
|
|
|
// public void Dispose()
|
|
// {
|
|
// dynamicallyLoadedCss = "";
|
|
// HtmlContent.Clear();
|
|
// _scopedContentService.OnBrandNameChanged -= HandleBrandNameChanged;
|
|
// AIService.OnContentReceived -= UpdateContent;
|
|
// AIService.OnStatusChangeReceived -= UpdateStatus;
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
dynamicallyLoadedCss = "";
|
|
HtmlContent.Clear();
|
|
await CssTemplateService.DeleteSessionCssFile(SessionId);
|
|
_scopedContentService.OnBrandNameChanged -= HandleBrandNameChanged;
|
|
ChatGptService.OnContentReceived -= UpdateContent;
|
|
ChatGptService.OnContentReceiveFinished -= UpdateFinished;
|
|
ChatGptService.OnStatusChangeReceived -= UpdateStatus;
|
|
ChatGptService.OnTextContentAvailable -= UpdateTextContentForVoice;
|
|
}
|
|
|
|
|
|
// public async ValueTask DisposeAsync()
|
|
// {
|
|
// await CssTemplateService.DeleteSessionCssFile(SessionId);
|
|
// }
|
|
|
|
public async Task EditSite()
|
|
{
|
|
string dialogKey = $"EditSiteInfoDialogSettings_{siteid}"; // can be anything unique
|
|
|
|
var settings = await LoadStateAsync(dialogKey)
|
|
?? new EditSiteInfoDialogSettings
|
|
{
|
|
Width = "500px",
|
|
Height = "512px",
|
|
Left = "10%",
|
|
Top = "10%"
|
|
};
|
|
|
|
await DialogService.OpenAsync<ManageSiteInfoPartial>($"Edit information of {SiteInfo.SiteName}",
|
|
new Dictionary<string, object>() {
|
|
{ "SiteId", siteid },
|
|
{ "OnSiteNameChanged", new Func<string, Task>(OnSiteNameChanged) },
|
|
{ "OnSiteInfoSaveClicked", new Func<SiteInfo, Task>(OnSiteInfoSaved) },
|
|
},
|
|
new DialogOptions()
|
|
{
|
|
Resizable = true,
|
|
Draggable = true,
|
|
Resize = GetResizeHandler(dialogKey),
|
|
Drag = GetDragHandler(dialogKey),
|
|
Width = settings.Width,
|
|
Height = settings.Height,
|
|
Left = settings.Left,
|
|
Top = settings.Top,
|
|
CssClass = "draggable-popup-dialog",
|
|
WrapperCssClass = "draggable-popup-dialog-wrapper"
|
|
});
|
|
|
|
await SaveStateAsync(dialogKey, _editSiteinfoSettings);
|
|
}
|
|
|
|
public async Task EditMenu()
|
|
{
|
|
string dialogKey = $"EditMenuDialogSettings_{siteid}"; // can be anything unique
|
|
|
|
var settings = await LoadStateAsync(dialogKey)
|
|
?? new EditSiteInfoDialogSettings
|
|
{
|
|
Width = "500px",
|
|
Height = "512px",
|
|
Left = "10%",
|
|
Top = "10%"
|
|
};
|
|
|
|
await DialogService.OpenAsync<MenuItemEditor>($"Edit menu of {SiteInfo.SiteName}",
|
|
new Dictionary<string, object>() {
|
|
{ "SiteId", siteid },
|
|
{ "SessionId", SessionId },
|
|
// { "OnSiteNameChanged", new Func<string, Task>(OnSiteNameChanged) },
|
|
// { "OnSiteInfoSaveClicked", new Func<SiteInfo, Task>(OnSiteInfoSaved) },
|
|
},
|
|
new DialogOptions()
|
|
{
|
|
Resizable = true,
|
|
Draggable = true,
|
|
Resize = GetResizeHandler(dialogKey),
|
|
Drag = GetDragHandler(dialogKey),
|
|
Width = settings.Width,
|
|
Height = settings.Height,
|
|
Left = settings.Left,
|
|
Top = settings.Top,
|
|
CssClass = "draggable-popup-dialog",
|
|
WrapperCssClass = "draggable-popup-dialog-wrapper"
|
|
});
|
|
|
|
await SaveStateAsync(dialogKey, _editSiteinfoSettings);
|
|
}
|
|
|
|
private async Task OnSiteNameChanged(string newName)
|
|
{
|
|
Console.WriteLine("Sitename updated!!!!!!");
|
|
SelectedBrandName = newName;
|
|
}
|
|
|
|
private async Task OnSiteInfoSaved(SiteInfo newInfo)
|
|
{
|
|
Console.WriteLine("Sitename updated!!!!!!");
|
|
|
|
var message = NotificationHelper.CreateNotificationMessage("Site information saved", 2, "Success", "Site information saved successfully");
|
|
ShowNotification(message);
|
|
}
|
|
|
|
|
|
public async Task EditContentItem(int Id)
|
|
{
|
|
string dialogKey = $"EditContentItemDialogSettings_{Id}"; // can be anything unique
|
|
|
|
var settings = await LoadStateAsync(dialogKey)
|
|
?? new EditSiteInfoDialogSettings
|
|
{
|
|
Width = "70vw",
|
|
Height = "80vh",
|
|
Left = "10%",
|
|
Top = "10%"
|
|
};
|
|
|
|
await DialogService.OpenAsync<EditContentItem>($"Edit content {Id}",
|
|
new Dictionary<string, object>() {
|
|
{ "ContentItemId", Id },
|
|
{ "OnContentUpdated", new Func<ContentItem, Task>(OnContentItemUpdated) },
|
|
{ "OnSaved", new Func<ContentItem, Task>(OnContentItemSaved) },
|
|
{ "OnCancelled", new Func<Task>(OnEditContentItemCancelClicked) },
|
|
},
|
|
new DialogOptions()
|
|
{
|
|
Resizable = true,
|
|
Draggable = true,
|
|
Resize = GetResizeHandler(dialogKey),
|
|
Drag = GetDragHandler(dialogKey),
|
|
Width = settings.Width,
|
|
Height = settings.Height,
|
|
Left = settings.Left,
|
|
Top = settings.Top,
|
|
CssClass = "draggable-popup-dialog",
|
|
WrapperCssClass = "draggable-popup-dialog-wrapper"
|
|
});
|
|
|
|
await SaveStateAsync(dialogKey, _editSiteinfoSettings);
|
|
}
|
|
|
|
private async Task OnContentItemUpdated(ContentItem contentGroup)
|
|
{
|
|
|
|
}
|
|
|
|
private async Task OnContentItemSaved(ContentItem contentGroup)
|
|
{
|
|
|
|
//TODO Cahce outdated
|
|
await CacheService.UpdateContentCache(SessionId, SiteId);
|
|
var message = NotificationHelper.CreateNotificationMessage("ContentItem saved", 2, "Success", "ContentItem saved successfully");
|
|
ShowNotification(message);
|
|
|
|
}
|
|
|
|
|
|
private async Task OnEditContentItemCancelClicked()
|
|
{
|
|
Console.WriteLine("ContentItem Edit clicked");
|
|
|
|
|
|
|
|
}
|
|
|
|
public async Task OpenManageContentGroups()
|
|
{
|
|
string dialogKey = $"ManageContentGroupsDialogSettings_{siteid}"; // can be anything unique
|
|
var settings = await LoadStateAsync(dialogKey);
|
|
if (settings != null)
|
|
{
|
|
Console.WriteLine($"Settings: {settings.Top}, {settings.Left}, {settings.Height}, {settings.Width}");
|
|
}
|
|
else
|
|
{
|
|
settings = new EditSiteInfoDialogSettings
|
|
{
|
|
Width = "300px",
|
|
Height = "612px",
|
|
Left = "10%",
|
|
Top = "10%"
|
|
};
|
|
}
|
|
|
|
await DialogService.OpenAsync<ManageContentGroupsPartial>($"Manage content of {SiteInfo.SiteName}",
|
|
new Dictionary<string, object>() {
|
|
{ "SiteInfoId", siteid },
|
|
{ "OnManageContentItemClicked", new Func<string, int, Task>(OnManageContentItemClicked) }
|
|
},
|
|
|
|
new DialogOptions()
|
|
{
|
|
Resizable = true,
|
|
Draggable = true,
|
|
Resize = GetResizeHandler(dialogKey),
|
|
Drag = GetDragHandler(dialogKey),
|
|
Width = settings.Width,
|
|
Height = settings.Height,
|
|
Left = settings.Left,
|
|
Top = settings.Top,
|
|
CssClass = "draggable-popup-dialog",
|
|
WrapperCssClass = "draggable-popup-dialog-wrapper"
|
|
});
|
|
|
|
await SaveStateAsync(dialogKey, _editSiteinfoSettings);
|
|
}
|
|
|
|
private async Task OnContentGroupUpdated(ContentGroup contentGroup)
|
|
{
|
|
Console.WriteLine("ContentGroup updated!!!!!!");
|
|
}
|
|
|
|
private async Task OnContentGroupEditStarted(ContentGroup contentGroup)
|
|
{
|
|
Console.WriteLine("ContentGroup edit started!!!!!!");
|
|
}
|
|
|
|
|
|
private async Task OnManageContentItemClicked(string methodName, int Id)
|
|
{
|
|
Console.WriteLine("ContentItem Edit clicked");
|
|
await EditContentItem(Id);
|
|
}
|
|
|
|
public async Task OpenManageUploads()
|
|
{
|
|
string dialogKey = $"ManageUploadsDialogSettings_{siteid}"; // can be anything unique
|
|
var settings = await LoadStateAsync(dialogKey)
|
|
?? new EditSiteInfoDialogSettings
|
|
{
|
|
Width = "600px",
|
|
Height = "600px",
|
|
Left = "10%",
|
|
Top = "10%"
|
|
};
|
|
|
|
await DialogService.OpenAsync<ManageUploads>($"Media library",
|
|
null,
|
|
new DialogOptions()
|
|
{
|
|
Resizable = true,
|
|
Draggable = true,
|
|
Resize = GetResizeHandler(dialogKey),
|
|
Drag = GetDragHandler(dialogKey),
|
|
Width = settings.Width,
|
|
Height = settings.Height,
|
|
Left = settings.Left,
|
|
Top = settings.Top,
|
|
CssClass = "draggable-popup-dialog",
|
|
WrapperCssClass = "draggable-popup-dialog-wrapper"
|
|
});
|
|
await SaveStateAsync(dialogKey, _editSiteinfoSettings);
|
|
}
|
|
|
|
public async Task OpenContentEditor(MenuItem currentMenuItem)
|
|
{
|
|
string dialogKey = $"HtmlContentEditorSettings_{siteid}"; // can be anything unique
|
|
// <HtmlContentEditor Html="@CurrentHtml" HtmlChanged="@OnHtmlUpdated" />
|
|
var settings = await LoadStateAsync(dialogKey)
|
|
?? new EditSiteInfoDialogSettings
|
|
|
|
{
|
|
Width = "600px",
|
|
Height = "600px",
|
|
Left = "10%",
|
|
Top = "10%"
|
|
};
|
|
|
|
await DialogService.OpenAsync<HtmlContentEditor>($"Edit the content of this page",
|
|
new Dictionary<string, object>() {
|
|
{ "Html", currentMenuItem.StoredHtml },
|
|
{ "HtmlChanged", new Func<string, Task>(OnHtmlUpdated) }
|
|
},
|
|
new DialogOptions()
|
|
{
|
|
Resizable = true,
|
|
Draggable = true,
|
|
Resize = GetResizeHandler(dialogKey),
|
|
Drag = GetDragHandler(dialogKey),
|
|
Width = settings.Width,
|
|
Height = settings.Height,
|
|
Left = settings.Left,
|
|
Top = settings.Top,
|
|
CssClass = "draggable-popup-dialog",
|
|
WrapperCssClass = "draggable-popup-dialog-wrapper"
|
|
});
|
|
|
|
await SaveStateAsync(dialogKey, _editSiteinfoSettings);
|
|
}
|
|
|
|
private async Task OnHtmlUpdated(string newHtml)
|
|
{
|
|
HtmlContent.Clear();
|
|
HtmlContent.Append(newHtml);
|
|
// You can trigger embedding regeneration, saving, etc.
|
|
currentMenuItem.StoredHtml = newHtml;
|
|
|
|
var result = await _contentEditorService.UpdateMenuItemAsync(currentMenuItem);
|
|
var message = NotificationHelper.CreateNotificationMessage("Content saved", 2, "Success", "Static content saved successfully");
|
|
ShowNotification(message);
|
|
}
|
|
|
|
private Action<System.Drawing.Point> GetDragHandler(string key)
|
|
{
|
|
return (point) =>
|
|
{
|
|
if (!_hasInitialized.ContainsKey(key))
|
|
{
|
|
_hasInitialized[key] = true;
|
|
Console.WriteLine($"🚫 Skipping initial drag for {key}");
|
|
return;
|
|
}
|
|
|
|
var settings = GetSettingsForKey(key);
|
|
Console.WriteLine($"Got settings: {settings.Top}, {settings.Left}, {settings.Height}, {settings.Width}");
|
|
settings.Left = $"{point.X}px";
|
|
settings.Top = $"{point.Y}px";
|
|
Console.WriteLine($"NEW Settings: {settings.Top}, {settings.Left}, {settings.Height}, {settings.Width}");
|
|
_dialogSettings[key] = settings;
|
|
InvokeAsync(() => SaveStateAsync(key, settings));
|
|
};
|
|
}
|
|
|
|
private Action<System.Drawing.Size> GetResizeHandler(string key)
|
|
{
|
|
return (size) =>
|
|
{
|
|
if (!_hasInitialized.ContainsKey(key))
|
|
{
|
|
_hasInitialized[key] = true;
|
|
Console.WriteLine($"🚫 Skipping initial resize for {key}");
|
|
return;
|
|
}
|
|
|
|
var settings = GetSettingsForKey(key);
|
|
Console.WriteLine($"Got settings: {settings.Top}, {settings.Left}, {settings.Height}, {settings.Width}");
|
|
settings.Width = $"{size.Width}px";
|
|
settings.Height = $"{size.Height}px";
|
|
Console.WriteLine($"NEW Settings: {settings.Top}, {settings.Left}, {settings.Height}, {settings.Width}");
|
|
_dialogSettings[key] = settings;
|
|
InvokeAsync(() => SaveStateAsync(key, settings));
|
|
};
|
|
}
|
|
|
|
private EditSiteInfoDialogSettings GetSettingsForKey(string key)
|
|
{
|
|
|
|
Console.WriteLine($"Getting settings for {key}");
|
|
if (_dialogSettings.TryGetValue(key, out var value))
|
|
return value;
|
|
|
|
var newSettings = new EditSiteInfoDialogSettings();
|
|
_dialogSettings[key] = newSettings;
|
|
return newSettings;
|
|
}
|
|
|
|
// void OnDrag(System.Drawing.Point point)
|
|
// {
|
|
// jsRuntime.InvokeVoidAsync("eval", $"console.log('Dialog drag. Left:{point.X}, Top:{point.Y}')");
|
|
|
|
// if (EditSiteInfoSettings == null)
|
|
// {
|
|
// EditSiteInfoSettings = new EditSiteInfoDialogSettings();
|
|
// }
|
|
|
|
// EditSiteInfoSettings.Left = $"{point.X}px";
|
|
// EditSiteInfoSettings.Top = $"{point.Y}px";
|
|
|
|
// InvokeAsync(() => SaveStateAsync(DialogKey, EditSiteInfoSettings));
|
|
// }
|
|
|
|
// void OnResize(System.Drawing.Size size)
|
|
// {
|
|
// jsRuntime.InvokeVoidAsync("eval", $"console.log('Dialog resize. Width:{size.Width}, Height:{size.Height}')");
|
|
|
|
// if (EditSiteInfoSettings == null)
|
|
// {
|
|
// EditSiteInfoSettings = new EditSiteInfoDialogSettings();
|
|
// }
|
|
|
|
// EditSiteInfoSettings.Width = $"{size.Width}px";
|
|
// EditSiteInfoSettings.Height = $"{size.Height}px";
|
|
|
|
// InvokeAsync(() => SaveStateAsync(DialogKey, EditSiteInfoSettings));
|
|
// }
|
|
|
|
private EditSiteInfoDialogSettings _editSiteinfoSettings = new();
|
|
|
|
public EditSiteInfoDialogSettings EditSiteInfoSettings
|
|
{
|
|
get => _editSiteinfoSettings;
|
|
set
|
|
{
|
|
if (_editSiteinfoSettings != value)
|
|
{
|
|
_editSiteinfoSettings = value;
|
|
InvokeAsync(() => SaveStateAsync(DialogKey, _editSiteinfoSettings));
|
|
}
|
|
}
|
|
}
|
|
|
|
// private async Task LoadStateAsync()
|
|
// {
|
|
// await Task.CompletedTask;
|
|
|
|
// var result = await jsRuntime.InvokeAsync<string>("window.localStorage.getItem", "EditSiteInfoDialogSettings");
|
|
// if (!string.IsNullOrEmpty(result))
|
|
// {
|
|
// _editSiteinfoSettings = JsonSerializer.Deserialize<EditSiteInfoDialogSettings>(result);
|
|
// }
|
|
// }
|
|
|
|
// private async Task SaveStateAsync()
|
|
// {
|
|
// await Task.CompletedTask;
|
|
|
|
// await jsRuntime.InvokeVoidAsync("window.localStorage.setItem", "EditSiteInfoDialogSettings", JsonSerializer.Serialize<EditSiteInfoDialogSettings>(EditSiteInfoSettings));
|
|
// }
|
|
|
|
private async Task<EditSiteInfoDialogSettings?> LoadStateAsync(string dialogKey)
|
|
{
|
|
Console.WriteLine($"Loading setting for {dialogKey}");
|
|
var result = await jsRuntime.InvokeAsync<string>("window.localStorage.getItem", dialogKey);
|
|
if (!string.IsNullOrEmpty(result))
|
|
{
|
|
Console.WriteLine($"Found setting for {dialogKey}");
|
|
return JsonSerializer.Deserialize<EditSiteInfoDialogSettings>(result);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private async Task SaveStateAsync(string dialogKey, EditSiteInfoDialogSettings settings)
|
|
{
|
|
if (string.IsNullOrEmpty(settings?.Width) ||
|
|
string.IsNullOrEmpty(settings?.Height) ||
|
|
string.IsNullOrEmpty(settings?.Top) ||
|
|
string.IsNullOrEmpty(settings?.Left))
|
|
{
|
|
Console.WriteLine($"❌ Skipping save for {dialogKey} due to invalid values");
|
|
return; // Do NOT save garbage data
|
|
}
|
|
Console.WriteLine($"Saving setting for {dialogKey}");
|
|
var json = JsonSerializer.Serialize(settings);
|
|
Console.WriteLine($"Saving ettings: {settings.Top}, {settings.Left}, {settings.Height}, {settings.Width}, {json}");
|
|
await jsRuntime.InvokeVoidAsync("window.localStorage.setItem", dialogKey, json);
|
|
}
|
|
|
|
public class EditSiteInfoDialogSettings
|
|
{
|
|
public string Left { get; set; }
|
|
public string Top { get; set; }
|
|
public string Width { get; set; }
|
|
public string Height { get; set; }
|
|
}
|
|
|
|
|
|
}
|