start new controllers

This commit is contained in:
2021-11-23 15:43:21 +01:00
parent bffddbe9a8
commit a9bf2d28cb
61 changed files with 578 additions and 891 deletions
@@ -1,5 +1,7 @@
using Raven.Client.Documents.Indexes;
using Raven.Client.Documents;
using Raven.Client.Documents.Indexes;
using Raven.Client.Documents.Linq;
using Raven.Client.Documents.Session;
namespace zero.Collections;
@@ -40,18 +42,26 @@ public abstract partial class CollectionOperations
/// <inheritdoc />
public virtual async Task<ListResult<T>> Load<T>(ListQuery<T> query) where T : ZeroIdEntity, new()
public virtual async Task<Paged<T>> Load<T>(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default) where T : ZeroIdEntity, new()
{
return await Session.Query<T>().FilterAsync(query);
IRavenQueryable<T> queryable = Session.Query<T>().Statistics(out QueryStatistics statistics);
querySelector ??= x => x;
List<T> result = await querySelector(queryable).Paging(pageNumber, pageSize).ToListAsync();
return new Paged<T>(result, statistics.TotalResults, pageNumber, pageSize);
}
/// <inheritdoc />
public virtual async Task<ListResult<T>> Load<T, TIndex>(ListQuery<T> query)
public virtual async Task<Paged<T>> Load<T, TIndex>(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default)
where T : ZeroIdEntity, new()
where TIndex : AbstractCommonApiForIndexes, new()
{
return await Session.Query<T, TIndex>().FilterAsync(query);
IRavenQueryable<T> queryable = Session.Query<T, TIndex>().Statistics(out QueryStatistics statistics);
querySelector ??= x => x;
List<T> result = await querySelector(queryable).Paging(pageNumber, pageSize).ToListAsync();
return new Paged<T>(result, statistics.TotalResults, pageNumber, pageSize);
}
@@ -74,16 +84,17 @@ public abstract partial class CollectionOperations
/// <inheritdoc />
public virtual async IAsyncEnumerable<T> Stream<T>(Func<IRavenQueryable<T>, IRavenQueryable<T>> expression) where T : ZeroIdEntity, new()
public virtual async IAsyncEnumerable<T> Stream<T>(Func<IRavenQueryable<T>, IQueryable<T>> expression) where T : ZeroIdEntity, new()
{
IRavenQueryable<T> query = Session.Query<T>();
IQueryable<T> queryable = query;
if (expression != null)
{
query = expression(query);
queryable = expression(query);
}
var stream = await Session.Advanced.StreamAsync(query);
var stream = await Session.Advanced.StreamAsync(queryable);
while (await stream.MoveNextAsync())
{
@@ -5,7 +5,13 @@ namespace zero.Collections;
public abstract partial class CollectionOperations
{
/// <inheritdoc />
public virtual async Task<EntityResult<T>> Save<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : ZeroIdEntity, new()
public virtual Task<EntityResult<T>> Create<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : ZeroIdEntity, new() => Save(model, validate);
/// <inheritdoc />
public virtual Task<EntityResult<T>> Update<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : ZeroIdEntity, new() => Save(model, validate);
/// <inheritdoc />
protected virtual async Task<EntityResult<T>> Save<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : ZeroIdEntity, new()
{
if (model == null)
{
+10 -5
View File
@@ -150,12 +150,12 @@ public interface ICollectionOperations
/// <summary>
/// Get entities by query
/// </summary>
Task<ListResult<T>> Load<T>(ListQuery<T> query) where T : ZeroIdEntity, new();
Task<Paged<T>> Load<T>(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> expression = default) where T : ZeroIdEntity, new();
/// <summary>
/// Get entities by query (by using the specified index)
/// </summary>
Task<ListResult<T>> Load<T, TIndex>(ListQuery<T> query) where T : ZeroIdEntity, new() where TIndex : AbstractCommonApiForIndexes, new();
Task<Paged<T>> Load<T, TIndex>(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> expression = default) where T : ZeroIdEntity, new() where TIndex : AbstractCommonApiForIndexes, new();
/// <summary>
/// Get all entities from this collection.
@@ -171,12 +171,17 @@ public interface ICollectionOperations
/// <summary>
/// Stream the collection
/// </summary>
IAsyncEnumerable<T> Stream<T>(Func<IRavenQueryable<T>, IRavenQueryable<T>> expression) where T : ZeroIdEntity, new();
IAsyncEnumerable<T> Stream<T>(Func<IRavenQueryable<T>, IQueryable<T>> expression) where T : ZeroIdEntity, new();
/// <summary>
/// Updates or creates an entity with an optional validator
/// Creates an entity with an optional validator
/// </summary>
Task<EntityResult<T>> Save<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : ZeroIdEntity, new();
Task<EntityResult<T>> Create<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : ZeroIdEntity, new();
/// <summary>
/// Updates an entity with an optional validator
/// </summary>
Task<EntityResult<T>> Update<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : ZeroIdEntity, new();
/// <summary>
/// Deletes an entity
+17 -9
View File
@@ -43,10 +43,10 @@ public abstract partial class EntityCollection<T> : IEntityCollection<T> where T
public virtual Task<Dictionary<string, T>> Load(IEnumerable<string> ids) => Operations.Load<T>(ids);
/// <inheritdoc />
public virtual Task<ListResult<T>> Load(ListQuery<T> query) => Operations.Load(query);
public virtual Task<Paged<T>> Load(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default) => Operations.Load(pageNumber, pageSize, querySelector);
/// <inheritdoc />
public virtual Task<ListResult<T>> Load<TIndex>(ListQuery<T> query) where TIndex : AbstractCommonApiForIndexes, new() => Operations.Load<T, TIndex>(query);
public virtual Task<Paged<T>> Load<TIndex>(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default) where TIndex : AbstractCommonApiForIndexes, new() => Operations.Load<T, TIndex>(pageNumber, pageSize, querySelector);
/// <inheritdoc />
public virtual Task<List<T>> LoadAll() => Operations.LoadAll<T>();
@@ -55,10 +55,13 @@ public abstract partial class EntityCollection<T> : IEntityCollection<T> where T
public virtual IAsyncEnumerable<T> Stream() => Operations.Stream<T>();
/// <inheritdoc />
public virtual IAsyncEnumerable<T> Stream(Func<IRavenQueryable<T>, IRavenQueryable<T>> expression) => Operations.Stream<T>(expression);
public virtual IAsyncEnumerable<T> Stream(Func<IRavenQueryable<T>, IQueryable<T>> expression) => Operations.Stream<T>(expression);
/// <inheritdoc />
public virtual Task<EntityResult<T>> Save(T model) => Operations.Save(model, async m => await Validate(m));
public virtual Task<EntityResult<T>> Create(T model) => Operations.Create(model, async m => await Validate(m));
/// <inheritdoc />
public virtual Task<EntityResult<T>> Update(T model) => Operations.Update(model, async m => await Validate(m));
/// <inheritdoc />
public virtual Task<EntityResult<T>> Delete(T model) => Operations.Delete(model);
@@ -115,12 +118,12 @@ public interface IEntityCollection<T> where T : ZeroIdEntity, new()
/// <summary>
/// Get entities by query
/// </summary>
Task<ListResult<T>> Load(ListQuery<T> query);
Task<Paged<T>> Load(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default);
/// <summary>
/// Get entities by query (by using the specified index)
/// </summary>
Task<ListResult<T>> Load<TIndex>(ListQuery<T> query) where TIndex : AbstractCommonApiForIndexes, new();
Task<Paged<T>> Load<TIndex>(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default) where TIndex : AbstractCommonApiForIndexes, new();
/// <summary>
/// Get all entities from this collection.
@@ -136,7 +139,7 @@ public interface IEntityCollection<T> where T : ZeroIdEntity, new()
/// <summary>
/// Stream the collection
/// </summary>
IAsyncEnumerable<T> Stream(Func<IRavenQueryable<T>, IRavenQueryable<T>> expression);
IAsyncEnumerable<T> Stream(Func<IRavenQueryable<T>, IQueryable<T>> expression);
/// <summary>
/// Validates an entity in this collection
@@ -144,9 +147,14 @@ public interface IEntityCollection<T> where T : ZeroIdEntity, new()
Task<ValidationResult> Validate(T model);
/// <summary>
/// Updates or creates an entity with an optional validator
/// Creates an entity with an optional validator
/// </summary>
Task<EntityResult<T>> Save(T model);
Task<EntityResult<T>> Create(T model);
/// <summary>
/// Updates an entity with an optional validator
/// </summary>
Task<EntityResult<T>> Update(T model);
/// <summary>
/// Deletes an entity
+2 -2
View File
@@ -5,7 +5,7 @@ public static class EnumerableExtensions
/// <summary>
///
/// </summary>
public static ListResult<T> ToQueriedList<T>(this IEnumerable<T> items, ListQuery<T> query) where T : ZeroEntity
public static Paged<T> ToQueriedList<T>(this IEnumerable<T> items, ListQuery<T> query) where T : ZeroEntity
{
//queryable = queryable.Statistics(out QueryStatistics stats);
@@ -45,7 +45,7 @@ public static class EnumerableExtensions
List<T> result = items.ToList();
return new ListResult<T>(result, result.Count, query.Page, query.PageSize);
return new Paged<T>(result, result.Count, query.Page, query.PageSize);
}
+2 -2
View File
@@ -54,7 +54,7 @@ namespace zero.Core.Api
/// <inheritdoc />
public async Task<ListResult<BackofficeUser>> GetByQuery(ListQuery<BackofficeUser> query)
public async Task<Paged<BackofficeUser>> GetByQuery(ListQuery<BackofficeUser> query)
{
string currentUserId = UserManager.GetUserId(Context.Context.BackofficeUser);
@@ -247,7 +247,7 @@ namespace zero.Core.Api
/// <summary>
/// Get all available users (with query)
/// </summary>
Task<ListResult<BackofficeUser>> GetByQuery(ListQuery<BackofficeUser> query);
Task<Paged<BackofficeUser>> GetByQuery(ListQuery<BackofficeUser> query);
/// <summary>
/// Creates or updates a user
@@ -1,4 +1,4 @@
namespace zero;
namespace zero.Models;
public interface IZeroRouteEntity
{
@@ -2,7 +2,7 @@
using Raven.Client.Documents.Session;
using System.Linq.Expressions;
namespace zero;
namespace zero.Models;
public class ListQuery<T>
{
@@ -1,7 +1,7 @@
using FluentValidation.Results;
using System.Runtime.Serialization;
namespace zero;
namespace zero.Models;
[DataContract(Name = "result", Namespace = "")]
public class EntityResult<T>
@@ -1,11 +1,35 @@
namespace zero;
namespace zero.Models;
/// <summary>
/// Represents a paged result for a model collection
/// </summary>
public class ListResult<T> : ListResult
public class Paged<T> : Paged
{
public ListResult(long totalItems, long page, long pageSize)
public IList<T> Items { get; set; } = new List<T>();
public Paged(IList<T> items, long totalItems, long pageNumber, long pageSize) : this(totalItems, pageNumber, pageSize)
{
Items = items;
}
public Paged<TTarget> MapTo<TTarget>(Func<T, TTarget> convertItem)
{
return new Paged<TTarget>(Items.Select(x => convertItem(x)).Where(x => x != null).ToList(), TotalItems, Page, PageSize);
}
}
public class Paged
{
public long Page { get; protected set; }
public long PageSize { get; protected set; }
public long TotalPages { get; protected set; }
public long TotalItems { get; protected set; }
public bool HasMore { get; protected set; }
public Paged(long totalItems, long page, long pageSize)
{
TotalItems = totalItems;
Page = page;
@@ -23,25 +47,6 @@ public class ListResult<T> : ListResult
HasMore = TotalPages > Page;
}
public ListResult(IList<T> items, long totalItems, long pageNumber, long pageSize) : this(totalItems, pageNumber, pageSize)
{
Items = items;
}
public ListResult<TTarget> MapTo<TTarget>(Func<T, TTarget> convertItem)
{
return new ListResult<TTarget>(Items.Select(x => convertItem(x)).Where(x => x != null).ToList(), TotalItems, Page, PageSize);
}
public IList<T> Items { get; set; } = new List<T>();
/// <summary>
/// Calculates the skip size based on the paged parameters specified
/// </summary>
/// <remarks>
/// Returns 0 if the page number or page size is zero
/// </remarks>
public int GetSkipSize()
{
if (Page > 0 && PageSize > 0)
@@ -50,18 +55,4 @@ public class ListResult<T> : ListResult
}
return 0;
}
}
public class ListResult
{
public long Page { get; protected set; }
public long PageSize { get; protected set; }
public long TotalPages { get; protected set; }
public long TotalItems { get; protected set; }
public bool HasMore { get; protected set; }
}
@@ -1,7 +1,7 @@
using Newtonsoft.Json;
using System.Diagnostics;
namespace zero;
namespace zero.Models;
[DebuggerDisplay("Id = {Id,nq}, Name = {Name}, Alias = {Alias}")]
public class ZeroEntity : ZeroIdEntity, IZeroDbConventions, IZeroRouteEntity
@@ -1,4 +1,4 @@
namespace zero;
namespace zero.Models;
[RavenCollection("Previews")]
public class ZeroEntityPreview : ZeroEntity
@@ -1,4 +1,4 @@
namespace zero;
namespace zero.Models;
public class ZeroIdEntity
{
@@ -1,4 +1,4 @@
namespace zero;
namespace zero.Models;
public class ZeroReference
{
@@ -11,7 +11,7 @@ public static class RavenQueryableExtensions
/// <summary>
///
/// </summary>
public static async Task<ListResult<T>> FilterAsync<T>(this IRavenQueryable<T> source, ListQuery<T> listQuery)
public static async Task<Paged<T>> FilterAsync<T>(this IRavenQueryable<T> source, ListQuery<T> listQuery)
{
return await source.WithFilter(listQuery).ToListResultAsync(listQuery);
}
@@ -73,10 +73,10 @@ public static class RavenQueryableExtensions
/// <summary>
///
/// </summary>
public static async Task<ListResult<T>> ToListResultAsync<T>(this IQueryable<T> source, ListQuery<T> listQuery, CancellationToken token = default)
public static async Task<Paged<T>> ToListResultAsync<T>(this IQueryable<T> source, ListQuery<T> listQuery, CancellationToken token = default)
{
List<T> results = await source.ToListAsync(token);
return new ListResult<T>(results, listQuery.Statistics.TotalResults, listQuery.Page, listQuery.PageSize);
return new Paged<T>(results, listQuery.Statistics.TotalResults, listQuery.Page, listQuery.PageSize);
}
+2 -1
View File
@@ -22,4 +22,5 @@ global using zero.Rendering;
global using zero.Routing;
global using zero.Utils;
global using zero.Validation;
global using zero.Collections;
global using zero.Collections;
global using zero.Models;
+2 -2
View File
@@ -38,7 +38,7 @@ namespace zero.Core.Api
/// <inheritdoc />
public async Task<ListResult<Application>> GetByQuery(ListQuery<Application> query)
public async Task<Paged<Application>> GetByQuery(ListQuery<Application> query)
{
query.SearchFor(entity => entity.Name);
@@ -76,7 +76,7 @@ namespace zero.Core.Api
/// <summary>
/// Get all available applications (with query)
/// </summary>
Task<ListResult<Application>> GetByQuery(ListQuery<Application> query);
Task<Paged<Application>> GetByQuery(ListQuery<Application> query);
/// <summary>
/// Creates or updates a application
+2 -2
View File
@@ -65,7 +65,7 @@ namespace zero.Core.Api
/// <inheritdoc />
public async Task<ListResult<RecycledEntity>> GetByQuery(RecycleBinListQuery query)
public async Task<Paged<RecycledEntity>> GetByQuery(RecycleBinListQuery query)
{
query.SearchSelector = x => x.Name;
@@ -145,7 +145,7 @@ namespace zero.Core.Api
/// <summary>
/// Get all recycled items
/// </summary>
Task<ListResult<RecycledEntity>> GetByQuery(RecycleBinListQuery query);
Task<Paged<RecycledEntity>> GetByQuery(RecycleBinListQuery query);
/// <summary>
/// Get affected entities from a specific operation
+6 -6
View File
@@ -20,7 +20,7 @@ namespace zero.Core.Api
/// <summary>
/// Get revision list for an entity
/// </summary>
public async Task<ListResult<Revision<T>>> GetPagedWithModel<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity
public async Task<Paged<Revision<T>>> GetPagedWithModel<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity
{
// get paged revisions
List<T> items = await Session.Advanced.Revisions.GetForAsync<T>(id, (pageNumber - 1) * pageSize, pageSize);
@@ -66,16 +66,16 @@ namespace zero.Core.Api
revisions.Add(revision);
}
return new ListResult<Revision<T>>(revisions, totalResults, pageNumber, pageSize);
return new Paged<Revision<T>>(revisions, totalResults, pageNumber, pageSize);
}
/// <summary>
/// Get revision list for an entity
/// </summary>
public async Task<ListResult<Revision>> GetPaged<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity
public async Task<Paged<Revision>> GetPaged<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity
{
ListResult<Revision<T>> items = await GetPagedWithModel<T>(id, pageNumber, pageSize);
Paged<Revision<T>> items = await GetPagedWithModel<T>(id, pageNumber, pageSize);
return items.MapTo(model => new Revision()
{
ChangeVector = model.ChangeVector,
@@ -92,11 +92,11 @@ namespace zero.Core.Api
/// <summary>
/// Get revision list including models for an entity
/// </summary>
Task<ListResult<Revision<T>>> GetPagedWithModel<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity;
Task<Paged<Revision<T>>> GetPagedWithModel<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity;
/// <summary>
/// Get revision list for an entity
/// </summary>
Task<ListResult<Revision>> GetPaged<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity;
Task<Paged<Revision>> GetPaged<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity;
}
}
+1 -14
View File
@@ -2,23 +2,10 @@
using Microsoft.AspNetCore.Identity;
using Newtonsoft.Json;
using Raven.Client.Documents;
using Raven.Client.Documents.Conventions;
using Raven.Client.Documents.Session;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using zero.Core.Database;
using zero.Core.Entities;
using zero.Core.Entities.Setup;
using zero.Core.Extensions;
using zero.Core.Identity;
using zero.Core.Options;
using zero.Core.Utils;
using zero.Core.Validation;
using zero.Setup;
namespace zero.Core.Api
{
+6 -6
View File
@@ -89,7 +89,7 @@ namespace zero.Core.Api
/// <inheritdoc />
public async Task<ListResult<SpaceContent>> GetListByQuery(string alias, ListQuery<SpaceContent> query)
public async Task<Paged<SpaceContent>> GetListByQuery(string alias, ListQuery<SpaceContent> query)
{
query.SearchSelector = item => item.Name;
@@ -100,7 +100,7 @@ namespace zero.Core.Api
/// <inheritdoc />
public async Task<ListResult<T>> GetListByQuery<T>(string alias, ListQuery<T> query) where T : SpaceContent
public async Task<Paged<T>> GetListByQuery<T>(string alias, ListQuery<T> query) where T : SpaceContent
{
query.SearchSelector = item => item.Name;
@@ -111,7 +111,7 @@ namespace zero.Core.Api
/// <inheritdoc />
public async Task<ListResult<T>> GetListByQuery<T>(ListQuery<T> query) where T : SpaceContent
public async Task<Paged<T>> GetListByQuery<T>(ListQuery<T> query) where T : SpaceContent
{
Space space = GetBy<T>();
query.SearchSelector = item => item.Name;
@@ -172,17 +172,17 @@ namespace zero.Core.Api
/// <summary>
/// Get all list items for a space (with query)
/// </summary>
Task<ListResult<SpaceContent>> GetListByQuery(string alias, ListQuery<SpaceContent> query);
Task<Paged<SpaceContent>> GetListByQuery(string alias, ListQuery<SpaceContent> query);
/// <summary>
/// Get all list items for a space (with query)
/// </summary>
Task<ListResult<T>> GetListByQuery<T>(string alias, ListQuery<T> query) where T : SpaceContent;
Task<Paged<T>> GetListByQuery<T>(string alias, ListQuery<T> query) where T : SpaceContent;
/// <summary>
/// Get all list items for a space (with query)
/// </summary>
Task<ListResult<T>> GetListByQuery<T>(ListQuery<T> query) where T : SpaceContent;
Task<Paged<T>> GetListByQuery<T>(ListQuery<T> query) where T : SpaceContent;
/// <summary>
/// Saves a content item in a space
@@ -89,7 +89,7 @@ namespace zero.Core.Collections
/// <inheritdoc />
public override async Task<ListResult<Integration>> Load(ListQuery<Integration> query)
public override async Task<Paged<Integration>> Load(ListQuery<Integration> query)
{
List<Integration> result = new();
List<Integration> models = await Session.Query<Integration>().ToListAsync();
@@ -257,7 +257,7 @@ namespace zero.Core.Collections
/// <summary>
/// Get all integrations with the specified query
/// </summary>
Task<ListResult<Integration>> Load(ListQuery<Integration> query);
Task<Paged<Integration>> Load(ListQuery<Integration> query);
/// <summary>
/// Get all integration types with their configuration status
@@ -75,7 +75,7 @@ namespace zero.Core.Collections
/// <inheritdoc />
public virtual async Task<ListResult<Media>> Load(MediaListQuery query)
public virtual async Task<Paged<Media>> Load(MediaListQuery query)
{
query.SearchFor(entity => entity.Name);
@@ -162,7 +162,7 @@ namespace zero.Core.Collections
/// <inheritdoc />
public virtual async Task<ListResult<MediaListItem>> Load(MediaListItemQuery query)
public virtual async Task<Paged<MediaListItem>> Load(MediaListItemQuery query)
{
bool hasSearch = !query.Search.IsNullOrWhiteSpace();
bool isRoot = query.FolderId.IsNullOrWhiteSpace();
@@ -180,7 +180,7 @@ namespace zero.Core.Collections
dbQuery = dbQuery.WhereIf(x => x.ParentId == query.FolderId, !query.FolderId.IsNullOrEmpty(), x => x.ParentId == null);
}
ListResult<MediaListItem> result = await dbQuery.ToQueriedListAsyncX(query);
Paged<MediaListItem> result = await dbQuery.ToQueriedListAsyncX(query);
string[] ids = result.Items.Where(x => x.IsFolder).Select(x => x.Id).ToArray();
@@ -256,12 +256,12 @@ namespace zero.Core.Collections
/// <summary>
/// Get all available media items with query
/// </summary>
Task<ListResult<Media>> Load(MediaListQuery query);
Task<Paged<Media>> Load(MediaListQuery query);
/// <summary>
/// Get all available media items (including folders) with query
/// </summary>
Task<ListResult<MediaListItem>> Load(MediaListItemQuery query);
Task<Paged<MediaListItem>> Load(MediaListItemQuery query);
/// <summary>
/// Move a file to a new parent