Skip to content

Commit ff436c5

Browse files
Adding the correct version of plugin
Adding the correct version of the plugin
1 parent 523675f commit ff436c5

File tree

48 files changed

+17161
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+17161
-0
lines changed

Nop.Plugin.Widgets.AzPersonalizer/.editorconfig

Lines changed: 551 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
namespace Nop.Plugin.Widgets.AzPersonalizer
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Threading.Tasks;
6+
using Nop.Core;
7+
using Nop.Services.Cms;
8+
using Nop.Services.Configuration;
9+
using Nop.Services.Localization;
10+
using Nop.Services.Logging;
11+
using Nop.Services.Plugins;
12+
using Nop.Web.Framework.Infrastructure;
13+
14+
/// <summary>
15+
/// Represents the plugin implementation
16+
/// </summary>
17+
public class AzPersonalizerPlugin : BasePlugin, IWidgetPlugin
18+
{
19+
20+
#region fields
21+
22+
private readonly ILocalizationService _localizationService;
23+
private readonly ISettingService _settingService;
24+
private readonly IWebHelper _webHelper;
25+
private readonly ILogger _logger;
26+
27+
#endregion
28+
29+
#region ctor
30+
31+
public AzPersonalizerPlugin (ILocalizationService localizationService,
32+
ISettingService settingService,
33+
IWebHelper webHelper,
34+
ILogger logger)
35+
{
36+
_localizationService = localizationService;
37+
_logger = logger;
38+
_settingService = settingService;
39+
_webHelper = webHelper;
40+
}
41+
42+
#endregion
43+
44+
#region methods
45+
46+
/// <summary>
47+
/// Gets widget zones where this widget should be rendered
48+
/// </summary>
49+
/// <returns>
50+
/// A task that represents the asynchronous operation
51+
/// The task result contains the widget zones
52+
/// </returns>
53+
public Task<IList<string>> GetWidgetZonesAsync () =>
54+
Task.FromResult<IList<string>>(new List<string> {PublicWidgetZones.ProductDetailsEssentialBottom});
55+
56+
/// <summary>
57+
/// Gets a configuration page URL
58+
/// </summary>
59+
public override string GetConfigurationPageUrl () =>
60+
_webHelper.GetStoreLocation() + "Admin/AzPersonalizer/Configure";
61+
62+
/// <summary>
63+
/// Gets a name of a view component for displaying widget
64+
/// </summary>
65+
/// <param name="widgetZone">Name of the widget zone</param>
66+
/// <returns>View component name</returns>
67+
public string GetWidgetViewComponentName (string widgetZone) => "WidgetsAzPersonalizer";
68+
69+
/// <summary>
70+
/// Install plugin
71+
/// </summary>
72+
/// <returns>A task that represents the asynchronous operation</returns>
73+
public async override Task InstallAsync ()
74+
{
75+
//settings
76+
AzPersonalizerSettings settings = new() {APIkey = "", Endpoint = ""};
77+
try
78+
{
79+
await _settingService.SaveSettingAsync(settings);
80+
81+
await _localizationService.AddLocaleResourceAsync(new Dictionary<string, string> {
82+
["Plugins.Widgets.AzPersonalizer.ApiKey"] = "Api key",
83+
["Plugins.Widgets.AzPersonalizer.Endpoint"] = "Endpoint"
84+
});
85+
await base.InstallAsync();
86+
}
87+
catch (Exception e)
88+
{
89+
await _logger.ErrorAsync($"failed to install plugin. Cause is Exception:{e.Message}", e);
90+
}
91+
}
92+
93+
/// <summary>
94+
/// Uninstall plugin
95+
/// </summary>
96+
/// <returns>A task that represents the asynchronous operation</returns>
97+
public async override Task UninstallAsync ()
98+
{
99+
try
100+
{
101+
//settings
102+
await _settingService.DeleteSettingAsync<AzPersonalizerSettings>();
103+
104+
//locales
105+
await _localizationService.DeleteLocaleResourcesAsync("Plugins.Widgets.AzPersonalizer");
106+
107+
await base.UninstallAsync();
108+
}
109+
catch (Exception e)
110+
{
111+
await _logger.ErrorAsync($"failed to install plugin. Cause is Exception:{e.Message}", e);
112+
}
113+
}
114+
115+
/// <summary>
116+
/// Gets a value indicating whether to hide this plugin on the widget list page in the admin area
117+
/// </summary>
118+
public bool HideInWidgetList
119+
{
120+
get
121+
{
122+
return false;
123+
}
124+
}
125+
126+
#endregion
127+
}
128+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace Nop.Plugin.Widgets.AzPersonalizer
2+
{
3+
using Nop.Core.Configuration;
4+
5+
/// <summary>
6+
/// Represents plugin settings
7+
/// </summary>
8+
public class AzPersonalizerSettings : ISettings
9+
{
10+
/// <summary>
11+
/// Gets or sets the azure personalizer resource Api key
12+
/// </summary>
13+
public string APIkey { get; set; }
14+
15+
/// <summary>
16+
/// Gets or sets the azure personalizer resource endpoint
17+
/// </summary>
18+
public string Endpoint { get; set; }
19+
}
20+
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
namespace Nop.Plugin.Widgets.AzPersonalizer.Components
2+
{
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Globalization;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
using Microsoft.AspNetCore.Mvc;
11+
using Microsoft.Azure.CognitiveServices.Personalizer.Models;
12+
using Nop.Core;
13+
using Nop.Core.Domain.Catalog;
14+
using Nop.Core.Domain.Logging;
15+
using Nop.Plugin.Widgets.AzPersonalizer.Controllers;
16+
using Nop.Plugin.Widgets.AzPersonalizer.Models;
17+
using Nop.Plugin.Widgets.AzPersonalizer.Services;
18+
using Nop.Services.Catalog;
19+
using Nop.Services.Logging;
20+
using Nop.Web.Factories;
21+
using Nop.Web.Framework.Components;
22+
using Nop.Web.Framework.Infrastructure;
23+
using Nop.Web.Models.Catalog;
24+
25+
/// <summary>
26+
/// Represents the view component to place a widget into pages
27+
/// </summary>
28+
[ViewComponent(Name = "WidgetsAzPersonalizer")]
29+
public class WidgetsAzPersonalizerViewComponent : NopViewComponent
30+
{
31+
32+
#region fields
33+
34+
private readonly IWebHelper _webHelper;
35+
private readonly IProductService _productService;
36+
private readonly IProductModelFactory _productModelFactory;
37+
private readonly ILogger _logger;
38+
private readonly PersonalizerClientService _personalizerClientService;
39+
40+
#endregion
41+
42+
#region ctor
43+
44+
public WidgetsAzPersonalizerViewComponent (PersonalizerClientService personalizerClientService,
45+
IProductService productService,
46+
IProductModelFactory productModelFactory,
47+
IWebHelper webHelper,
48+
ILogger logger)
49+
{
50+
_logger = logger;
51+
_webHelper = webHelper;
52+
_personalizerClientService = personalizerClientService;
53+
_productService = productService;
54+
_productModelFactory = productModelFactory;
55+
}
56+
57+
#endregion
58+
59+
#region methods
60+
61+
/// <summary>
62+
/// Invoke view component
63+
/// </summary>
64+
/// <param name="widgetZone">Widget zone name</param>
65+
/// <param name="additionalData">Additional data</param>
66+
/// <returns>
67+
/// A task that represents the asynchronous operation
68+
/// The task result contains the view component result
69+
/// </returns
70+
public async Task<IViewComponentResult> InvokeAsync (string widgetZone, object additionalData)
71+
{
72+
if (widgetZone == null)
73+
{
74+
await _logger.ErrorAsync("Widget Zone was null");
75+
throw new ArgumentNullException(widgetZone);
76+
}
77+
78+
if (widgetZone.Equals(PublicWidgetZones.ProductDetailsEssentialBottom,
79+
StringComparison.InvariantCultureIgnoreCase))
80+
{
81+
try
82+
{
83+
string[] url = _webHelper.GetThisPageUrl(true)?.Split("?");
84+
if (TempData["RewardID"] != null
85+
&& TempData["OrderedIDs"] != null)
86+
{
87+
string id = TempData["RewardID"] is string rewardID ? rewardID : null;
88+
string pos = TempData["OrderedIDs"] is string position ? position : null;
89+
90+
await ProcessRewardAsync(id, pos, additionalData);
91+
}
92+
93+
IViewComponentResult list = await RecommendedListAsync(additionalData);
94+
if (list == null)
95+
{
96+
await _logger.ErrorAsync("Confirm everything is corret in the plugin settings.");
97+
return View("~/Plugins/Widgets.AzPersonalizer/Views/Default.cshtml");
98+
}
99+
100+
return list;
101+
}
102+
catch (Exception e)
103+
{
104+
await _logger.ErrorAsync(e.Message, e);
105+
return View("~/Plugins/Widgets.AzPersonalizer/Views/Default.cshtml");
106+
}
107+
}
108+
109+
// While there is only one widget zone in the plugin this shouldn't return anything. If you want to add
110+
// recommendations to multiple widget zones, then you should make this an else if and return the appropriate view.
111+
return View("~/Plugins/Widgets.AzPersonalizer/Views/Default.cshtml");
112+
}
113+
114+
115+
/// <summary>
116+
/// Prepares the view component with a list of Ranked Actions
117+
/// </summary>
118+
/// <param name="azPersonalizerSettings"></param>
119+
/// <param name="additionalData"></param>
120+
/// <returns>
121+
/// A task that represents the asynchronous operation
122+
/// The task result contains the view component result
123+
/// </returns>
124+
private async Task<IViewComponentResult> RecommendedListAsync (object additionalData)
125+
{
126+
try
127+
{
128+
RankResponse rankedActions =
129+
await _personalizerClientService?.GetRankedActionsAsync(additionalData);
130+
IList<RankedAction> model = rankedActions.Ranking.OrderByDescending(r => r.Probability).ToList();
131+
TempDataTokenController tdt = new(rankedActions.EventId);
132+
TempData["RewardID"] = rankedActions.EventId;
133+
IList<Product> products = new List<Product>(model.Count);
134+
StringBuilder odds = new(rankedActions.EventId + ": ");
135+
136+
for (int i = 0; i < model.Count; i++)
137+
{
138+
odds.Append("(" + model[i]?.Id + "," + model[i].Probability + ");");
139+
products.Insert(i,
140+
await _productService?.GetProductByIdAsync(int.Parse(model[i]?.Id,
141+
new CultureInfo("en-UK"))));
142+
tdt.AddId(model[i]?.Id);
143+
}
144+
145+
TempData["OrderedIDs"] = tdt.OrderedIDs;
146+
147+
await _logger.InsertLogAsync(LogLevel.Debug, odds.ToString());
148+
149+
return View("~/Plugins/Widgets.AzPersonalizer/Views/Recommendations.cshtml",
150+
new ProductOverviewToRankingList(
151+
(await _productModelFactory.PrepareProductOverviewModelsAsync(products)).ToList(),
152+
rankedActions.EventId));
153+
}
154+
catch (Exception e)
155+
{
156+
await _logger.ErrorAsync(
157+
$"Failed to get recommendations: Exception type:{e.GetType()} and message:{e.Message}", e);
158+
return null;
159+
}
160+
}
161+
162+
/// <summary>
163+
/// Calculates and sends a reward to a given Event.
164+
/// </summary>
165+
/// <param name="ID"></param>
166+
/// <param name="orderIDs"></param>
167+
/// <param name="additionalData"></param>
168+
/// <returns>An empty task.</returns>
169+
private async Task ProcessRewardAsync (string eventID, string orderIDs, object additionalData)
170+
{
171+
try
172+
{
173+
ProductDetailsModel product = additionalData is ProductDetailsModel model ? model : null;
174+
if (string.IsNullOrEmpty(eventID) || string.IsNullOrEmpty(orderIDs) || product == null)
175+
{
176+
return;
177+
}
178+
179+
string[] products = orderIDs.Split("-");
180+
for (int i = 0; i < products.Length; i++)
181+
{
182+
if (products[i].Equals(product.Id.ToString(new CultureInfo("en-UK")),
183+
StringComparison.InvariantCultureIgnoreCase))
184+
{
185+
await _personalizerClientService.RewardAnActionAsync(eventID, i);
186+
return;
187+
}
188+
}
189+
}
190+
catch (Exception e)
191+
{
192+
await _logger.ErrorAsync($"Failed to reward event with EventId:{eventID}", e);
193+
}
194+
}
195+
196+
#endregion
197+
}
198+
}

0 commit comments

Comments
 (0)