SignalR message serialize, deserialize, toaster, messagehandler JS library

This commit is contained in:
Adam 2024-11-15 15:01:41 +01:00
parent 01bd971a80
commit 53abcb5a64
15 changed files with 396 additions and 63 deletions

View File

@ -1,9 +1,13 @@
using Microsoft.AspNetCore.Mvc;
using DocumentFormat.OpenXml.EMMA;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Nop.Plugin.Misc.AuctionPlugin.Areas.Admin.Models;
using Nop.Plugin.Misc.AuctionPlugin.Domains;
using Nop.Plugin.Misc.AuctionPlugin.Domains.Entities;
using Nop.Plugin.Misc.AuctionPlugin.Hubs;
using Nop.Plugin.Misc.AuctionPlugin.Hubs.Messages;
using Nop.Plugin.Misc.AuctionPlugin.Services;
using Nop.Services.Logging;
using Nop.Web.Framework;
@ -64,13 +68,67 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Areas.Admin.Controllers
if (viewModel.IsActive == true)
{
var announcement = new MessageBase
{
MessageType = "announcement",
Data = new AnnouncementMessage
{
Title = viewModel.Name,
Message = viewModel.Body,
}
};
var jsonMessage = JsonConvert.SerializeObject(announcement, Formatting.Indented,
new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
await _logger.InformationAsync($"sending announcements");
await _announcementHubContext.Clients.All.SendAsync("send", viewModel.Body.ToString());
await _announcementHubContext.Clients.All.SendAsync("send", jsonMessage);
//await _announcementHubContext.Clients.All.SendAsync("send", viewModel.Body.ToString());
}
return RedirectToAction("AnnouncementList");
}
public async Task<IActionResult> SendBidNotificationViewModel()
{
var viewModel = new BidNotificationViewModel();
viewModel.ProductName = "Picasso - Önarckép";
viewModel.BidPrice = 200000;
viewModel.NextStepAmount = 50000;
return View("~/Plugins/Misc.AuctionPlugin/Areas/Admin/Views/BidNotification.cshtml", viewModel);
}
[HttpPost]
public async Task<IActionResult> SendBidNotificationViewModel(BidNotificationViewModel viewModel)
{
AuctionBid objOfAuctionBid = new AuctionBid();
objOfAuctionBid.ProductId = 4;
objOfAuctionBid.BidPrice = viewModel.BidPrice;
objOfAuctionBid.Created = DateTime.UtcNow;
//await _announcementService.InsertAsync(objOfAuctionBid);
var bid = new MessageBase
{
MessageType = "bidNotification",
Data = new BidNotificationMessage
{
ProductName = viewModel.ProductName,
BidPrice = viewModel.BidPrice,
NextStepAmount = viewModel.NextStepAmount
}
};
var jsonMessage = JsonConvert.SerializeObject(bid, Formatting.Indented,
new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }
);
await _announcementHubContext.Clients.All.SendAsync("send", jsonMessage);
return View("~/Plugins/Misc.AuctionPlugin/Areas/Admin/Views/BidNotification.cshtml", viewModel);
}
[HttpPost]
public async Task<IActionResult> Edit(Announcement model)
{

View File

@ -0,0 +1,17 @@
using Nop.Web.Framework.Models;
using Nop.Web.Framework.Mvc.ModelBinding;
namespace Nop.Plugin.Misc.AuctionPlugin.Areas.Admin.Models
{
public record BidNotificationViewModel : BaseNopModel
{
[NopResourceDisplayName("Name")]
public string ProductName { get; set; }
public int BidPrice { get; set; }
public int NextStepAmount { get; set; }
}
}

View File

@ -0,0 +1,87 @@
@model BidNotificationViewModel
@using Nop.Core.Infrastructure
@using Nop.Web.Framework
@{
var defaultGridPageSize = EngineContext.Current.Resolve<Nop.Core.Domain.Common.AdminAreaSettings>().DefaultGridPageSize;
var gridPageSizes = EngineContext.Current.Resolve<Nop.Core.Domain.Common.AdminAreaSettings>().GridPageSizes;
Layout = "_AdminLayout";
//page title
ViewBag.Title = T("Admin.Plugins.HomePageProduct").Text;
}
@using (Html.BeginForm())
{
<div class="content-header clearfix">
<h1 class="pull-left">
Send BidNotification
</h1>
<div class="pull-right">
<button type="submit" class="btn bg-purple">
<i class="fa fa-file-pdf-o"></i>
Send BidNotification
</button>
</div>
</div>
<div class="content">
<div class="form-horizontal">
<div class="panel-group">
<div class="panel panel-default panel-search">
<div class="panel-body">
<div class="row">
<div class="form-group">
<div class="col-md-3" style="text-align:center;">
@Html.LabelFor(model => model.ProductName)
</div>
<div class="col-md-8">
@Html.EditorFor(model => model.ProductName)
</div>
<div class="col-md-1">
&nbsp;
</div>
</div>
<div class="form-group">
<div class="col-md-3" style="text-align:center;">
@Html.LabelFor(model => model.BidPrice)
</div>
<div class="col-md-8">
@Html.EditorFor(model => model.BidPrice)
</div>
<div class="col-md-1">
&nbsp;
</div>
</div>
<div class="form-group">
<div class="col-md-3" style="text-align:center;">
@Html.LabelFor(model => model.NextStepAmount)
</div>
<div class="col-md-8">
@Html.EditorFor(model => model.NextStepAmount)
</div>
<div class="col-md-1">
&nbsp;
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}

View File

@ -29,6 +29,7 @@ public static class AuctionDefaults
public static string AnnouncementListRouteName => "Plugin.Misc.AuctionPlugin.AnnouncementList";
public static string AuctionRouteName => "Plugin.Misc.AuctionPlugin.Auction";
public static string TestPageRouteName => "Plugin.Misc.AuctionPlugin.TestPage";
public static string BidNotificationRouteName => "Plugin.Misc.AuctionPlugin.BidNotification";
/// <summary>
/// Gets the name of autosuggest component

View File

@ -193,6 +193,14 @@ namespace Nop.Plugin.Misc.AuctionPlugin
Url = "~/Admin/AuctionPluginAdmin/TestPage"
});
liveAnnouncementPluginNode.ChildNodes.Add(new SiteMapNode()
{
Title = await _localizationService.GetResourceAsync("Misc.SendBid"),
Visible = true,
IconClass = "fa-dot-circle-o",
Url = "~/Admin/Announcement/SendBidNotificationViewModel"
});
}
}
}

