Reworking UI and simple dashboard implementation

This commit is contained in:
Max 2023-06-25 22:02:15 +02:00
parent 3cc8838c23
commit 0b35c32fe1
10 changed files with 120 additions and 34 deletions

View File

@ -12,7 +12,6 @@ using SharpRss.Models;
namespace SharpRss
{
//TODO: Need rework to only get from db syndication service will handle extra data.
internal static class DbAccess
{
private static readonly string ConnectionString = $"Data Source={Path.Combine(Environment.CurrentDirectory, "sharp_rss.sqlite")};";

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Argotic.Common;
using Argotic.Syndication;
@ -10,14 +9,14 @@ using SharpRss.Models;
namespace SharpRss.Services
{
/// <summary>
/// Managing feeds and categories.
/// Managing syndication feeds and categories.
/// </summary>
public class SyndicationService
{
public SyndicationService()
{
Log.Information("Constructing SyndicationService...");
SetupTestCategoriesAndFeedsAsync();
Task.Run(async () => await SetupTestCategoriesAndFeedsAsync());
}
public async Task<HashSet<object>> GetCategoriesAndSyndicationsAsync()
@ -59,16 +58,16 @@ namespace SharpRss.Services
}
catch (Exception e)
{
Log.Error(e,"Error adding feed: {FeedUrl} to database!", url);
Log.Error(e,"Error adding syndication: {FeedUrl} to database!", url);
}
return true;
}
public async Task UpdateFeeds()
{
Log.Information("Fetching feeds...");
var feeds = await GetFeedsAsync();
Log.Information("Fetching...");
var feeds = await GetSyndicationsAsync();
}
public async Task<HashSet<SyndicationModel>> GetFeedsAsync(string? categoryId = null) => await DbAccess.GetSyndicationsAsync(categoryId == null ? null : new[]{ categoryId });
public async Task<HashSet<SyndicationModel>> GetSyndicationsAsync(string? categoryId = null) => await DbAccess.GetSyndicationsAsync(categoryId == null ? null : new[]{ categoryId });
public async Task<HashSet<SyndicationModel>> GetUngroupedSyndicationsAsync() => await DbAccess.GetSyndicationsAsync(new []{""});
public async Task<HashSet<SyndicationItemModel>> GetSyndicationItemsAsync(string feedId, string? groupId = null) => await GetSyndicationItemsFromSyndicationsAsync(new[] { feedId }, groupId);
public async Task<HashSet<SyndicationItemModel>> GetSyndicationItemsFromSyndicationsAsync(string[] feedIds, string? categoryId = null)
@ -98,24 +97,24 @@ namespace SharpRss.Services
AtomFeed atomFeed = (AtomFeed)resource;
break;
default:
Log.Information("Feed implementation missing!");
Log.Information("Syndication implementation missing!");
break;
}
return model;
}
private GenericSyndicationFeed? CreateFeed(string url)
private GenericSyndicationFeed? CreateSyndication(string url)
{
Uri feedUri = new Uri(url);
Log.Verbose("Checking feed: {FeedUrl}", feedUri.ToString());
Log.Verbose("Checking syndication: {FeedUrl}", feedUri.ToString());
if (!SyndicationDiscoveryUtility.UriExists(feedUri))
{
Log.Warning("Feed: {FeedUri} does not exists!", feedUri.ToString());
Log.Warning("Syndication: {FeedUri} does not exists!", feedUri.ToString());
return null;
}
Log.Verbose("Fetching feed: {FeedUrl}", feedUri.ToString());
Log.Verbose("Fetching syndication: {FeedUrl}", feedUri.ToString());
return GenericSyndicationFeed.Create(new Uri(url));
}
private async void SetupTestCategoriesAndFeedsAsync()
private async Task SetupTestCategoriesAndFeedsAsync()
{
Log.Information("Setting up test data...");
try

View File

@ -1,3 +1,5 @@
@using System.Drawing
@using Color = MudBlazor.Color
@inherits LayoutComponentBase
<MudThemeProvider @bind-IsDarkMode="@_darkTheme" Theme="_mainTheme"/>
@ -27,6 +29,10 @@
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" Href="https://github.com/hmaxnl/SharpRSS" Target="_blank"></MudIconButton>
</MudAppBar>
<MudDrawer @bind-Open="@_drawerOpen" ClipMode="DrawerClipMode.Always">
<MudNavMenu>
<MudNavLink Href="/" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
<MudNavLink Href="/list?cid=" Icon="@Icons.Material.Filled.Power">All</MudNavLink>
</MudNavMenu>
<SideGuide/>
</MudDrawer>
<MudMainContent>

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using MudBlazor;
using SharpRss;

View File

@ -1,14 +1,38 @@
@page "/"
@page "/dashboard"
@using WebSharpRSS.Models;
@using SharpRss.Models
@using SharpRss.Services
@inject FeedStateContainer _stateContainer;
@inject SyndicationService _service;
<MudText>Dashboard!</MudText>
<MudGrid Spacing="2" Class="ml-2 mr-2">
<MudGrid Spacing="2" Class="mx-2" Justify="Justify.FlexStart">
@if (_loading)
{
<MudProgressCircular Indeterminate="true" Color="Color.Primary"/>
}
else
{
@foreach (CategoryModel category in _categories)
{
<MudItem>
<DashboardCategoryItemView Category="category"/>
</MudItem>
}
}
</MudGrid>
@code {
bool _loading = true;
HashSet<CategoryModel> _categories = new HashSet<CategoryModel>();
protected override async void OnInitialized()
{
await _service.GetCategoriesAsync().ContinueWith(task =>
{
_categories = task.Result;
_loading = false;
});
}
}

View File

@ -8,9 +8,11 @@
<div>
@if (_isLoading)
{
<div class="justify-self: center">
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
<MudText>Loading...</MudText>
<div class="d-flex justify-center">
<div>
<MudProgressCircular Class="d-block" Color="Color.Primary" Indeterminate="true" Size="Size.Large"/>
<MudText Class="d-block">Loading...</MudText>
</div>
</div>
}
else
@ -28,7 +30,7 @@
set
{
_fid = value;
LoadItems();
Task.Run(async () => await LoadItems());
}
}
private string? _fid;
@ -40,13 +42,13 @@
set
{
_cid = value;
LoadItems();
Task.Run(async () => await LoadItems());
}
}
private string? _cid;
HashSet<SyndicationItemData> items = new HashSet<SyndicationItemData>();
bool _isLoading = true;
private async void LoadItems()
private async Task LoadItems()
{
_isLoading = true;
if (Fid != null)
@ -56,16 +58,12 @@
}
else if (Cid != null)
{
var feeds = await _syndicationService.GetFeedsAsync(Cid == string.Empty ? null : Cid);
var feeds = await _syndicationService.GetSyndicationsAsync(Cid == string.Empty ? null : Cid);
var feedIds = feeds.Select(x => x.EncodedUrl);
var feedItems = await _syndicationService.GetSyndicationItemsFromSyndicationsAsync(feedIds.ToArray());
items = feedItems.Select(x => SyndicationItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
}
_isLoading = false;
StateHasChanged();
}
protected override void OnInitialized()
{
LoadItems();
await InvokeAsync(StateHasChanged);
}
}

