diff --git a/src/TagzApp.Common/ISocialMediaProvider.cs b/src/TagzApp.Common/ISocialMediaProvider.cs index b719e394..b8c3987d 100644 --- a/src/TagzApp.Common/ISocialMediaProvider.cs +++ b/src/TagzApp.Common/ISocialMediaProvider.cs @@ -16,6 +16,8 @@ public interface ISocialMediaProvider /// string DisplayName { get; } + virtual string DllName => DisplayName; + /// /// Provider description /// diff --git a/src/TagzApp.Common/Models/Creator.cs b/src/TagzApp.Common/Models/Creator.cs index f03a3b1d..11d04fad 100644 --- a/src/TagzApp.Common/Models/Creator.cs +++ b/src/TagzApp.Common/Models/Creator.cs @@ -20,7 +20,7 @@ public class Creator /// /// Uri to the profile of the creator /// - public required Uri ProfileUri { get; set; } + public required Uri ProfileUri { get; set; } = new Uri("/img/user.jpg", UriKind.Relative); /// /// Uri to the profile image of the creator diff --git a/src/TagzApp.Providers.AzureQueue/AzureQueueConfiguration.cs b/src/TagzApp.Providers.AzureQueue/AzureQueueConfiguration.cs new file mode 100644 index 00000000..797e57b2 --- /dev/null +++ b/src/TagzApp.Providers.AzureQueue/AzureQueueConfiguration.cs @@ -0,0 +1,11 @@ +namespace TagzApp.Providers.AzureQueue; + +public class AzureQueueConfiguration +{ + + public string QueueConnectionString { get; set; } = string.Empty; + + public bool Activated { get; set; } + +} + diff --git a/src/TagzApp.Providers.AzureQueue/AzureQueueProvider.cs b/src/TagzApp.Providers.AzureQueue/AzureQueueProvider.cs new file mode 100644 index 00000000..3b316f13 --- /dev/null +++ b/src/TagzApp.Providers.AzureQueue/AzureQueueProvider.cs @@ -0,0 +1,77 @@ +using Azure.Storage.Queues; +using System.Text.Json; + +namespace TagzApp.Providers.AzureQueue; + +public class AzureQueueProvider : ISocialMediaProvider +{ + private const string QueueName = "tagzapp-content"; + private readonly AzureQueueConfiguration _Configuration; + private QueueClient _Client; + private SocialMediaStatus _Status = SocialMediaStatus.Unhealthy; + private string _StatusMessage = "Not started"; + + public string Id => "WEBSITE"; + public string DisplayName => "Website"; + public string DllName { get { return "AzureQueue"; } } + public string Description => "Q+A submitted through a website form"; + public TimeSpan NewContentRetrievalFrequency => TimeSpan.FromSeconds(5); + + public AzureQueueProvider(AzureQueueConfiguration configuration) + { + _Configuration = configuration; + } + + + public async Task> GetContentForHashtag(Hashtag tag, DateTimeOffset since) + { + + var messageResponse = await _Client.ReceiveMessagesAsync(maxMessages: 10); + if (!messageResponse.Value.Any()) return Enumerable.Empty(); + + var outList = new List(); + + foreach (var msg in messageResponse.Value) + { + + var content = JsonSerializer.Deserialize(msg.Body.ToStream()); + if (content is not null) + { + content.HashtagSought = tag.Text.ToLowerInvariant(); + outList.Add(content); + await _Client.DeleteMessageAsync(msg.MessageId, msg.PopReceipt); + } + + } + + return outList; + + + } + + public Task<(SocialMediaStatus Status, string Message)> GetHealth() + { + return Task.FromResult((_Status, _StatusMessage)); + } + + public async Task StartAsync() + { + + _Client = new QueueClient(_Configuration.QueueConnectionString, QueueName); + + try + { + await _Client.CreateIfNotExistsAsync(); + } + catch (Exception ex) + { + _Status = SocialMediaStatus.Unhealthy; + _StatusMessage = $"Unable to start a connection to the Azure Queue: {ex.Message}"; + return; + } + + _Status = SocialMediaStatus.Healthy; + _StatusMessage = "Connected"; + + } +} diff --git a/src/TagzApp.Providers.AzureQueue/StartAzureQueue.cs b/src/TagzApp.Providers.AzureQueue/StartAzureQueue.cs new file mode 100644 index 00000000..871c265c --- /dev/null +++ b/src/TagzApp.Providers.AzureQueue/StartAzureQueue.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.DependencyInjection; +using TagzApp.Communication; + +namespace TagzApp.Providers.AzureQueue; + +public class StartAzureQueue : BaseConfigurationProvider, IConfigureProvider +{ + + private AzureQueueConfiguration _azureQueueConfiguration; + + public StartAzureQueue(IProviderConfigurationRepository providerConfigurationRepository) : base(providerConfigurationRepository) + { + } + + public async Task RegisterServices(IServiceCollection services, CancellationToken cancellationToken = default) + { + await LoadConfigurationValuesAsync("WEBSITE", cancellationToken); + + services.AddSingleton(_azureQueueConfiguration ?? new()); + services.AddTransient(); + return services; + } + + protected override void MapConfigurationValues(ProviderConfiguration providerConfiguration) + { + + var config = providerConfiguration.ConfigurationSettings; + + if (config != null) + { + _azureQueueConfiguration = new() + { + Activated = providerConfiguration.Activated, + QueueConnectionString = config["QueueConnectionString"] ?? string.Empty + }; + } + + } + +} diff --git a/src/TagzApp.Providers.AzureQueue/TagzApp.Providers.AzureQueue.csproj b/src/TagzApp.Providers.AzureQueue/TagzApp.Providers.AzureQueue.csproj new file mode 100644 index 00000000..924ab4a7 --- /dev/null +++ b/src/TagzApp.Providers.AzureQueue/TagzApp.Providers.AzureQueue.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/src/TagzApp.Web/Areas/Admin/Pages/Providers.cshtml b/src/TagzApp.Web/Areas/Admin/Pages/Providers.cshtml index 915f2462..6a58282a 100644 --- a/src/TagzApp.Web/Areas/Admin/Pages/Providers.cshtml +++ b/src/TagzApp.Web/Areas/Admin/Pages/Providers.cshtml @@ -12,7 +12,7 @@

Provider Management

- @foreach (var provider in Model.Providers) + @foreach (var provider in Model.Providers.OrderBy(p => p.DisplayName)) { var health = await provider.GetHealth(); @@ -41,7 +41,7 @@

Please fill in the configuration values below:

- @foreach (var property in vmUtilities.LoadViewModel(provider.DisplayName) ?? new System.Reflection.PropertyInfo[0]) + @foreach (var property in vmUtilities.LoadViewModel(provider.DllName) ?? new System.Reflection.PropertyInfo[0]) { var displayName = vmUtilities.GetDisplayName(property); displayName = string.IsNullOrWhiteSpace(displayName) ? property.Name : displayName; diff --git a/src/TagzApp.Web/Pages/Overlay.cshtml b/src/TagzApp.Web/Pages/Overlay.cshtml index 54a96356..e0502c2d 100644 --- a/src/TagzApp.Web/Pages/Overlay.cshtml +++ b/src/TagzApp.Web/Pages/Overlay.cshtml @@ -57,7 +57,7 @@ overlayDisplay.className = "begin"; overlayDisplay.innerHTML = ` - ${content.authorDisplayName} + ${content.authorDisplayName}