diff --git a/zero.Core/Api/BackofficeApi.cs b/zero.Core/Api/BackofficeApi.cs
index 2ac23def..f42dfe94 100644
--- a/zero.Core/Api/BackofficeApi.cs
+++ b/zero.Core/Api/BackofficeApi.cs
@@ -241,16 +241,33 @@ namespace zero.Core.Api
}
+ ///
+ public async Task DeleteByIds(params string[] ids) where T : IZeroIdEntity
+ {
+ int successCount = 0;
+
+ foreach (string id in ids)
+ {
+ EntityResult result = await DeleteById(id);
+ successCount += result.IsSuccess ? 1 : 0;
+ }
+
+ return successCount;
+ }
+
+
///
public async Task Purge(string querySuffix = null, Parameters parameters = null)
{
var collectionName = Raven.Conventions.FindCollectionName(typeof(T));
- Operation operation = await Raven.Operations.SendAsync(new DeleteByQueryOperation(new IndexQuery()
+ var operationQuery = new DeleteByQueryOperation(new IndexQuery()
{
- Query = $"from {collectionName} {querySuffix ?? String.Empty}",
+ Query = $"from {collectionName} c {querySuffix ?? String.Empty}",
QueryParameters = parameters
- }));
+ });
+
+ Operation operation = await Raven.Operations.SendAsync(operationQuery);
await operation.WaitForCompletionAsync(TimeSpan.FromSeconds(30));
}
@@ -281,6 +298,11 @@ namespace zero.Core.Api
///
Task> DeleteById(string id) where T : IZeroIdEntity;
+ ///
+ /// Deletes entities by Id
+ ///
+ Task DeleteByIds(params string[] ids) where T : IZeroIdEntity;
+
///
/// Delete a whole collection (with an optional query suffix, i.e. a where statement)
///
diff --git a/zero.Core/Api/PagesApi.cs b/zero.Core/Api/PagesApi.cs
index 93611ab6..210dd484 100644
--- a/zero.Core/Api/PagesApi.cs
+++ b/zero.Core/Api/PagesApi.cs
@@ -15,11 +15,17 @@ namespace zero.Core.Api
{
public class PagesApi : AppAwareBackofficeApi, IPagesApi where T : IPage
{
+ const string RECYCLE_BIN_GROUP = "pages";
+
protected IZeroOptions Options { get; private set; }
- public PagesApi(IZeroOptions options, IBackofficeStore store) : base(store)
+ protected IRecycleBinApi RecycleBinApi { get; private set; }
+
+
+ public PagesApi(IZeroOptions options, IBackofficeStore store, IRecycleBinApi recycleBinApi) : base(store)
{
Options = options;
+ RecycleBinApi = recycleBinApi;
}
@@ -180,51 +186,39 @@ namespace zero.Core.Api
public async Task> Delete(string id, bool moveToRecycleBin = true)
{
IList pages = await GetByIdWithDescendants(id);
+ string[] ids = pages.Select(x => x.Id).ToArray();
- using (IAsyncDocumentSession session = Raven.OpenAsyncSession())
+ if (moveToRecycleBin)
{
- session.Advanced.WaitForIndexesAfterSaveChanges(throwOnTimeout: false);
-
- foreach (T page in pages)
- {
- if (moveToRecycleBin)
- {
- page.IsRecycled = true;
- await session.StoreAsync(page);
- }
- else
- {
- session.Delete(page.Id);
- }
- }
-
- await session.SaveChangesAsync();
+ await RecycleBinApi.Add(pages, RECYCLE_BIN_GROUP);
}
- return EntityResult.Success(pages.Select(x => x.Id).ToArray());
+ await DeleteByIds(ids);
+
+ return EntityResult.Success(ids);
}
///
- public async Task> Restore(string id)
- {
- IList pages = await GetByIdWithDescendants(id);
+ //public async Task> Restore(string id)
+ //{
+ // IList pages = await GetByIdWithDescendants(id);
- using (IAsyncDocumentSession session = Raven.OpenAsyncSession())
- {
- session.Advanced.WaitForIndexesAfterSaveChanges(throwOnTimeout: false);
+ // using (IAsyncDocumentSession session = Raven.OpenAsyncSession())
+ // {
+ // session.Advanced.WaitForIndexesAfterSaveChanges(throwOnTimeout: false);
- foreach (T page in pages)
- {
- page.IsRecycled = false;
- await session.StoreAsync(page);
- }
+ // foreach (T page in pages)
+ // {
+ // page.IsRecycled = false;
+ // await session.StoreAsync(page);
+ // }
- await session.SaveChangesAsync();
- }
+ // await session.SaveChangesAsync();
+ // }
- return EntityResult.Success(pages.Select(x => x.Id).ToArray());
- }
+ // return EntityResult.Success(pages.Select(x => x.Id).ToArray());
+ //}
///
@@ -327,6 +321,6 @@ namespace zero.Core.Api
///
/// Restores a page from the recycle bin
///
- Task> Restore(string id);
+ //Task> Restore(string id);
}
}
diff --git a/zero.Core/Api/RecycleBinApi.cs b/zero.Core/Api/RecycleBinApi.cs
index 177130b3..ee405f3b 100644
--- a/zero.Core/Api/RecycleBinApi.cs
+++ b/zero.Core/Api/RecycleBinApi.cs
@@ -1,4 +1,6 @@
-using Raven.Client.Documents.Session;
+using Newtonsoft.Json;
+using Raven.Client.Documents.Session;
+using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using zero.Core.Entities;
@@ -7,60 +9,60 @@ using zero.Core.Utils;
namespace zero.Core.Api
{
- public class RecycleBinApi : AppAwareBackofficeApi, IRecycleBinApi where T : IRecycledEntity, new()
+ public class RecycleBinApi : AppAwareBackofficeApi, IRecycleBinApi
{
- public RecycleBinApi(IBackofficeStore store) : base(store)
+ Type Type;
+
+ public RecycleBinApi(IBackofficeStore store, IRecycledEntity entity) : base(store)
{
-
+ Type = entity.GetType();
}
///
- public async Task> Add(TEntity model, string group = null, string operationId = null) where TEntity : IZeroEntity
+ public async Task> Add(TEntity model, string group = null, string operationId = null) where TEntity : IZeroEntity
{
- T entity = new T()
- {
- Group = group,
- Content = null,
- OriginalId = model.Id,
- OperationId = operationId,
- Name = model.Name
- };
+ IRecycledEntity entity = Activator.CreateInstance(Type) as IRecycledEntity;
+ entity.Group = group;
+ entity.Content = model;
+ entity.OriginalId = model.Id;
+ entity.OperationId = operationId;
+ entity.Name = model.Name;
return await SaveModel(entity);
}
///
- public async Task>> Add(IEnumerable models, string group = null) where TEntity : IZeroEntity
+ public async Task>> Add(IEnumerable models, string group = null) where TEntity : IZeroEntity
{
- IList results = new List();
+ IList results = new List();
string operationId = IdGenerator.Create();
foreach (TEntity model in models)
{
- EntityResult result = await Add(model, group, operationId);
+ EntityResult result = await Add(model, group, operationId);
if (!result.IsSuccess)
{
- return EntityResult>.Fail(result.Errors);
+ return EntityResult>.Fail(result.Errors);
}
results.Add(result.Model);
}
- return EntityResult>.Success(results);
+ return EntityResult>.Success(results);
}
///
- public async Task> GetByQuery(RecycleBinListQuery query)
+ public async Task> GetByQuery(RecycleBinListQuery query)
{
query.SearchSelector = x => x.Name;
using (IAsyncDocumentSession session = Raven.OpenAsyncSession())
{
- return await session.Query()
+ return await session.Query()
.Scope(Scope)
.WhereIf(x => x.Group == query.Group, !query.Group.IsNullOrWhiteSpace())
.WhereIf(x => x.OperationId == query.OperationId, !query.OperationId.IsNullOrWhiteSpace())
@@ -72,7 +74,7 @@ namespace zero.Core.Api
///
public async Task Delete(string id)
{
- await DeleteById(id);
+ await DeleteById(id);
}
@@ -80,41 +82,40 @@ namespace zero.Core.Api
public async Task DeleteAll()
{
// TODO make Purge operations app-aware
- await Purge();
+ await Purge();
}
///
public async Task DeleteByOperation(string operationId)
{
- await Purge("where OperationId = $id", new Raven.Client.Parameters() { { "id", operationId } });
+ await Purge("where c.OperationId = $id", new Raven.Client.Parameters() { { "id", operationId } });
}
///
public async Task DeleteByGroup(string group)
{
- await Purge("where Group = $group", new Raven.Client.Parameters() { { "group", group } });
+ await Purge("where c.Group = $group", new Raven.Client.Parameters() { { "group", group } });
}
}
-
- public interface IRecycleBinApi where T : IRecycledEntity
+ public interface IRecycleBinApi
{
///
/// Adds an entity to the recycle bin. This operation will not remove this entity from it's own collection!
///
- Task> Add(TEntity model, string group = null, string operationId = null) where TEntity : IZeroEntity;
+ Task> Add(TEntity model, string group = null, string operationId = null) where TEntity : IZeroEntity;
///
/// Adds the specified entities to the recycle bin. This operation will not remove entities from their own collection!
///
- Task>> Add(IEnumerable models, string group = null) where TEntity : IZeroEntity;
+ Task>> Add(IEnumerable models, string group = null) where TEntity : IZeroEntity;
///
/// Get all recycled items
///
- Task> GetByQuery(RecycleBinListQuery query);
+ Task> GetByQuery(RecycleBinListQuery query);
//
/// Deletes a country by Id
diff --git a/zero.Core/Entities/Pages/Page.cs b/zero.Core/Entities/Pages/Page.cs
index c4b16c22..79f263db 100644
--- a/zero.Core/Entities/Pages/Page.cs
+++ b/zero.Core/Entities/Pages/Page.cs
@@ -17,9 +17,6 @@ namespace zero.Core.Entities
///
public string AppId { get; set; }
- ///
- public bool IsRecycled { get; set; }
-
///
public DateTimeOffset? PublishDate { get; set; }
@@ -40,11 +37,6 @@ namespace zero.Core.Entities
///
string PageTypeAlias { get; set; }
- ///
- /// Whether this page is recycled or not
- ///
- bool IsRecycled { get; set; }
-
///
/// Date when the page is published
///
diff --git a/zero.Core/Entities/RecycleBin/RecycledEntity.cs b/zero.Core/Entities/RecycleBin/RecycledEntity.cs
index da27cfff..385f25c1 100644
--- a/zero.Core/Entities/RecycleBin/RecycledEntity.cs
+++ b/zero.Core/Entities/RecycleBin/RecycledEntity.cs
@@ -17,7 +17,7 @@ namespace zero.Core.Entities
public string Group { get; set; }
///
- public string Content { get; set; }
+ public IZeroEntity Content { get; set; }
}
@@ -35,9 +35,9 @@ namespace zero.Core.Entities
string OperationId { get; set; }
///
- /// Contains the entity content as JSON
+ /// Contains the entity content
///
- string Content { get; set; }
+ IZeroEntity Content { get; set; }
///
/// Recycled entities can be grouped together (e.g. pages, media, ...)
diff --git a/zero.Core/Entities/Translation.cs b/zero.Core/Entities/Translation.cs
index f70546c2..717888d6 100644
--- a/zero.Core/Entities/Translation.cs
+++ b/zero.Core/Entities/Translation.cs
@@ -1,4 +1,6 @@
-namespace zero.Core.Entities
+using zero.Core.Attributes;
+
+namespace zero.Core.Entities
{
public class Translation : ZeroEntity, ITranslation
{
@@ -26,6 +28,7 @@
}
+ [Collection("Translations")]
public interface ITranslation : IZeroEntity, ILanguageAwareEntity, IAppAwareShareableEntity, IZeroDbConventions
{
///
diff --git a/zero.Debug/Controllers/TestController.cs b/zero.Debug/Controllers/TestController.cs
index 3d35e60e..eb71c8b7 100644
--- a/zero.Debug/Controllers/TestController.cs
+++ b/zero.Debug/Controllers/TestController.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Threading.Tasks;
using zero.Core.Api;
using zero.Core.Entities;
+using zero.Core.Utils;
namespace zero.Debug.Controllers
{
@@ -56,6 +57,7 @@ namespace zero.Debug.Controllers
}
+
[HttpGet]
public IActionResult Things([FromServices] IValidator appValidator)
{
diff --git a/zero.Web/Controllers/PagesController.cs b/zero.Web/Controllers/PagesController.cs
index 3337cde9..4a31529b 100644
--- a/zero.Web/Controllers/PagesController.cs
+++ b/zero.Web/Controllers/PagesController.cs
@@ -55,7 +55,7 @@ namespace zero.Web.Controllers
public async Task Copy([FromBody] CopyModel model) => Json(await Api.Copy(model.Id, model.DestinationId, model.IncludeDescendants));
- public async Task Delete([FromQuery] string id, [FromQuery] bool moveToRecycleBin = false) => Json(await Api.Delete(id, moveToRecycleBin));
+ public async Task Delete([FromQuery] string id) => Json(await Api.Delete(id, true));
public class CopyModel
diff --git a/zero.Web/Defaults/ZeroBackofficePlugin.cs b/zero.Web/Defaults/ZeroBackofficePlugin.cs
index e238c852..7a5ed78d 100644
--- a/zero.Web/Defaults/ZeroBackofficePlugin.cs
+++ b/zero.Web/Defaults/ZeroBackofficePlugin.cs
@@ -35,7 +35,8 @@ namespace zero.Web.Defaults
services.AddTransient(typeof(IPagesApi<>), typeof(PagesApi<>));
services.AddTransient(typeof(IPageTreeApi<>), typeof(PageTreeApi<>));
services.AddTransient(typeof(IUserApi<>), typeof(UserApi<>));
- services.AddTransient(typeof(IRecycleBinApi<>), typeof(RecycleBinApi<>));
+ services.AddTransient(typeof(IRecycleBinApi), typeof(RecycleBinApi));
+ // services.AddTransient(typeof(IRecycleBinApi), typeof(RecycleBinApi));
services.AddTransient();
services.AddTransient();