Finishing models

This commit is contained in:
Max 2023-06-10 20:27:26 +02:00
parent 13fd44bc72
commit 18e4135130
8 changed files with 40 additions and 38 deletions

View File

@ -43,9 +43,9 @@ namespace SharpRss
Id = reader["id"].ToString(), Id = reader["id"].ToString(),
Name = reader["name"].ToString(), Name = reader["name"].ToString(),
HexColor = reader["hex_color"].ToString(), HexColor = reader["hex_color"].ToString(),
FeedCount = 0, // Not implemented.
Icon = reader["icon"].ToString() Icon = reader["icon"].ToString()
}; };
categoryModel.FeedCount = await dbc.ExecuteScalarAsync<int>($"SELECT COUNT(*) FROM feed WHERE category_id=@CatId", new { CatId = categoryModel.Id });
categories.Add(categoryModel); categories.Add(categoryModel);
} }
return categories; return categories;
@ -125,7 +125,7 @@ namespace SharpRss
await using SqliteConnection dbc = new SqliteConnection(ConnectionString); await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open(); dbc.Open();
HashSet<FeedModel> feeds = new HashSet<FeedModel>(); HashSet<FeedModel> feeds = new HashSet<FeedModel>();
await using DbDataReader reader = await dbc.ExecuteReaderAsync(categoryIds == null ? "SELECT * FROM feed WHERE category_id == ''" : "SELECT * FROM feed WHERE category_id IN(@CatIds)", new { CatIds = categoryIds }); await using DbDataReader reader = await dbc.ExecuteReaderAsync(categoryIds == null ? "SELECT * FROM feed" : "SELECT * FROM feed WHERE category_id IN(@CatIds)", new { CatIds = categoryIds });
while (await reader.ReadAsync()) while (await reader.ReadAsync())
{ {
FeedModel feedModel = new FeedModel() FeedModel feedModel = new FeedModel()

View File

@ -6,17 +6,12 @@ namespace SharpRss.Models
{ {
public class CategoryModel public class CategoryModel
{ {
private string _id = string.Empty; public CategoryModel()
public string Id
{ {
get Id = Guid.NewGuid().ToString();
{
if (_id.IsNullEmptyWhiteSpace())
_id = Guid.NewGuid().ToString();
return _id;
}
set => _id = value;
} }
/*private string _id = string.Empty;*/
public string Id { get; set; }
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
private string _hexColor = string.Empty; private string _hexColor = string.Empty;
public string HexColor public string HexColor

View File

@ -70,8 +70,8 @@ namespace SharpRss.Services
var feeds = await GetFeedsAsync(); var feeds = await GetFeedsAsync();
} }
public async Task<HashSet<FeedModel>> GetFeedsAsync(string? groupId = null) => await DbAccess.GetFeedsAsync(); public async Task<HashSet<FeedModel>> GetFeedsAsync(string? categoryId = null) => await DbAccess.GetFeedsAsync(categoryId == null ? null : new[]{ categoryId });
public async Task<HashSet<FeedModel>> GetUngroupedFeedsAsync() => await DbAccess.GetFeedsAsync(); public async Task<HashSet<FeedModel>> GetUngroupedFeedsAsync() => await DbAccess.GetFeedsAsync(new []{""});
public async Task<HashSet<FeedItemModel>> GetFeedItemsAsync(string feedId, string? groupId = null) => await GetFeedItemsFromFeedsAsync(new[] { feedId }, groupId); public async Task<HashSet<FeedItemModel>> GetFeedItemsAsync(string feedId, string? groupId = null) => await GetFeedItemsFromFeedsAsync(new[] { feedId }, groupId);
public async Task<HashSet<FeedItemModel>> GetFeedItemsFromFeedsAsync(string[] feedIds, string? groupId = null) public async Task<HashSet<FeedItemModel>> GetFeedItemsFromFeedsAsync(string[] feedIds, string? groupId = null)
@ -94,7 +94,11 @@ namespace SharpRss.Services
} }
private async void SetupTestGroupsAndFeedsAsync() private async void SetupTestGroupsAndFeedsAsync()
{ {
/*await AddSubscriptionAsync("https://www.nu.nl/rss/Algemeen");*/ CategoryModel NewsCat = new CategoryModel() { Name = "News" };
await AddSubscriptionAsync("https://www.nu.nl/rss/Algemeen", NewsCat);
await AddSubscriptionAsync("https://www.nu.nl/rss/Economie", NewsCat);
await AddSubscriptionAsync("http://fedoramagazine.org/feed/");
await AddSubscriptionAsync("https://itsfoss.com/feed");
//TODO: Make multiple adding of feed to a transaction, now throws an exception. //TODO: Make multiple adding of feed to a transaction, now throws an exception.
/*var groupRes = await CreateGroupAsync(new GroupModel() { Name = "Test" }); /*var groupRes = await CreateGroupAsync(new GroupModel() { Name = "Test" });
groupRes = await CreateGroupAsync(new GroupModel() { Name = "News" }); groupRes = await CreateGroupAsync(new GroupModel() { Name = "News" });

View File

@ -69,7 +69,7 @@ namespace SharpRss
container.FeedModel.Description = rssFeed.Channel.Description ?? string.Empty; container.FeedModel.Description = rssFeed.Channel.Description ?? string.Empty;
container.FeedModel.Language = rssFeed.Channel.Language?.ToString() ?? string.Empty; container.FeedModel.Language = rssFeed.Channel.Language?.ToString() ?? string.Empty;
container.FeedModel.Copyright = rssFeed.Channel.Copyright ?? string.Empty; container.FeedModel.Copyright = rssFeed.Channel.Copyright ?? string.Empty;
container.FeedModel.PublicationDate = rssFeed.Channel.LastBuildDate is not { Ticks: > 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(rssFeed.Channel.LastBuildDate); container.FeedModel.PublicationDate = rssFeed.Channel.LastBuildDate is not { Ticks: > 0 } ? new DateTimeOffset(rssFeed.Channel.LastBuildDate) : DateTimeOffset.MinValue;
container.FeedModel.Categories = rssFeed.Channel.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>(); container.FeedModel.Categories = rssFeed.Channel.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>();
container.FeedModel.ImageUrl = rssFeed.Channel.Image?.Url.ToString() ?? string.Empty; container.FeedModel.ImageUrl = rssFeed.Channel.Image?.Url.ToString() ?? string.Empty;
foreach (var rssItem in rssFeed.Channel.Items) foreach (var rssItem in rssFeed.Channel.Items)
@ -82,7 +82,7 @@ namespace SharpRss
Title = rssItem.Title ?? string.Empty, Title = rssItem.Title ?? string.Empty,
Description = rssItem.Description ?? string.Empty, Description = rssItem.Description ?? string.Empty,
Link = rssItem.Link?.ToString() ?? string.Empty, Link = rssItem.Link?.ToString() ?? string.Empty,
PublishingDate = rssItem.PublicationDate is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(rssItem.PublicationDate), PublishingDate = rssItem.PublicationDate is not { Ticks: <= 0 } ? new DateTimeOffset(rssItem.PublicationDate) : DateTimeOffset.MinValue,
Authors = rssItem.Author != null ? new []{ rssItem.Author } : Array.Empty<string>(), Authors = rssItem.Author != null ? new []{ rssItem.Author } : Array.Empty<string>(),
Categories = rssItem.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>(), Categories = rssItem.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>(),
Content = rssItem.Extensions?.Where(x => x is SiteSummaryContentSyndicationExtension).Select(x => (x as SiteSummaryContentSyndicationExtension)?.Context.Encoded).FirstOrDefault() ?? string.Empty, Content = rssItem.Extensions?.Where(x => x is SiteSummaryContentSyndicationExtension).Select(x => (x as SiteSummaryContentSyndicationExtension)?.Context.Encoded).FirstOrDefault() ?? string.Empty,
@ -113,8 +113,8 @@ namespace SharpRss
Title = entry.Title?.Content ?? string.Empty, Title = entry.Title?.Content ?? string.Empty,
Description = entry.Summary?.Content ?? string.Empty, Description = entry.Summary?.Content ?? string.Empty,
Link = entry.Id?.Uri.ToString() ?? string.Empty, Link = entry.Id?.Uri.ToString() ?? string.Empty,
LastUpdated = entry.UpdatedOn is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(entry.UpdatedOn), LastUpdated = entry.UpdatedOn is not { Ticks: <= 0 } ? new DateTimeOffset(entry.UpdatedOn) : DateTimeOffset.MinValue,
PublishingDate = entry.PublishedOn is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(entry.PublishedOn), PublishingDate = entry.PublishedOn is not { Ticks: <= 0 } ? new DateTimeOffset(entry.PublishedOn) : DateTimeOffset.MinValue,
Authors = entry.Authors?.Select(auth => auth.Name).ToArray() ?? Array.Empty<string>(), Authors = entry.Authors?.Select(auth => auth.Name).ToArray() ?? Array.Empty<string>(),
Categories = entry.Categories?.Select(cat => cat.Label).ToArray() ?? Array.Empty<string>(), Categories = entry.Categories?.Select(cat => cat.Label).ToArray() ?? Array.Empty<string>(),
Content = entry.Content?.Content ?? string.Empty Content = entry.Content?.Content ?? string.Empty

View File

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using MudBlazor; using MudBlazor;
using SharpRss.Models; using SharpRss.Models;
using ToolQit; using ToolQit;
@ -8,12 +10,12 @@ namespace WebSharpRSS.Models
{ {
public class TreeItemData public class TreeItemData
{ {
public TreeItemData(CategoryModel groupModel) public TreeItemData(CategoryModel categoryModel)
{ {
GroupModel = groupModel; CategoryModel = categoryModel;
Title = groupModel.Name; Title = categoryModel.Name;
Icon = groupModel.Icon == string.Empty ? Icons.Material.Filled.RssFeed : groupModel.Icon; Icon = categoryModel.Icon == string.Empty ? Icons.Material.Filled.RssFeed : categoryModel.Icon;
HasChild = groupModel.FeedCount > 0; HasChildren = CategoryModel.FeedCount > 0;
} }
public TreeItemData(FeedModel feedModel) public TreeItemData(FeedModel feedModel)
@ -23,7 +25,7 @@ namespace WebSharpRSS.Models
if (FeedModel.OriginalUrl == null) return; if (FeedModel.OriginalUrl == null) return;
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(FeedModel.OriginalUrl).Host); FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(FeedModel.OriginalUrl).Host);
} }
public readonly CategoryModel? GroupModel; public readonly CategoryModel? CategoryModel;
public readonly FeedModel? FeedModel; public readonly FeedModel? FeedModel;
public HashSet<TreeItemData>? Children { get; set; } public HashSet<TreeItemData>? Children { get; set; }
@ -31,7 +33,7 @@ namespace WebSharpRSS.Models
public bool IsSelected { get; set; } public bool IsSelected { get; set; }
public string? Icon { get; set; } public string? Icon { get; set; }
public string? FaviconUrl { get; set; } public string? FaviconUrl { get; set; }
public bool HasChild { get; set; } public bool HasChildren { get; set; }
public bool Loading { get; set; } public bool Loading { get; set; }
public bool IsExpanded { get; set; } public bool IsExpanded { get; set; }
} }

View File

@ -33,17 +33,17 @@
} }
private string? _fid; private string? _fid;
[Parameter] [Parameter]
[SupplyParameterFromQuery(Name = "gid")] [SupplyParameterFromQuery(Name = "cid")]
public string? Gid public string? Cid
{ {
get => _gid; get => _cid;
set set
{ {
_gid = value; _cid = value;
LoadItems(); LoadItems();
} }
} }
private string? _gid; private string? _cid;
HashSet<FeedItemData> items = new HashSet<FeedItemData>(); HashSet<FeedItemData> items = new HashSet<FeedItemData>();
bool _isLoading = true; bool _isLoading = true;
private async void LoadItems() private async void LoadItems()
@ -54,9 +54,9 @@
var fItems = await _rssService.GetFeedItemsAsync(Fid); var fItems = await _rssService.GetFeedItemsAsync(Fid);
items = fItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet(); items = fItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
} }
else if (Gid != null) else if (Cid != null)
{ {
var feeds = await _rssService.GetFeedsAsync(Gid); var feeds = await _rssService.GetFeedsAsync(Cid == string.Empty ? null : Cid);
var feedIds = feeds.Select(x => x.OriginalUrl); var feedIds = feeds.Select(x => x.OriginalUrl);
var feedItems = await _rssService.GetFeedItemsFromFeedsAsync(feedIds.ToArray()); var feedItems = await _rssService.GetFeedItemsFromFeedsAsync(feedIds.ToArray());
items = feedItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet(); items = feedItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();

View File

@ -11,14 +11,14 @@
<MudStack Spacing="2"> <MudStack Spacing="2">
<MudTreeView Color="Color.Success" Items="_guideItems" @bind-SelectedValue="SelectedItem" Hover="true"> <MudTreeView Color="Color.Success" Items="_guideItems" @bind-SelectedValue="SelectedItem" Hover="true">
<ItemTemplate> <ItemTemplate>
<MudTreeViewItem @bind-Expanded="@context.IsExpanded" Value="@context" Items="@context.Children" CanExpand="@context.HasChild" @onclick="ItemClicked"> <MudTreeViewItem @bind-Expanded="@context.IsExpanded" Value="@context" Items="@context.Children" CanExpand="@context.HasChildren" @onclick="ItemClicked">
<Content> <Content>
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%"> <div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
<div style="justify-self: start;" class="d-flex align-center"> <div style="justify-self: start;" class="d-flex align-center">
<MudTreeViewItemToggleButton ExpandedChanged="@(() => ExpandedChanged(context))" Loading="@context.Loading" Visible="@context.HasChild" LoadingIconColor="Color.Info" /> <MudTreeViewItemToggleButton ExpandedChanged="@(() => ExpandedChanged(context))" Loading="@context.Loading" Visible="@context.HasChildren" LoadingIconColor="Color.Info" />
@if (context.FaviconUrl == null && context.Icon != null) @if (context.FaviconUrl == null && context.Icon != null)
{ {
<MudIcon Icon="@context.Icon" Style="@($"color:{context.GroupModel?.HexColor ?? _theme.Palette.Primary.Value}")"/> <MudIcon Icon="@context.Icon" Style="@($"color:{context.CategoryModel?.HexColor ?? _theme.Palette.Primary.Value}")"/>
} }
else else
{ {
@ -53,15 +53,15 @@
{ {
_navigation.NavigateTo($"/list?fid={_selectedItem.FeedModel.OriginalUrl}"); _navigation.NavigateTo($"/list?fid={_selectedItem.FeedModel.OriginalUrl}");
} }
else if (_selectedItem.GroupModel != null) else if (_selectedItem.CategoryModel != null)
{ {
_navigation.NavigateTo($"/list?gid={_selectedItem.GroupModel.Id}"); _navigation.NavigateTo($"/list?cid={_selectedItem.CategoryModel.Id}");
} }
} }
private async void ExpandedChanged(TreeItemData treeItemData) private async void ExpandedChanged(TreeItemData treeItemData)
{ {
treeItemData.Loading = true; treeItemData.Loading = true;
var groupedItems = await _rssService.GetFeedsAsync(treeItemData.GroupModel?.Id); var groupedItems = await _rssService.GetFeedsAsync(treeItemData.CategoryModel?.Id);
treeItemData.Children = ModelToTreeItem(groupedItems); treeItemData.Children = ModelToTreeItem(groupedItems);
treeItemData.IsExpanded = !treeItemData.IsExpanded; treeItemData.IsExpanded = !treeItemData.IsExpanded;
treeItemData.Loading = false; treeItemData.Loading = false;
@ -70,6 +70,7 @@
protected override async void OnInitialized() protected override async void OnInitialized()
{ {
Log.Verbose("Loading guide data..."); Log.Verbose("Loading guide data...");
_guideItems.Add(new TreeItemData(new CategoryModel() { Name = "All", Icon = Icons.Material.Filled.Home, HexColor = Colors.Blue.Accent1, Id = string.Empty }));
HashSet<object> items = await _rssService.GetCategoriesFeedsAsync(); HashSet<object> items = await _rssService.GetCategoriesFeedsAsync();
_guideItems.UnionWith(ModelToTreeItem(items)); _guideItems.UnionWith(ModelToTreeItem(items));

Binary file not shown.