View File

@ -14,7 +14,7 @@
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered"/>
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered"/>
<component type="typeof(App)" render-mode="Server"/>
<div id="blazor-error-ui">
<environment include="Staging,Production">

View File

@ -0,0 +1,62 @@
@using SharpRss.Models
@using SharpRss.Services
@using WebSharpRSS.Models
@using Serilog
@inject SyndicationService _service;
<MudPaper Height="100%" Width="80vh">
@if (Category != null)
{
<div style="justify-self: start;" class="d-flex align-center my-2">
<MudIcon Icon="@Category.Icon" Style="@($"color:{Category.HexColor}")" Class="mx-2"/>
<MudText>@Category.Name</MudText>
</div>
<MudDivider/>
@if (_isLoading)
{
<div class="d-flex justify-center">
<div>
<MudProgressCircular Class="d-block" Color="Color.Primary" Indeterminate="true"/>
<MudText Class="d-block">Loading...</MudText>
</div>
</div>
}
else
{
<div style="display: flex; height: 80vh; overflow-y: scroll">
<SyndicationListItem Items="@items"/>
</div>
}
}
else
{
<MudText>Could not load data!</MudText>
}
</MudPaper>
@code {
[Parameter]
public CategoryModel? Category { get; set; }
bool _isLoading = true;
HashSet<SyndicationItemData> items = new HashSet<SyndicationItemData>();
async Task LoadDataAsync()
{
if (Category == null)
{
Log.Warning("Category is null!");
return;
}
_isLoading = true;
var syndicationIds = Category.Syndications.Select(x => x.EncodedUrl);
var syndicationItems = await _service.GetSyndicationItemsFromSyndicationsAsync(syndicationIds.ToArray());
items = syndicationItems.Select(x => SyndicationItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
_isLoading = false;
}
protected override void OnInitialized()
{
Task.Run(async () => await LoadDataAsync()).ContinueWith(async t => await InvokeAsync(StateHasChanged));
}
}

View File

@ -15,7 +15,7 @@
<Content>
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
<div class="d-flex align-center">
<MudTreeViewItemToggleButton ExpandedChanged="@(() => ExpandedChanged(context))" Loading="@context.Loading" Visible="@context.HasChildren" LoadingIconColor="Color.Info" />
<MudTreeViewItemToggleButton ExpandedChanged="@(() => ExpandedChanged(context))" Loading="@context.Loading" Visible="@context.HasChildren" LoadingIconColor="Color.Info"/>
@if (context.FaviconUrl == null && context.Icon != null)
{
<MudIcon Icon="@context.Icon" Style="@($"color:{context.CategoryModel?.HexColor ?? _theme.Palette.Primary.Value}")"/>
@ -71,7 +71,6 @@
protected override async void OnInitialized()
{
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 _syndicationService.GetCategoriesAndSyndicationsAsync();
_guideItems.UnionWith(ModelToTreeItem(items));

Binary file not shown.