diff --git a/zero.Core/Api/RevisionsApi.cs b/zero.Core/Api/RevisionsApi.cs
index 05bd0cc1..8a9f4972 100644
--- a/zero.Core/Api/RevisionsApi.cs
+++ b/zero.Core/Api/RevisionsApi.cs
@@ -1,80 +1,56 @@
-using Newtonsoft.Json;
-using Raven.Client.Documents;
-using Raven.Client.Documents.Commands;
-using Raven.Client.Documents.Operations;
-using Raven.Client.Documents.Session;
-using Sparrow.Json;
-using System;
+using Raven.Client.Documents.Session;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using zero.Core.Database;
using zero.Core.Entities;
using zero.Core.Extensions;
-using zero.Core.Options;
namespace zero.Core.Api
{
public class RevisionsApi : IRevisionsApi
{
- protected IZeroOptions Options { get; set; }
+ protected IAsyncDocumentSession Session { get; set; }
- protected IZeroStore Store { get; set; }
-
- protected IUserApi UserApi { get; set; }
-
-
- public RevisionsApi(IZeroOptions options, IZeroStore store, IUserApi userApi)
+ public RevisionsApi(IAsyncDocumentSession session)
{
- Options = options;
- Store = store;
- UserApi = userApi;
+ Session = session;
}
///
/// Get revision list for an entity
///
- public async Task> GetPaged(string id, int pageNumber = 1, int pageSize = 10, bool includeContent = false) where T : ZeroEntity
+ public async Task>> GetPagedWithModel(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity
{
- using IAsyncDocumentSession session = Store.OpenAsyncSession();
-
// get paged revisions
- List items = await session.Advanced.Revisions.GetForAsync(id, (pageNumber - 1) * pageSize, pageSize);
- double totalResults = items.Count;
-
- // get total results in case items count equals page size
- if (pageSize <= items.Count || pageNumber > 1)
- {
- GetRevisionsCommand command = new GetRevisionsCommand(id, 0, 1, true);
- session.Advanced.RequestExecutor.Execute(command, session.Advanced.Context);
- command.Result.Results.Parent.TryGet("TotalResults", out totalResults);
- }
+ List items = await Session.Advanced.Revisions.GetForAsync(id, (pageNumber - 1) * pageSize, pageSize);
+ long totalResults = await Session.Advanced.Revisions.GetCountForAsync(id);
// add creation for last page
- if (!items.Any() && pageNumber >= (int)Math.Ceiling((decimal)totalResults / pageSize))
- {
- T currentRevision = await session.LoadAsync(id);
- if (currentRevision != null)
- {
- items.Add(currentRevision);
- }
- }
+ //if (!items.Any() && pageNumber >= (int)Math.Ceiling((decimal)totalResults / pageSize))
+ //{
+ // T currentRevision = await Session.LoadAsync(id);
+ // if (currentRevision != null)
+ // {
+ // items.Add(currentRevision);
+ // }
+ //}
- List revisions = new List();
+ List> revisions = new();
// load affected users as the revisions could have been edited by other users too
string[] userIds = items.Select(x => x.LastModifiedById).Distinct().ToArray();
- Dictionary users = await UserApi.GetByIds(userIds);
+ Dictionary users = await Session.LoadAsync(userIds);
// create revision objects
foreach (T item in items)
{
- Revision revision = new Revision()
+ Revision revision = new()
{
- ChangeVector = session.Advanced.GetChangeVectorFor(item),
- Date = item.LastModifiedDate,
- Json = includeContent ? JsonConvert.SerializeObject(item) : null
+ Model = item,
+ ModelId = item.Id,
+ ChangeVector = Session.Advanced.GetChangeVectorFor(item),
+ Date = item.LastModifiedDate
};
if (!item.LastModifiedById.IsNullOrEmpty() && users.TryGetValue(item.LastModifiedById, out BackofficeUser user) && user != null)
@@ -90,7 +66,23 @@ namespace zero.Core.Api
revisions.Add(revision);
}
- return new ListResult(revisions, Convert.ToInt64(totalResults), pageNumber, pageSize);
+ return new ListResult>(revisions, totalResults, pageNumber, pageSize);
+ }
+
+
+ ///
+ /// Get revision list for an entity
+ ///
+ public async Task> GetPaged(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity
+ {
+ ListResult> items = await GetPagedWithModel(id, pageNumber, pageSize);
+ return items.MapTo(model => new Revision()
+ {
+ ChangeVector = model.ChangeVector,
+ Date = model.Date,
+ ModelId = model.ModelId,
+ User = model.User
+ });
}
}
@@ -98,8 +90,13 @@ namespace zero.Core.Api
public interface IRevisionsApi
{
///
- /// Get revision list (without content JSON) for an entity
+ /// Get revision list including models for an entity
///
- Task> GetPaged(string id, int pageNumber = 1, int pageSize = 10, bool includeContent = false) where T : ZeroEntity;
+ Task>> GetPagedWithModel(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity;
+
+ ///
+ /// Get revision list for an entity
+ ///
+ Task> GetPaged(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity;
}
}
diff --git a/zero.Core/Collections/CollectionBase.cs b/zero.Core/Collections/CollectionBase.cs
index 35a48101..ed12405f 100644
--- a/zero.Core/Collections/CollectionBase.cs
+++ b/zero.Core/Collections/CollectionBase.cs
@@ -20,6 +20,7 @@ namespace zero.Core.Collections
public abstract class CollectionBase : ICollectionBase, IDisposable where T : ZeroEntity
{
private IAsyncDocumentSession _session;
+ private IRevisionsApi _revisions;
private string _database;
protected ICollectionInterceptorHandler InterceptorHandler { get; private set; }
@@ -54,6 +55,23 @@ namespace zero.Core.Collections
///
protected readonly IValidator Validator;
+ ///
+ /// Manage revisions
+ ///
+ protected IRevisionsApi Revisions
+ {
+ get
+ {
+ if (_revisions != null)
+ {
+ return _revisions;
+ }
+
+ _revisions = new RevisionsApi(Session);
+ return _revisions;
+ }
+ }
+
///
/// Create an an async document session
///
@@ -108,12 +126,16 @@ namespace zero.Core.Collections
///
- public virtual async Task GetById(string id)
+ public virtual async Task GetById(string id, string changeVector = null)
{
if (id.IsNullOrWhiteSpace())
{
return default;
}
+ if (!changeVector.IsNullOrEmpty())
+ {
+ return WhenActive(await GetRevision(changeVector));
+ }
return WhenActive(await Session.LoadAsync(id));
}
@@ -158,6 +180,25 @@ namespace zero.Core.Collections
}
+ ///
+ public virtual async Task> GetRevisions(string id, int page = 1, int pageSize = 10)
+ {
+ if (id.IsNullOrWhiteSpace())
+ {
+ return default;
+ }
+
+ return await Revisions.GetPaged(id, page, pageSize);
+ }
+
+
+ ///
+ public virtual async Task GetRevision(string changeVector)
+ {
+ return await Session.Advanced.Revisions.GetAsync(changeVector);
+ }
+
+
///
public virtual IAsyncEnumerable Stream() => Stream(null);
@@ -445,7 +486,7 @@ namespace zero.Core.Collections
///
/// Get an entity by Id
///
- Task GetById(string id);
+ Task GetById(string id, string changeVector = null);
///
/// Get entities by ids
@@ -463,6 +504,16 @@ namespace zero.Core.Collections
///
Task> GetAll();
+ ///
+ /// Get page revisions for the specified entity
+ ///
+ Task> GetRevisions(string id, int page = 1, int pageSize = 10);
+
+ ///
+ /// Get a revision by change vector
+ ///
+ Task GetRevision(string changeVector);
+
///
/// Stream the collection
///
diff --git a/zero.Core/Collections/Media/MediaCollection.cs b/zero.Core/Collections/Media/MediaCollection.cs
index 3a0ba216..d43bfd43 100644
--- a/zero.Core/Collections/Media/MediaCollection.cs
+++ b/zero.Core/Collections/Media/MediaCollection.cs
@@ -62,7 +62,7 @@ namespace zero.Core.Collections
protected IPaths Paths { get; set; }
- public override Task GetById(string id)
+ public override Task GetById(string id, string changeVector = null)
{
ApplyScopeBasedOnId(id);
return base.GetById(id);
diff --git a/zero.Core/Database/ZeroDocumentConventionsBuilder.cs b/zero.Core/Database/ZeroDocumentConventionsBuilder.cs
index ce856acb..d4171f84 100644
--- a/zero.Core/Database/ZeroDocumentConventionsBuilder.cs
+++ b/zero.Core/Database/ZeroDocumentConventionsBuilder.cs
@@ -81,7 +81,7 @@ namespace zero.Core.Database
};
// get inner type for revisions
- if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Revision<>))
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Raven.Client.Documents.Subscriptions.Revision<>))
{
type = type.GetGenericArguments().FirstOrDefault();
}
diff --git a/zero.Core/Entities/Revision.cs b/zero.Core/Entities/Revision.cs
index 884e2fc7..ac0d88fd 100644
--- a/zero.Core/Entities/Revision.cs
+++ b/zero.Core/Entities/Revision.cs
@@ -2,15 +2,20 @@
namespace zero.Core.Entities
{
+ public class Revision : Revision where T : ZeroEntity
+ {
+ public T Model { get; set; }
+ }
+
public class Revision
{
+ public string ModelId { get; set; }
+
public RevisionUser User { get; set; }
public DateTimeOffset Date { get; set; }
public string ChangeVector { get; set; }
-
- public string Json { get; set; }
}
public class RevisionUser
diff --git a/zero.Web.UI/App/editor/editor.scss b/zero.Web.UI/App/editor/editor.scss
index 49eca368..ced5eaa3 100644
--- a/zero.Web.UI/App/editor/editor.scss
+++ b/zero.Web.UI/App/editor/editor.scss
@@ -119,4 +119,32 @@
margin-top: 0;
padding-top: 0;
border-top: none;
+}
+
+.editor-aside-links
+{
+ display: flex;
+ width: 100%;
+ margin-bottom: -5px;
+}
+
+.editor-aside-links .ui-link
+{
+ color: var(--color-text-dim);
+ font-size: var(--font-size-s);
+ text-decoration: none !important;
+ position: relative;
+}
+
+.editor-aside-links .ui-link + .ui-link
+{
+ margin-left: 20px;
+}
+
+.editor-aside-links .ui-link + .ui-link:before
+{
+ content: '·';
+ position: absolute;
+ left: -12px;
+ top: -1px;
}
\ No newline at end of file
diff --git a/zero.Web.UI/app/utils/request.js b/zero.Web.UI/app/utils/request.js
new file mode 100644
index 00000000..1cac91a6
--- /dev/null
+++ b/zero.Web.UI/app/utils/request.js
@@ -0,0 +1,247 @@
+"use strict";
+var __assign = (this && this.__assign) || function () {
+ __assign = Object.assign || function(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
+ t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
+};
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (_) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.download = exports.collection = exports.send = exports.patch = exports.put = exports.del = exports.post = exports.get = void 0;
+var axios_1 = require("axios");
+var getConfig = function (config) {
+ config = config || {};
+ if (config.scope) {
+ config.params = config.params || {};
+ config.params.scope = config.scope;
+ }
+ return config;
+};
+function get(url, config) {
+ if (config === void 0) { config = null; }
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, send(__assign({ method: 'get', url: url }, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+}
+exports.get = get;
+function post(url, data, config) {
+ if (data === void 0) { data = null; }
+ if (config === void 0) { config = null; }
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, send(__assign({ method: 'post', url: url, data: data }, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+}
+exports.post = post;
+function del(url, config) {
+ if (config === void 0) { config = null; }
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, send(__assign({ method: 'delete', url: url }, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+}
+exports.del = del;
+function put(url, data, config) {
+ if (data === void 0) { data = null; }
+ if (config === void 0) { config = null; }
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, send(__assign({ method: 'put', url: url, data: data }, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+}
+exports.put = put;
+function patch(url, data, config) {
+ if (data === void 0) { data = null; }
+ if (config === void 0) { config = null; }
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, send(__assign({ method: 'patch', url: url, data: data }, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+}
+exports.patch = patch;
+function send(config) {
+ return __awaiter(this, void 0, void 0, function () {
+ var result, err_1;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ config = getConfig(config);
+ _a.label = 1;
+ case 1:
+ _a.trys.push([1, 3, , 4]);
+ return [4 /*yield*/, axios_1.default(config)];
+ case 2:
+ result = _a.sent();
+ return [2 /*return*/, result.data];
+ case 3:
+ err_1 = _a.sent();
+ return [3 /*break*/, 4];
+ case 4: return [2 /*return*/];
+ }
+ });
+ });
+}
+exports.send = send;
+function collection(base) {
+ var _this = this;
+ return {
+ getById: function (id, changeVector, config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, get(base + 'getById', __assign(__assign({}, config), { params: { id: id, changeVector: changeVector } }))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ getByIds: function (ids, config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, get(base + 'getByIds', __assign(__assign({}, config), { params: { ids: ids } }))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ getEmpty: function (config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, get(base + 'getEmpty', __assign({}, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ getByQuery: function (query, config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, get(base + 'getByQuery', __assign(__assign({}, config), { params: { query: query } }))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ getAll: function (config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, get(base + 'getAll', __assign({}, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ getPreviews: function (ids, config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, get(base + 'getPreviews', __assign(__assign({}, config), { params: { ids: ids } }))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ getForPicker: function (config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, get(base + 'getForPicker', __assign({}, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ getRevisions: function (id, query, config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, get(base + 'getRevisions', __assign(__assign({}, config), { params: { id: id, query: query } }))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ save: function (model, config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, post(base + 'save', model, __assign({}, config))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); },
+ delete: function (id, config) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, del(base + 'delete', __assign(__assign({}, config), { params: { id: id } }))];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ }); }); }
+ };
+}
+exports.collection = collection;
+function download(response) {
+ var filename = response.headers["zero-filename"] || 'download.bin';
+ // code from: https://github.com/kennethjiang/js-file-download/blob/master/file-download.js
+ var blob = response.data;
+ if (typeof window.navigator.msSaveBlob !== 'undefined') {
+ // IE workaround for "HTML7007: One or more blob URLs were
+ // revoked by closing the blob for which they were created.
+ // These URLs will no longer resolve as the data backing
+ // the URL has been freed."
+ window.navigator.msSaveBlob(blob, filename);
+ }
+ else {
+ var blobURL = (window.URL && window.URL.createObjectURL) ? window.URL.createObjectURL(blob) : window.webkitURL.createObjectURL(blob);
+ var tempLink = document.createElement('a');
+ tempLink.style.display = 'none';
+ tempLink.href = blobURL;
+ tempLink.setAttribute('download', filename);
+ // Safari thinks _blank anchor are pop ups. We only want to set _blank
+ // target if the browser does not support the HTML5 download attribute.
+ // This allows you to download files in desktop safari if pop up blocking
+ // is enabled.
+ if (typeof tempLink.download === 'undefined') {
+ tempLink.setAttribute('target', '_blank');
+ }
+ document.body.appendChild(tempLink);
+ tempLink.click();
+ // Fixes "webkit blob resource error 1"
+ setTimeout(function () {
+ document.body.removeChild(tempLink);
+ window.URL.revokeObjectURL(blobURL);
+ }, 200);
+ }
+}
+exports.download = download;
+;
+//# sourceMappingURL=request.js.map
\ No newline at end of file
diff --git a/zero.Web.UI/app/utils/request.js.map b/zero.Web.UI/app/utils/request.js.map
new file mode 100644
index 00000000..e50257cc
--- /dev/null
+++ b/zero.Web.UI/app/utils/request.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"request.js","sourceRoot":"","sources":["request.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/zero.Web.UI/app/utils/request.ts b/zero.Web.UI/app/utils/request.ts
index 2399ec29..ecb53b67 100644
--- a/zero.Web.UI/app/utils/request.ts
+++ b/zero.Web.UI/app/utils/request.ts
@@ -56,13 +56,14 @@ export async function send(config)
export function collection(base)
{
return {
- getById: async (id, config) => await get(base + 'getById', { ...config, params: { id } }),
+ getById: async (id, changeVector, config) => await get(base + 'getById', { ...config, params: { id, changeVector } }),
getByIds: async (ids, config) => await get(base + 'getByIds', { ...config, params: { ids } }),
getEmpty: async config => await get(base + 'getEmpty', { ...config }),
getByQuery: async (query, config) => await get(base + 'getByQuery', { ...config, params: { query } }),
getAll: async (config) => await get(base + 'getAll', { ...config }),
getPreviews: async (ids, config) => await get(base + 'getPreviews', { ...config, params: { ids } }),
getForPicker: async (config) => await get(base + 'getForPicker', { ...config }),
+ getRevisions: async (id, query, config) => await get(base + 'getRevisions', { ...config, params: { id, query } }),
save: async (model, config) => await post(base + 'save', model, { ...config }),
delete: async (id, config) => await del(base + 'delete', { ...config, params: { id } })
};
diff --git a/zero.Web/Controllers/BackofficeCollectionController.cs b/zero.Web/Controllers/BackofficeCollectionController.cs
index 4d0ae8e3..bce84aad 100644
--- a/zero.Web/Controllers/BackofficeCollectionController.cs
+++ b/zero.Web/Controllers/BackofficeCollectionController.cs
@@ -35,7 +35,7 @@ namespace zero.Web.Controllers
}
- public virtual async Task> GetById([FromQuery] string id) => Edit(await Collection.GetById(id));
+ public virtual async Task> GetById([FromQuery] string id, [FromQuery] string changeVector = null) => Edit(changeVector.IsNullOrEmpty() ? await Collection.GetById(id) : await Collection.GetRevision(changeVector));
public virtual async Task> GetByIds([FromQuery] string[] ids) => await Collection.GetByIds(ids);
@@ -57,6 +57,12 @@ namespace zero.Web.Controllers
}
+ public virtual async Task> GetRevisions([FromQuery] string id, [FromQuery] ListBackofficeQuery query)
+ {
+ return await Collection.GetRevisions(id, query.Page, query.PageSize);
+ }
+
+
public virtual async Task> GetForPicker() => await SelectList(Collection.Stream(), PickerTransform);
diff --git a/zero.Web/Controllers/PagesController.cs b/zero.Web/Controllers/PagesController.cs
index 9863e259..f66e1af0 100644
--- a/zero.Web/Controllers/PagesController.cs
+++ b/zero.Web/Controllers/PagesController.cs
@@ -16,12 +16,10 @@ namespace zero.Web.Controllers
{
IPagesApi Api;
IZeroStore Store;
- IRevisionsApi RevisionsApi;
- public PagesController(IPagesApi api, IRevisionsApi revisionsApi, IZeroStore store)
+ public PagesController(IPagesApi api, IZeroStore store)
{
Api = api;
- RevisionsApi = revisionsApi;
Store = store;
}
@@ -88,7 +86,8 @@ namespace zero.Web.Controllers
}
- public async Task> GetRevisions([FromQuery] string id, [FromQuery] int page = 1) => await RevisionsApi.GetPaged(id, page);
+ //public async Task> GetRevisions([FromQuery] string id, [FromQuery] int page = 1) => await RevisionsApi.GetPaged(id, page);
+ // TODO this endpoint is available when pages controller moved to BackofficeCollectionController
public async Task> Save([FromBody] Page model) => await Api.Save(model);
diff --git a/zero.Web/Defaults/ZeroBackofficePlugin.cs b/zero.Web/Defaults/ZeroBackofficePlugin.cs
index 9ce8df18..ad15cb66 100644
--- a/zero.Web/Defaults/ZeroBackofficePlugin.cs
+++ b/zero.Web/Defaults/ZeroBackofficePlugin.cs
@@ -99,7 +99,6 @@ namespace zero.Web.Defaults
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();