From 562049681fee1adcf35c54a6ce95a678bc3f10dd Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 30 Dec 2025 10:02:16 +0100 Subject: [PATCH] Workshop - Recently updated tab --- .../Steps/DefaultEntriesStepViewModel.cs | 12 +- .../Entries/List/EntryListViewModel.cs | 10 +- .../Workshop/Home/WorkshopHomeViewModel.cs | 4 +- .../Library/Tabs/InstalledTabViewModel.cs | 11 +- .../Tabs/RecentlyUpdatedItemView.axaml | 83 +++++++++++++- .../Tabs/RecentlyUpdatedItemViewModel.cs | 19 +++- .../Library/Tabs/RecentlyUpdatedView.axaml | 43 ++++++- .../Library/Tabs/RecentlyUpdatedView.axaml.cs | 2 +- .../Library/Tabs/RecentlyUpdatedViewModel.cs | 106 +++++++++++++++++- .../Plugins/PluginDescriptionViewModel.cs | 2 +- .../BuiltInPluginsMigrator.cs | 14 +-- .../Queries/GetDependantEntries.graphql | 9 +- .../Queries/GetEntries.graphql | 64 +++++------ .../WorkshopConstants.cs | 8 +- src/Artemis.WebClient.Workshop/schema.graphql | 65 +++++++---- 15 files changed, 351 insertions(+), 101 deletions(-) diff --git a/src/Artemis.UI/Screens/StartupWizard/Steps/DefaultEntriesStepViewModel.cs b/src/Artemis.UI/Screens/StartupWizard/Steps/DefaultEntriesStepViewModel.cs index ad2b4d043..d97ed8dc6 100644 --- a/src/Artemis.UI/Screens/StartupWizard/Steps/DefaultEntriesStepViewModel.cs +++ b/src/Artemis.UI/Screens/StartupWizard/Steps/DefaultEntriesStepViewModel.cs @@ -100,19 +100,13 @@ public partial class DefaultEntriesStepViewModel : WizardStepViewModel { FetchingDefaultEntries = true; - IOperationResult result = await _client.GetDefaultEntries.ExecuteAsync(100, null, cancellationToken); - List entries = result.Data?.EntriesV2?.Edges?.Select(e => e.Node).Cast().ToList() ?? []; - while (result.Data?.EntriesV2?.PageInfo is {HasNextPage: true}) - { - result = await _client.GetDefaultEntries.ExecuteAsync(100, result.Data.EntriesV2.PageInfo.EndCursor, cancellationToken); - if (result.Data?.EntriesV2?.Edges != null) - entries.AddRange(result.Data.EntriesV2.Edges.Select(e => e.Node)); - } + IOperationResult result = await _client.GetDefaultEntries.ExecuteAsync(cancellationToken); + IReadOnlyList entries = result.Data?.Entries ?? []; DeviceProviderEntryViewModels.Clear(); EssentialEntryViewModels.Clear(); OtherEntryViewModels.Clear(); - foreach (IEntrySummary entry in entries) + foreach (IGetDefaultEntries_Entries entry in entries) { if (entry.DefaultEntryInfo == null) continue; diff --git a/src/Artemis.UI/Screens/Workshop/Entries/List/EntryListViewModel.cs b/src/Artemis.UI/Screens/Workshop/Entries/List/EntryListViewModel.cs index 6124c212b..3bc47a638 100644 --- a/src/Artemis.UI/Screens/Workshop/Entries/List/EntryListViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/Entries/List/EntryListViewModel.cs @@ -25,7 +25,7 @@ public partial class EntryListViewModel : RoutableScreen private readonly SourceList _entries = new(); private readonly INotificationService _notificationService; private readonly IWorkshopClient _workshopClient; - private IGetEntries_EntriesV2_PageInfo? _currentPageInfo; + private IGetEntries_PagedEntries_PageInfo? _currentPageInfo; [Notify] private bool _initializing = true; [Notify] private bool _fetchingMore; @@ -98,11 +98,11 @@ public partial class EntryListViewModel : RoutableScreen IOperationResult entries = await _workshopClient.GetEntries.ExecuteAsync(search, IncludeDefaultEntries, filter, sort, entriesPerFetch, _currentPageInfo?.EndCursor, cancellationToken); entries.EnsureNoErrors(); - _currentPageInfo = entries.Data?.EntriesV2?.PageInfo; - if (entries.Data?.EntriesV2?.Edges != null) - _entries.Edit(e => e.AddRange(entries.Data.EntriesV2.Edges.Select(edge => edge.Node))); + _currentPageInfo = entries.Data?.PagedEntries?.PageInfo; + if (entries.Data?.PagedEntries?.Edges != null) + _entries.Edit(e => e.AddRange(entries.Data.PagedEntries.Edges.Select(edge => edge.Node))); - InputViewModel.TotalCount = entries.Data?.EntriesV2?.TotalCount ?? 0; + InputViewModel.TotalCount = entries.Data?.PagedEntries?.TotalCount ?? 0; } catch (Exception e) { diff --git a/src/Artemis.UI/Screens/Workshop/Home/WorkshopHomeViewModel.cs b/src/Artemis.UI/Screens/Workshop/Home/WorkshopHomeViewModel.cs index 4dee0a822..9d953ffdb 100644 --- a/src/Artemis.UI/Screens/Workshop/Home/WorkshopHomeViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/Home/WorkshopHomeViewModel.cs @@ -55,8 +55,8 @@ public partial class WorkshopHomeViewModel : RoutableScreen latest.Edit(l => { l.Clear(); - if (latestResult.Data?.EntriesV2?.Edges != null) - l.AddRange(latestResult.Data.EntriesV2.Edges.Select(e => e.Node)); + if (latestResult.Data?.PagedEntries?.Edges != null) + l.AddRange(latestResult.Data.PagedEntries.Edges.Select(e => e.Node)); }); }); } diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabViewModel.cs index a2e70990d..54867a206 100644 --- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/InstalledTabViewModel.cs @@ -4,6 +4,7 @@ using System.Reactive; using System.Reactive.Disposables; using System.Reactive.Disposables.Fluent; using System.Reactive.Linq; +using System.Threading.Tasks; using Artemis.UI.Shared.Routing; using Artemis.WebClient.Workshop.Models; using Artemis.WebClient.Workshop.Services; @@ -18,6 +19,7 @@ namespace Artemis.UI.Screens.Workshop.Library.Tabs; public partial class InstalledTabViewModel : RoutableScreen { + private readonly IRouter _router; private SourceList _entries = new(); [Notify] private string? _searchEntryInput; @@ -25,6 +27,7 @@ public partial class InstalledTabViewModel : RoutableScreen public InstalledTabViewModel(IWorkshopService workshopService, IRouter router, Func getInstalledTabItemViewModel) { + _router = router; IObservable> searchFilter = this.WhenAnyValue(vm => vm.SearchEntryInput) .Throttle(TimeSpan.FromMilliseconds(100)) .ObserveOn(RxApp.MainThreadScheduler) @@ -47,8 +50,6 @@ public partial class InstalledTabViewModel : RoutableScreen workshopService.OnEntryUninstalled += WorkshopServiceOnOnEntryUninstalled; Disposable.Create(() => workshopService.OnEntryUninstalled -= WorkshopServiceOnOnEntryUninstalled).DisposeWith(d); }); - - OpenWorkshop = ReactiveCommand.CreateFromTask(async () => await router.Navigate("workshop")); } private void WorkshopServiceOnOnEntryUninstalled(object? sender, InstalledEntry e) @@ -57,9 +58,13 @@ public partial class InstalledTabViewModel : RoutableScreen } public bool Empty => _empty.Value; - public ReactiveCommand OpenWorkshop { get; } public ReadOnlyObservableCollection> EntryGroups { get; } + public async Task OpenWorkshop() + { + await _router.Navigate("workshop"); + } + private Func CreatePredicate(string? text) { if (string.IsNullOrWhiteSpace(text)) diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedItemView.axaml b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedItemView.axaml index 105eba36f..0f1598426 100644 --- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedItemView.axaml +++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedItemView.axaml @@ -3,8 +3,87 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:tabs="clr-namespace:Artemis.UI.Screens.Workshop.Library.Tabs" + xmlns:il="clr-namespace:AsyncImageLoader;assembly=AsyncImageLoader.Avalonia" + xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" + xmlns:converters="clr-namespace:Artemis.UI.Converters" + xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight" + xmlns:ui="clr-namespace:Artemis.UI" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.RecentlyUpdatedItemView" x:DataType="tabs:RecentlyUpdatedItemViewModel"> - Welcome to Avalonia! - + + + + + + + + + + + + + + + + + + by + + + + + + + + + + + + + + + + + + + not yet installed + + + + + + + There are no release notes for this release. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedItemViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedItemViewModel.cs index 1df0f3311..a49c8f623 100644 --- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedItemViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedItemViewModel.cs @@ -1,8 +1,23 @@ -using Artemis.UI.Shared; +using System; +using Artemis.UI.Shared; +using Artemis.WebClient.Workshop; +using Artemis.WebClient.Workshop.Models; +using Artemis.WebClient.Workshop.Services; namespace Artemis.UI.Screens.Workshop.Library.Tabs; public partial class RecentlyUpdatedItemViewModel : ActivatableViewModelBase { - + public IGetRecentUpdates_Entries Entry { get; } + public IGetRecentUpdates_Entries_LatestRelease Release { get; } + public InstalledEntry InstalledEntry { get; } + + public RecentlyUpdatedItemViewModel(IGetRecentUpdates_Entries entry, IWorkshopService workshopService) + { + Entry = entry; + Release = entry.LatestRelease ?? throw new InvalidOperationException("Entry does not have a latest release"); + InstalledEntry = workshopService.GetInstalledEntry(entry.Id) ?? throw new InvalidOperationException("Entry is not installed"); + } + + public bool NotYetInstalled => InstalledEntry.ReleaseId < Release.Id; } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedView.axaml b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedView.axaml index a4bab6833..b64fb619d 100644 --- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedView.axaml +++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedView.axaml @@ -6,5 +6,46 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.RecentlyUpdatedView" x:DataType="tabs:RecentlyUpdatedViewModel"> - Welcome to Avalonia! + + + + + + + + + + + + + + + + + Looks like nothing updated in the last 30 days + + Any entries you download that recently received updates will show up here + + + + + + + + + + + + + + + + + + + + diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedView.axaml.cs b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedView.axaml.cs index 6d90ae6ff..31d33f746 100644 --- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedView.axaml.cs +++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedView.axaml.cs @@ -2,7 +2,7 @@ namespace Artemis.UI.Screens.Workshop.Library.Tabs; -public partial class RecentlyUpdatedView : ReactiveUserControl +public partial class RecentlyUpdatedView : ReactiveUserControl { public RecentlyUpdatedView() { diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedViewModel.cs index 1a056dd8b..2dc398dff 100644 --- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/RecentlyUpdatedViewModel.cs @@ -1,8 +1,112 @@ -using Artemis.UI.Shared.Routing; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reactive.Linq; +using System.Threading; +using System.Threading.Tasks; +using Artemis.UI.Extensions; +using Artemis.UI.Shared.Routing; +using Artemis.WebClient.Workshop; +using Artemis.WebClient.Workshop.Models; +using Artemis.WebClient.Workshop.Services; +using DynamicData; +using DynamicData.Aggregation; +using DynamicData.Binding; +using PropertyChanged.SourceGenerator; +using ReactiveUI; +using StrawberryShake; namespace Artemis.UI.Screens.Workshop.Library.Tabs; public partial class RecentlyUpdatedViewModel : RoutableScreen { + private readonly IWorkshopService _workshopService; + private readonly IWorkshopClient _client; + private readonly IRouter _router; + private readonly SourceCache _entries; + private readonly ObservableAsPropertyHelper _empty; + + [Notify] private bool _isLoading = true; + [Notify] private bool _workshopReachable; + [Notify] private string? _searchEntryInput; + + public RecentlyUpdatedViewModel(IWorkshopService workshopService, + IWorkshopClient client, + IRouter router, + Func getRecentlyUpdatedItemViewModel) + { + IObservable> searchFilter = this.WhenAnyValue(vm => vm.SearchEntryInput) + .Throttle(TimeSpan.FromMilliseconds(100)) + .ObserveOn(RxApp.MainThreadScheduler) + .Select(CreatePredicate); + + _workshopService = workshopService; + _client = client; + _router = router; + _entries = new SourceCache(e => e.Id); + + _entries.Connect() + .Filter(searchFilter) + .Transform(getRecentlyUpdatedItemViewModel) + .SortAndBind( + out ReadOnlyObservableCollection entries, + SortExpressionComparer.Descending(p => p.Release.CreatedAt) + ) + .Subscribe(); + + _empty = _entries.Connect().Count().Select(c => c == 0).ToProperty(this, vm => vm.Empty); + + Entries = entries; + + this.WhenActivatedAsync(async d => + { + WorkshopReachable = await workshopService.ValidateWorkshopStatus(true, d.AsCancellationToken()); + if (WorkshopReachable) + await GetEntries(d.AsCancellationToken()); + }); + } + + public bool Empty => _empty.Value; + public ReadOnlyObservableCollection Entries { get; } + + public async Task OpenWorkshop() + { + await _router.Navigate("workshop"); + } + private async Task GetEntries(CancellationToken ct) + { + IsLoading = true; + + try + { + List installedEntries = _workshopService.GetInstalledEntries(); + IOperationResult result = await _client.GetRecentUpdates.ExecuteAsync( + installedEntries.Select(e => e.Id).ToList(), + DateTimeOffset.Now.AddDays(-30).ToUniversalTime(), + ct); + + if (result.Data?.Entries == null) + _entries.Clear(); + else + _entries.Edit(e => + { + e.Clear(); + e.AddOrUpdate(result.Data.Entries); + }); + } + finally + { + IsLoading = false; + } + } + + private Func CreatePredicate(string? text) + { + if (string.IsNullOrWhiteSpace(text)) + return _ => true; + + return data => data.Name.Contains(text, StringComparison.InvariantCultureIgnoreCase); + } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Workshop/Plugins/PluginDescriptionViewModel.cs b/src/Artemis.UI/Screens/Workshop/Plugins/PluginDescriptionViewModel.cs index eb98f7823..1cdecf2e8 100644 --- a/src/Artemis.UI/Screens/Workshop/Plugins/PluginDescriptionViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/Plugins/PluginDescriptionViewModel.cs @@ -34,7 +34,7 @@ public partial class PluginDescriptionViewModel : RoutableScreen if (entry != null) { - IReadOnlyList? dependants = (await _client.GetDependantEntries.ExecuteAsync(entry.Id, 0, 25, cancellationToken)).Data?.Entries?.Items; + IReadOnlyList? dependants = (await _client.GetDependantEntries.ExecuteAsync(entry.Id, cancellationToken)).Data?.Entries; Dependants = dependants != null && dependants.Any() ? dependants.Select(_getEntryListViewModel).OrderByDescending(d => d.Entry.Downloads).Take(10).ToList() : null; } else diff --git a/src/Artemis.WebClient.Workshop/BuiltInPluginsMigrator.cs b/src/Artemis.WebClient.Workshop/BuiltInPluginsMigrator.cs index e6c29cffd..afa9158fd 100644 --- a/src/Artemis.WebClient.Workshop/BuiltInPluginsMigrator.cs +++ b/src/Artemis.WebClient.Workshop/BuiltInPluginsMigrator.cs @@ -57,17 +57,11 @@ public static class BuiltInPluginsMigrator } logger.Information("MigrateBuiltInPlugins - Migrating built-in plugins to workshop entries"); - IOperationResult result = await workshopClient.GetDefaultPlugins.ExecuteAsync(100, null, CancellationToken.None); - List entries = result.Data?.EntriesV2?.Edges?.Select(e => e.Node).ToList() ?? []; - while (result.Data?.EntriesV2?.PageInfo is {HasNextPage: true}) - { - result = await workshopClient.GetDefaultPlugins.ExecuteAsync(100, result.Data.EntriesV2.PageInfo.EndCursor, CancellationToken.None); - if (result.Data?.EntriesV2?.Edges != null) - entries.AddRange(result.Data.EntriesV2.Edges.Select(e => e.Node)); - } - + IOperationResult result = await workshopClient.GetDefaultPlugins.ExecuteAsync(CancellationToken.None); + IReadOnlyList entries = result.Data?.Entries ?? []; + logger.Information("MigrateBuiltInPlugins - Found {Count} default plugins in the workshop", entries.Count); - foreach (IGetDefaultPlugins_EntriesV2_Edges_Node entry in entries) + foreach (IGetDefaultPlugins_Entries entry in entries) { // Skip entries without plugin info or releases, shouldn't happen but theoretically possible if (entry.PluginInfo == null || entry.LatestRelease == null) diff --git a/src/Artemis.WebClient.Workshop/Queries/GetDependantEntries.graphql b/src/Artemis.WebClient.Workshop/Queries/GetDependantEntries.graphql index 551cb140e..58b49092a 100644 --- a/src/Artemis.WebClient.Workshop/Queries/GetDependantEntries.graphql +++ b/src/Artemis.WebClient.Workshop/Queries/GetDependantEntries.graphql @@ -1,15 +1,10 @@ -query GetDependantEntries($entryId: Long! $skip: Int $take: Int) { +query GetDependantEntries($entryId: Long!) { entries( where: { latestRelease: { dependencies: { some: { id: { eq: $entryId } } } } } - skip: $skip - take: $take order: { createdAt: DESC } ) { - totalCount - items { - ...entrySummary - } + ...entrySummary } } diff --git a/src/Artemis.WebClient.Workshop/Queries/GetEntries.graphql b/src/Artemis.WebClient.Workshop/Queries/GetEntries.graphql index 10c5502ed..d9d95c3b8 100644 --- a/src/Artemis.WebClient.Workshop/Queries/GetEntries.graphql +++ b/src/Artemis.WebClient.Workshop/Queries/GetEntries.graphql @@ -1,5 +1,5 @@ query GetEntries($search: String $includeDefaults: Boolean $filter: EntryFilterInput $order: [EntrySortInput!] $first: Int $after: String) { - entriesV2(search: $search includeDefaults: $includeDefaults where: $filter order: $order first: $first after: $after) { + pagedEntries(search: $search includeDefaults: $includeDefaults where: $filter order: $order first: $first after: $after) { totalCount pageInfo { hasNextPage @@ -20,29 +20,17 @@ query GetPopularEntries { } } -query GetDefaultEntries($first: Int, $after: String) { - entriesV2( +query GetDefaultEntries { + entries( includeDefaults: true where: { defaultEntryInfo: { entryId: { gt: 0 } } } - first: $first - after: $after ) { - totalCount - pageInfo { - hasNextPage - endCursor - } - edges { - cursor - node { - ...entrySummary - } - } + ...entrySummary } } -query GetDefaultPlugins($first: Int, $after: String) { - entriesV2( +query GetDefaultPlugins { + entries( includeDefaults: true where: { and: [ @@ -50,22 +38,34 @@ query GetDefaultPlugins($first: Int, $after: String) { { entryType: {eq: PLUGIN} } ] } - first: $first - after: $after ) { - totalCount - pageInfo { - hasNextPage - endCursor + ...entrySummary + pluginInfo { + pluginGuid } - edges { - cursor - node { - ...entrySummary - pluginInfo { - pluginGuid - } - } + } +} + +query GetRecentUpdates($entryIds: [Long!]!, $cutoff: DateTime!) { + entries( + includeDefaults: true + where: { + and: [ + { id: { in: $entryIds } } + { latestRelease: { createdAt: { gte: $cutoff } } } + ] + } + ) { + id + author + isOfficial + name + summary + entryType + createdAt + latestRelease { + ...release + changelog } } } \ No newline at end of file diff --git a/src/Artemis.WebClient.Workshop/WorkshopConstants.cs b/src/Artemis.WebClient.Workshop/WorkshopConstants.cs index 9899d65a7..73a6f14dd 100644 --- a/src/Artemis.WebClient.Workshop/WorkshopConstants.cs +++ b/src/Artemis.WebClient.Workshop/WorkshopConstants.cs @@ -4,10 +4,10 @@ public static class WorkshopConstants { // This is so I can never accidentally release with localhost #if DEBUG - // public const string AUTHORITY_URL = "https://localhost:5001"; - // public const string WORKSHOP_URL = "https://localhost:7281"; - public const string AUTHORITY_URL = "https://identity.artemis-rgb.com"; - public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com"; + public const string AUTHORITY_URL = "https://localhost:5001"; + public const string WORKSHOP_URL = "https://localhost:7281"; + // public const string AUTHORITY_URL = "https://identity.artemis-rgb.com"; + // public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com"; #else public const string AUTHORITY_URL = "https://identity.artemis-rgb.com"; public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com"; diff --git a/src/Artemis.WebClient.Workshop/schema.graphql b/src/Artemis.WebClient.Workshop/schema.graphql index 9112a4def..e20b76968 100644 --- a/src/Artemis.WebClient.Workshop/schema.graphql +++ b/src/Artemis.WebClient.Workshop/schema.graphql @@ -24,15 +24,6 @@ type DefaultEntryInfo { isDeviceProvider: Boolean! } -"A segment of a collection." -type EntriesCollectionSegment { - "Information to aid in pagination." - pageInfo: CollectionSegmentInfo! - "A flattened list of the items." - items: [Entry!] - totalCount: Int! @cost(weight: "10") -} - "A connection to a list of items." type EntriesV2Connection { "Information to aid in pagination." @@ -134,6 +125,26 @@ type PageInfo { endCursor: String } +"A connection to a list of items." +type PagedEntriesConnection { + "Information to aid in pagination." + pageInfo: PageInfo! + "A list of edges." + edges: [PagedEntriesEdge!] + "A flattened list of the nodes." + nodes: [Entry!] + "Identifies the total count of items in the connection." + totalCount: Int! @cost(weight: "10") +} + +"An edge in a connection." +type PagedEntriesEdge { + "A cursor for use in pagination." + cursor: String! + "The item at the end of the edge." + node: Entry! +} + type PluginInfo { entryId: Long! entry: Entry! @@ -162,21 +173,10 @@ type Query { where: CategoryFilterInput @cost(weight: "10") ): [Category!]! @cost(weight: "10") entries( - skip: Int - take: Int - search: String includeDefaults: Boolean order: [EntrySortInput!] @cost(weight: "10") where: EntryFilterInput @cost(weight: "10") - ): EntriesCollectionSegment - @listSize( - assumedSize: 100 - slicingArguments: ["take"] - slicingArgumentDefaultValue: 10 - sizedFields: ["items"] - requireOneSlicingArgument: false - ) - @cost(weight: "10") + ): [Entry!]! @cost(weight: "10") entriesV2( search: String includeDefaults: Boolean @@ -199,6 +199,29 @@ type Query { requireOneSlicingArgument: false ) @cost(weight: "10") + @deprecated(reason: "Use GetPagedEntries with offset paging instead") + pagedEntries( + search: String + includeDefaults: Boolean + "Returns the first _n_ elements from the list." + first: Int + "Returns the elements in the list that come after the specified cursor." + after: String + "Returns the last _n_ elements from the list." + last: Int + "Returns the elements in the list that come before the specified cursor." + before: String + order: [EntrySortInput!] @cost(weight: "10") + where: EntryFilterInput @cost(weight: "10") + ): PagedEntriesConnection + @listSize( + assumedSize: 100 + slicingArguments: ["first", "last"] + slicingArgumentDefaultValue: 10 + sizedFields: ["edges", "nodes"] + requireOneSlicingArgument: false + ) + @cost(weight: "10") entry(id: Long!): Entry @cost(weight: "10") submittedEntries( order: [EntrySortInput!] @cost(weight: "10")