diff --git a/zero.Core/Api/MediaApi.cs b/zero.Core/Api/MediaApi.cs index 12d3a70c..b2d8ba3a 100644 --- a/zero.Core/Api/MediaApi.cs +++ b/zero.Core/Api/MediaApi.cs @@ -112,7 +112,7 @@ namespace zero.Core.Api dbQuery = dbQuery.WhereIf(x => x.ParentId == query.FolderId, !query.FolderId.IsNullOrEmpty(), x => x.ParentId == null); } - ListResult result = await dbQuery.ToQueriedListAsync(query); + ListResult result = await dbQuery.ToQueriedListAsyncX(query); foreach (MediaListItem item in result.Items) { diff --git a/zero.Core/Collections/Media/MediaCollection.cs b/zero.Core/Collections/Media/MediaCollection.cs index 54a07e1a..b91e4c80 100644 --- a/zero.Core/Collections/Media/MediaCollection.cs +++ b/zero.Core/Collections/Media/MediaCollection.cs @@ -231,7 +231,7 @@ namespace zero.Core.Collections dbQuery = dbQuery.WhereIf(x => x.ParentId == query.FolderId, !query.FolderId.IsNullOrEmpty(), x => x.ParentId == null); } - ListResult result = await dbQuery.ToQueriedListAsync(query); + ListResult result = await dbQuery.ToQueriedListAsyncX(query); foreach (MediaListItem item in result.Items) { diff --git a/zero.Core/Entities/ListQuery.cs b/zero.Core/Entities/ListQuery.cs index d9cd0492..50362490 100644 --- a/zero.Core/Entities/ListQuery.cs +++ b/zero.Core/Entities/ListQuery.cs @@ -6,6 +6,22 @@ using System.Linq.Expressions; namespace zero.Core.Entities { + public class ListBackofficeQuery : ListQuery + { + public ListBackofficeQuery() + { + IncludeInactive = true; + } + } + + public class ListBackofficeQuery : ListQuery where TFilter : IListSpecificQuery + { + public ListBackofficeQuery() + { + IncludeInactive = true; + } + } + public class ListQuery { public string Search { get; set; } = null; @@ -26,6 +42,8 @@ namespace zero.Core.Entities public int PageSize { get; set; } = 30; + public bool IncludeInactive { get; set; } = false; + public void SearchFor(params Expression>[] selectors) { SearchSelectors = selectors; diff --git a/zero.Core/Extensions/RavenQueryableExtensions.cs b/zero.Core/Extensions/RavenQueryableExtensions.cs index 639f0931..617bc1f0 100644 --- a/zero.Core/Extensions/RavenQueryableExtensions.cs +++ b/zero.Core/Extensions/RavenQueryableExtensions.cs @@ -12,10 +12,12 @@ namespace zero.Core.Extensions { public static class RavenQueryableExtensions { + // TODO we need to simplify these extensions methods. + // ToQueriedListAsyncX is used in MediaCollection for the Media_ByParent index, which produces MediaListItem (which is no IZeroEntity) /// /// /// - public static async Task> ToQueriedListAsync(this IRavenQueryable queryable, ListQuery query) + public static async Task> ToQueriedListAsyncX(this IRavenQueryable queryable, ListQuery query) { queryable = queryable.Statistics(out QueryStatistics stats); @@ -59,7 +61,7 @@ namespace zero.Core.Extensions /// /// /// - public static async Task> ToQueriedListAsync(this IRavenQueryable queryable, ListQuery query) where TFilter : IListSpecificQuery + public static async Task> ToQueriedListAsync(this IRavenQueryable queryable, ListQuery query) where T : IZeroEntity { queryable = queryable.Statistics(out QueryStatistics stats); @@ -67,6 +69,60 @@ namespace zero.Core.Extensions if (query != null) { + if (!query.IncludeInactive) + { + rawQuery = rawQuery.Where(x => x.IsActive); + } + + if (!query.Search.IsNullOrEmpty() && query.SearchSelector != null) + { + rawQuery = rawQuery.SearchIf(query.SearchSelector, query.Search, "*", "*", Raven.Client.Documents.Queries.SearchOperator.And); + } + if (!query.Search.IsNullOrEmpty() && query.SearchSelectors.Length > 0) + { + foreach (var selector in query.SearchSelectors) + { + rawQuery = rawQuery.SearchIf(selector, query.Search, "*", "*", Raven.Client.Documents.Queries.SearchOperator.And); + } + } + + if (query.OrderQuery != null) + { + rawQuery = query.OrderQuery(rawQuery); + } + else if (!query.OrderBy.IsNullOrEmpty()) + { + rawQuery = rawQuery.OrderBy(query.OrderBy, query.OrderIsDescending, query.OrderType == ListQueryOrderType.String ? OrderingType.String : OrderingType.Double); + } + + if (query.PageSize > 0) + { + rawQuery = rawQuery.Paging(query.Page, query.PageSize); + } + } + + List items = await rawQuery.ToListAsync(); + + return new ListResult(items, stats.TotalResults, query.Page, query.PageSize); + } + + + /// + /// + /// + public static async Task> ToQueriedListAsync(this IRavenQueryable queryable, ListQuery query) where T : IZeroEntity where TFilter : IListSpecificQuery + { + queryable = queryable.Statistics(out QueryStatistics stats); + + IQueryable rawQuery = queryable; + + if (query != null) + { + if (!query.IncludeInactive) + { + rawQuery = rawQuery.Where(x => x.IsActive); + } + if (!query.Search.IsNullOrEmpty() && query.SearchSelector != null) { rawQuery = rawQuery.SearchIf(query.SearchSelector, query.Search, "*", "*"); diff --git a/zero.Web.UI/app/api/media.js b/zero.Web.UI/app/api/media.js index 5e0b09d8..72439211 100644 --- a/zero.Web.UI/app/api/media.js +++ b/zero.Web.UI/app/api/media.js @@ -31,6 +31,10 @@ const getImageSource = (id, thumb, shared) => { return id.substring(6) + "?preset=productListing"; } + if (Array.isArray(id)) + { + id = id[0]; + } return zero.apiPath + base + 'streamThumbnail/?id=' + id + (typeof thumb === 'boolean' ? '&thumb=' + (thumb ? 'true' : 'false') : '') + (shared === true ? '&scope=shared' : ''); }; diff --git a/zero.Web/Controllers/ApplicationsController.cs b/zero.Web/Controllers/ApplicationsController.cs index 308dd006..1f978609 100644 --- a/zero.Web/Controllers/ApplicationsController.cs +++ b/zero.Web/Controllers/ApplicationsController.cs @@ -28,7 +28,7 @@ namespace zero.Web.Controllers public async Task> GetAll() => await Api.GetAll(); - public async Task> GetByQuery([FromQuery] ListQuery query) => await Api.GetByQuery(query); + public async Task> GetByQuery([FromQuery] ListBackofficeQuery query) => await Api.GetByQuery(query); public IReadOnlyCollection GetAllFeatures() => Options.Features.GetAllItems(); diff --git a/zero.Web/Controllers/BackofficeCollectionController.cs b/zero.Web/Controllers/BackofficeCollectionController.cs index 9b7c7cfc..565f006d 100644 --- a/zero.Web/Controllers/BackofficeCollectionController.cs +++ b/zero.Web/Controllers/BackofficeCollectionController.cs @@ -42,7 +42,7 @@ namespace zero.Web.Controllers public virtual EditModel GetEmpty([FromServices] TEntity blueprint) => Edit(blueprint); - public virtual async Task> GetByQuery([FromQuery] ListQuery query) + public virtual async Task> GetByQuery([FromQuery] ListBackofficeQuery query) { query.SearchSelector = model => model.Name; IRavenQueryable ravenQuery = Collection.Query; diff --git a/zero.Web/Controllers/MediaController.cs b/zero.Web/Controllers/MediaController.cs index 090358a9..b155eb28 100644 --- a/zero.Web/Controllers/MediaController.cs +++ b/zero.Web/Controllers/MediaController.cs @@ -30,7 +30,11 @@ namespace zero.Web.Controllers } - public async Task> GetListByQuery([FromQuery] MediaListItemQuery query) => await Collection.GetListByQuery(query); + public async Task> GetListByQuery([FromQuery] MediaListItemQuery query) + { + query.IncludeInactive = true; + return await Collection.GetListByQuery(query); + } [HttpPost] @@ -45,6 +49,7 @@ namespace zero.Web.Controllers public async Task GetAll([FromQuery] MediaListQuery query) { + query.IncludeInactive = true; ListResult items = (await Collection.GetByQuery(query)).MapTo(x => new MediaListModel() { Id = x.Id, diff --git a/zero.Web/Controllers/RecycleBinController.cs b/zero.Web/Controllers/RecycleBinController.cs index ee2dda79..d86282d7 100644 --- a/zero.Web/Controllers/RecycleBinController.cs +++ b/zero.Web/Controllers/RecycleBinController.cs @@ -15,7 +15,11 @@ namespace zero.Web.Controllers } - public async Task> GetByQuery([FromQuery] RecycleBinListQuery query) => await Api.GetByQuery(query); + public async Task> GetByQuery([FromQuery] RecycleBinListQuery query) + { + query.IncludeInactive = true; + return await Api.GetByQuery(query); + } public async Task GetCountByOperation([FromQuery] string operationId) => await Api.GetCountByOperation(operationId); diff --git a/zero.Web/Controllers/SpacesController.cs b/zero.Web/Controllers/SpacesController.cs index 087d1e21..e9382b31 100644 --- a/zero.Web/Controllers/SpacesController.cs +++ b/zero.Web/Controllers/SpacesController.cs @@ -35,7 +35,7 @@ namespace zero.Web.Controllers public List GetAll() => Api.GetAll().Where(space => CanReadSpace(space.Alias)).ToList(); - public async Task GetList([FromQuery] string alias, [FromQuery] ListQuery query = null) + public async Task GetList([FromQuery] string alias, [FromQuery] ListBackofficeQuery query = null) { if (!CanReadSpace(alias)) { diff --git a/zero.Web/Controllers/TranslationsController.cs b/zero.Web/Controllers/TranslationsController.cs index 78f569db..1a2e0b85 100644 --- a/zero.Web/Controllers/TranslationsController.cs +++ b/zero.Web/Controllers/TranslationsController.cs @@ -16,7 +16,7 @@ namespace zero.Web.Controllers { } - public override async Task> GetByQuery([FromQuery] ListQuery query) + public override async Task> GetByQuery([FromQuery] ListBackofficeQuery query) { query.SearchFor(entity => entity.Key, entity => entity.Value); return await Collection.Query.OrderByDescending(x => x.CreatedDate).ToQueriedListAsync(query); diff --git a/zero.Web/Controllers/UsersController.cs b/zero.Web/Controllers/UsersController.cs index ed4f27de..6c5ae225 100644 --- a/zero.Web/Controllers/UsersController.cs +++ b/zero.Web/Controllers/UsersController.cs @@ -28,7 +28,7 @@ namespace zero.Web.Controllers public async Task> GetById([FromQuery] string id) => Edit(await Api.GetUserById(id)); - public async Task> GetAll([FromQuery] ListQuery query) => await Api.GetByQuery(query); + public async Task> GetAll([FromQuery] ListBackofficeQuery query) => await Api.GetByQuery(query); public IList GetAllPermissions() => PermissionsApi.GetAll();