View File

@ -1,12 +1,15 @@
$(function () {
// Define the message handler library
// SignalR connection setup
$(function () {
console.log("signalRJs Starts");
var connection = new signalR.HubConnectionBuilder()
.withUrl('/auctionhub')
.build();
connection.on('send', data => {
showannouncement(data);
MessageHandler.handle(data);
});
function start() {
@ -20,67 +23,97 @@
connection.onclose(function () {
start();
});
start();
});
function showannouncement(announcemant) {
console.log("announcement arrived!");
if (announcemant) {
toastr.options = {
"closeButton": true,
"debug": false,
"newestOnTop": false,
"progressBar": false,
"positionClass": "toast-bottom-right",
"preventDuplicates": false,
"onclick": null,
"showDuration": 300,
"hideDuration": 10000,
"timeOut": 100000,
"extendedTimeOut": 20000,
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
};
tostView = '<div class="item announcemantToast">' + announcemant + '</div>'
toastr["info"](tostView);
$('.toast-info').css("background-color", "#008080");
toastr.options.onclick = function () {
$("html, body").animate(
{ scrollTop: 0 },
1000);
}
//$(function () {
$(".toast").click(function () {
$("html, body").animate(
{ scrollTop: 0 },
1000);
});
// console.log("signalRJs Starts");
// var connection = new signalR.HubConnectionBuilder()
// .withUrl('/auctionhub')
// .build();
$(".toast-info").click(function () {
$("html, body").animate(
{ scrollTop: 0 },
1000);
});
// connection.on('send', data => {
// showannouncement(data);
// });
toastr.options = {
onclick: function () {
$("html, body").animate(
{ scrollTop: 0 },
1000);
}
}
// function start() {
// connection.start().catch(function (err) {
// setTimeout(function () {
// start();
// }, 100000);
// });
// }
$(".announcemantToast").on("click", function () {
$("html, body").animate(
{ scrollTop: 0 },
1000);
});
}
}
// connection.onclose(function () {
// start();
// });
// start();
//});
//function showannouncement(announcemant) {
// console.log("announcement arrived!");
// if (announcemant) {
// toastr.options = {
// "closeButton": true,
// "debug": false,
// "newestOnTop": false,
// "progressBar": false,
// "positionClass": "toast-bottom-right",
// "preventDuplicates": false,
// "onclick": null,
// "showDuration": 300,
// "hideDuration": 10000,
// "timeOut": 100000,
// "extendedTimeOut": 20000,
// "showEasing": "swing",
// "hideEasing": "linear",
// "showMethod": "fadeIn",
// "hideMethod": "fadeOut"
// };
// tostView = '<div class="item announcemantToast">' + announcemant + '</div>'
// toastr["info"](tostView);
// $('.toast-info').css("background-color", "#008080");
// toastr.options.onclick = function () {
// $("html, body").animate(
// { scrollTop: 0 },
// 1000);
// }
// $(".toast").click(function () {
// $("html, body").animate(
// { scrollTop: 0 },
// 1000);
// });
// $(".toast-info").click(function () {
// $("html, body").animate(
// { scrollTop: 0 },
// 1000);
// });
// toastr.options = {
// onclick: function () {
// $("html, body").animate(
// { scrollTop: 0 },
// 1000);
// }
// }
// $(".announcemantToast").on("click", function () {
// $("html, body").animate(
// { scrollTop: 0 },
// 1000);
// });
// }
//}

View File

@ -0,0 +1,71 @@
var MessageHandler = (function () {
// Handlers for each message type
let animation = "slideDown";
const handlers = {
announcement: function (data) {
toastr.info(`<div class="item announcemantToast">${data.message}</div>`, data.title, {
"closeButton": true,
"positionClass": "toast-bottom-right",
"newestOnTop": true,
"progressBar": true,
"preventDuplicates": false,
"onclick": null,
"showDuration": "30000",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": animation,
"hideMethod": "fadeOut"
});
$('.toast-info').css("background-color", "#008080");
},
bidNotification: function (data) {
//console.log("Bid product name" + data.productName);
toastr.success(`<div class="item bidToast"><p>${data.bidPrice}</p><p>${data.productName}</p></div>`, "New bid arrived", {
//"timeOut": 150000,
"closeButton": true,
"positionClass": "toast-bottom-right",
"newestOnTop": true,
"progressBar": true,
"preventDuplicates": false,
"onclick": null,
"showDuration": "30000",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": animation,
"hideMethod": "fadeOut"
});
$('.toast-success').css("background-color", "#4caf50");
},
// Add more handlers as needed
default: function (data) {
console.warn("Unhandled message type:", data);
}
};
// Message router to route to the appropriate handler based on message type
function messageRouter(message) {
// Parse the JSON message
try {
/*console.log(message);*/
const parsedMessage = JSON.parse(message);
const messageType = parsedMessage.messageType;
const messageData = parsedMessage.data;
console.log("Message type:" + messageType);
// Route to appropriate handler, default if no match
(handlers[messageType] || handlers.default)(messageData);
} catch (e) {
console.error("Error parsing message:", e);
}
}
return {
handle: messageRouter
};
})();

View File

@ -41,11 +41,11 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Hubs
//await _signalRservice.TestHub();
}
public async Task Send(string announcement)
{
await _logger.InformationAsync($" Hub Send method called with messgae: {announcement}");
await Clients.All.SendAsync("send", announcement);
}
//public async Task Send(string announcement)
//{
// await _logger.InformationAsync($" Hub Send method called with messgae: {announcement}");
// await Clients.All.SendAsync("send", announcement);
//}
public async Task SendPriceToUsers(string message)
{

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nop.Plugin.Misc.AuctionPlugin.Hubs.Messages
{
public class AnnouncementMessage
{
public string Title { get; set; }
public string Message { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nop.Plugin.Misc.AuctionPlugin.Hubs.Messages
{
public class BidNotificationMessage
{
public string ProductName { get; set; }
public int BidPrice { get; set; }
public int NextStepAmount { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nop.Plugin.Misc.AuctionPlugin.Hubs.Messages
{
public class MessageBase
{
public string MessageType { get; set; }
public object Data { get; set; }
}
}

View File

@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -15,6 +16,7 @@ using Nop.Services.Catalog;
using Nop.Services.Configuration;
using Nop.Services.Localization;
using Nop.Web.Framework;
using Nop.Web.Framework.Mvc.Routing;
namespace Nop.Plugin.Misc.AuctionPlugin.Infrastructure
{
@ -51,7 +53,8 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Infrastructure
services.AddScoped<IAuctionService, AuctionService>();
services.AddScoped<IProductAttributeService, ProductAttributeService>();
services.AddScoped<UrlHelperFactory>();
services.AddScoped<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped<IRouteProvider, RouteProvider>();
}
/// <summary>

View File

@ -37,6 +37,10 @@ namespace Nop.Plugin.Misc.AuctionPlugin.Infrastructure
endpointRouteBuilder.MapControllerRoute(name: AuctionDefaults.TestPageRouteName,
pattern: "Admin/Auction/TestPage",
defaults: new { controller = "AuctionPluginAdmin", action = "TestPage" });
endpointRouteBuilder.MapControllerRoute(name: AuctionDefaults.BidNotificationRouteName,
pattern: "Admin/Announcement/SendBidNotificationViewModel",
defaults: new { controller = "Announcement", action = "SendBidNotificationViewModel" });
}

View File

@ -14,6 +14,7 @@
<ItemGroup>
<None Remove="Areas\Admin\Views\Auction.cshtml" />
<None Remove="Areas\Admin\Views\BidNotification.cshtml" />
<None Remove="Areas\Admin\Views\TestPage.cshtml" />
<None Remove="logo.jpg" />
<None Remove="plugin.json" />
@ -29,6 +30,9 @@
</ItemGroup>
<ItemGroup>
<Content Include="Areas\Admin\Views\BidNotification.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Areas\Admin\Views\TestPage.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@ -100,6 +104,9 @@
<None Update="Content\Css\toastr.min.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Content\Js\MgMessageHandler.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Content\Js\LiveAnnouncement.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

View File

@ -11,6 +11,7 @@
IStoreContext _storeContext = EngineContext.Current.Resolve<IStoreContext>();
NopHtml.AddScriptParts(ResourceLocation.Head, "~/Plugins/Misc.AuctionPlugin/Content/Js/signalr.js");
NopHtml.AddScriptParts(ResourceLocation.Footer, "~/Plugins/Misc.AuctionPlugin/Content/Js/MgMessageHandler.js");
NopHtml.AddScriptParts(ResourceLocation.Footer, "~/Plugins/Misc.AuctionPlugin/Content/Js/LiveAnnouncement.js");
NopHtml.AddCssFileParts("~/Plugins/Misc.AuctionPlugin/Content/Css/toastr.min.css");
NopHtml.AddScriptParts(ResourceLocation.Footer, "~/Plugins/Misc.AuctionPlugin/Content/Js/toastr.js");