diff --git a/src/Artemis.UI/Screens/Workshop/Categories/CategoriesView.axaml b/src/Artemis.UI/Screens/Workshop/Categories/CategoriesView.axaml
index a9072633d..d629cc7d3 100644
--- a/src/Artemis.UI/Screens/Workshop/Categories/CategoriesView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Categories/CategoriesView.axaml
@@ -2,7 +2,20 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:categories="clr-namespace:Artemis.UI.Screens.Workshop.Categories"
+ xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- x:Class="Artemis.UI.Screens.Workshop.Categories.CategoriesView">
- Welcome to Avalonia!
-
+ x:Class="Artemis.UI.Screens.Workshop.Categories.CategoriesView"
+ x:DataType="categories:CategoriesViewModel">
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Categories/CategoriesView.axaml.cs b/src/Artemis.UI/Screens/Workshop/Categories/CategoriesView.axaml.cs
index 0864378dd..15ac17ab5 100644
--- a/src/Artemis.UI/Screens/Workshop/Categories/CategoriesView.axaml.cs
+++ b/src/Artemis.UI/Screens/Workshop/Categories/CategoriesView.axaml.cs
@@ -1,5 +1,5 @@
using Avalonia;
-using Avalonia.Controls;
+using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
@@ -16,4 +16,10 @@ public partial class CategoriesView : ReactiveUserControl
{
AvaloniaXamlLoader.Load(this);
}
+
+ private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
+ {
+ if (e.InitialPressMouseButton == MouseButton.Left && sender is IDataContextProvider p && p.DataContext is CategoryViewModel categoryViewModel)
+ categoryViewModel.IsSelected = !categoryViewModel.IsSelected;
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Categories/CategoriesViewModel.cs b/src/Artemis.UI/Screens/Workshop/Categories/CategoriesViewModel.cs
index 4306a9fbf..f131958ae 100644
--- a/src/Artemis.UI/Screens/Workshop/Categories/CategoriesViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Categories/CategoriesViewModel.cs
@@ -1,14 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Threading;
+using System.Threading.Tasks;
using Artemis.UI.Shared;
using Artemis.WebClient.Workshop;
+using ReactiveUI;
+using Serilog;
+using StrawberryShake;
namespace Artemis.UI.Screens.Workshop.Categories;
public class CategoriesViewModel : ActivatableViewModelBase
{
private readonly IWorkshopClient _client;
+ private readonly ILogger _logger;
+ private IReadOnlyList _categories;
- public CategoriesViewModel(IWorkshopClient client)
+ public CategoriesViewModel(ILogger logger, IWorkshopClient client)
{
+ _logger = logger;
_client = client;
+
+ this.WhenActivated(d => ReactiveCommand.CreateFromTask(GetCategories).Execute().Subscribe().DisposeWith(d));
+ }
+
+ public IReadOnlyList Categories
+ {
+ get => _categories;
+ set => RaiseAndSetIfChanged(ref _categories, value);
+ }
+
+ private async Task GetCategories(CancellationToken cancellationToken)
+ {
+ try
+ {
+ IOperationResult result = await _client.GetCategories.ExecuteAsync(cancellationToken);
+ if (result.IsErrorResult())
+ _logger.Warning("Failed to retrieve categories {Error}", result.Errors);
+
+ Categories = result.Data?.Categories.Select(c => new CategoryViewModel(c)).ToList() ?? new List();
+ }
+ catch (Exception e)
+ {
+ _logger.Warning(e, "Failed to retrieve categories");
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Categories/CategoryViewModel.cs b/src/Artemis.UI/Screens/Workshop/Categories/CategoryViewModel.cs
new file mode 100644
index 000000000..08d991009
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/Categories/CategoryViewModel.cs
@@ -0,0 +1,29 @@
+using System;
+using Artemis.UI.Shared;
+using Artemis.WebClient.Workshop;
+using Material.Icons;
+
+namespace Artemis.UI.Screens.Workshop.Categories;
+
+public class CategoryViewModel : ViewModelBase
+{
+ private bool _isSelected;
+
+ public CategoryViewModel(IGetCategories_Categories category)
+ {
+ Id = category.Id;
+ Name = category.Name;
+ if (Enum.TryParse(typeof(MaterialIconKind), category.Icon, out object? icon))
+ Icon = icon as MaterialIconKind? ?? MaterialIconKind.QuestionMarkCircle;
+ }
+
+ public int Id { get; }
+ public string Name { get; }
+ public MaterialIconKind Icon { get; }
+
+ public bool IsSelected
+ {
+ get => _isSelected;
+ set => RaiseAndSetIfChanged(ref _isSelected, value);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Layout/LayoutListView.axaml b/src/Artemis.UI/Screens/Workshop/Layout/LayoutListView.axaml
index ebbdfd31c..151ec2089 100644
--- a/src/Artemis.UI/Screens/Workshop/Layout/LayoutListView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Layout/LayoutListView.axaml
@@ -9,7 +9,10 @@
- Side panel
+
+ Categories
+
+
diff --git a/src/Artemis.UI/Screens/Workshop/Layout/LayoutListViewModel.cs b/src/Artemis.UI/Screens/Workshop/Layout/LayoutListViewModel.cs
index b86bf8ecc..17ac0ca9e 100644
--- a/src/Artemis.UI/Screens/Workshop/Layout/LayoutListViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Layout/LayoutListViewModel.cs
@@ -1,8 +1,8 @@
using System;
using System.Threading;
using System.Threading.Tasks;
+using Artemis.UI.Screens.Workshop.Categories;
using Artemis.UI.Screens.Workshop.Parameters;
-using Artemis.UI.Screens.Workshop.Search;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.WebClient.Workshop;
@@ -13,11 +13,13 @@ public class LayoutListViewModel : RoutableScreen
- public LayoutListViewModel()
+ public LayoutListViewModel(CategoriesViewModel categoriesViewModel)
{
+ CategoriesViewModel = categoriesViewModel;
}
+ public CategoriesViewModel CategoriesViewModel { get; }
+
public int Page
{
get => _page;
diff --git a/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryView.axaml b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryView.axaml
new file mode 100644
index 000000000..13395d7b7
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryView.axaml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Downloads
+ Last updated
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryView.axaml.cs b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryView.axaml.cs
new file mode 100644
index 000000000..288da66ae
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryView.axaml.cs
@@ -0,0 +1,18 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Artemis.UI.Screens.Workshop.Profile;
+
+public partial class ProfileListEntryView : UserControl
+{
+ public ProfileListEntryView()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryViewModel.cs b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryViewModel.cs
new file mode 100644
index 000000000..67786214d
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListEntryViewModel.cs
@@ -0,0 +1,14 @@
+using Artemis.UI.Shared;
+using Artemis.WebClient.Workshop;
+
+namespace Artemis.UI.Screens.Workshop.Profile;
+
+public class ProfileListEntryViewModel : ViewModelBase
+{
+ public ProfileListEntryViewModel(IGetEntries_Entries_Nodes entry)
+ {
+ Entry = entry;
+ }
+
+ public IGetEntries_Entries_Nodes Entry { get; }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Profile/ProfileListView.axaml b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListView.axaml
index d103a3288..38380c8e7 100644
--- a/src/Artemis.UI/Screens/Workshop/Profile/ProfileListView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListView.axaml
@@ -8,14 +8,22 @@
x:DataType="profile:ProfileListViewModel">
-
- Side panel
+
+
+ Categories
+
+
+
-
-
-
+
+
+
+
+
+
+
diff --git a/src/Artemis.UI/Screens/Workshop/Profile/ProfileListViewModel.cs b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListViewModel.cs
index d478b5229..76f1fa762 100644
--- a/src/Artemis.UI/Screens/Workshop/Profile/ProfileListViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Profile/ProfileListViewModel.cs
@@ -1,34 +1,70 @@
using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
+using Artemis.UI.Screens.Workshop.Categories;
using Artemis.UI.Screens.Workshop.Parameters;
-using Artemis.UI.Screens.Workshop.Search;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.WebClient.Workshop;
+using DynamicData;
+using ReactiveUI;
+using StrawberryShake;
namespace Artemis.UI.Screens.Workshop.Profile;
public class ProfileListViewModel : RoutableScreen, IWorkshopViewModel
{
+ private readonly SourceList _entries;
+ private readonly IWorkshopClient _workshopClient;
private int _page;
- ///
- public ProfileListViewModel()
+ public ProfileListViewModel(IWorkshopClient workshopClient, CategoriesViewModel categoriesViewModel)
{
-
+ _workshopClient = workshopClient;
+ CategoriesViewModel = categoriesViewModel;
+
+ _entries = new SourceList();
+ _entries.Connect()
+ .Transform(e => new ProfileListEntryViewModel(e))
+ .Bind(out ReadOnlyObservableCollection observableEntries)
+ .Subscribe();
+ Entries = observableEntries;
}
+ public CategoriesViewModel CategoriesViewModel { get; }
+ public ReadOnlyObservableCollection Entries { get; set; }
+
public int Page
{
get => _page;
set => RaiseAndSetIfChanged(ref _page, value);
}
- public override Task OnNavigating(WorkshopListParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
+ public override async Task OnNavigating(WorkshopListParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
{
Page = Math.Max(1, parameters.Page);
- return Task.CompletedTask;
+ await GetEntries(cancellationToken);
+ }
+
+ private async Task GetEntries(CancellationToken cancellationToken)
+ {
+ IOperationResult result = await _workshopClient.GetEntries.ExecuteAsync(CreateFilter(), cancellationToken);
+ if (result.IsErrorResult() || result.Data?.Entries?.Nodes == null)
+ return;
+
+ _entries.Edit(e =>
+ {
+ e.Clear();
+ e.AddRange(result.Data.Entries.Nodes);
+ });
+ }
+
+ private EntryFilterInput CreateFilter()
+ {
+ return new EntryFilterInput {EntryType = new EntryTypeOperationFilterInput {Eq = WebClient.Workshop.EntryType.Profile}};
}
public EntryType? EntryType => null;
diff --git a/src/Artemis.WebClient.Workshop/Queries/GetEntries.graphql b/src/Artemis.WebClient.Workshop/Queries/GetEntries.graphql
index 9d9457e62..dae8242c6 100644
--- a/src/Artemis.WebClient.Workshop/Queries/GetEntries.graphql
+++ b/src/Artemis.WebClient.Workshop/Queries/GetEntries.graphql
@@ -1,9 +1,14 @@
-query GetEntries {
- entries {
+query GetEntries($filter: EntryFilterInput) {
+ entries(where: $filter) {
nodes {
author
name
+ summary
entryType
+ categories {
+ name
+ icon
+ }
}
}
}
\ No newline at end of file