add revisions to collections
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get revision list for an entity
|
||||
/// </summary>
|
||||
public async Task<ListResult<Revision>> GetPaged<T>(string id, int pageNumber = 1, int pageSize = 10, bool includeContent = false) where T : ZeroEntity
|
||||
public async Task<ListResult<Revision<T>>> GetPagedWithModel<T>(string id, int pageNumber = 1, int pageSize = 10) where T : ZeroEntity
|
||||
{
|
||||
using IAsyncDocumentSession session = Store.OpenAsyncSession();
|
||||
|
||||
// get paged revisions
|
||||
List<T> items = await session.Advanced.Revisions.GetForAsync<T>(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<T> items = await Session.Advanced.Revisions.GetForAsync<T>(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<T>(id);
|
||||
if (currentRevision != null)
|
||||
{
|
||||
items.Add(currentRevision);
|
||||
}
|
||||
}
|
||||
//if (!items.Any() && pageNumber >= (int)Math.Ceiling((decimal)totalResults / pageSize))
|
||||
//{
|
||||
// T currentRevision = await Session.LoadAsync<T>(id);
|
||||
// if (currentRevision != null)
|
||||
// {
|
||||
// items.Add(currentRevision);
|
||||
// }
|
||||
//}
|
||||
|
||||
List<Revision> revisions = new List<Revision>();
|
||||
List<Revision<T>> 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<string, BackofficeUser> users = await UserApi.GetByIds(userIds);
|
||||
Dictionary<string, BackofficeUser> users = await Session.LoadAsync<BackofficeUser>(userIds);
|
||||
|
||||
// create revision objects
|
||||
foreach (T item in items)
|
||||
{
|
||||
Revision revision = new Revision()
|
||||
Revision<T> 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<Revision>(revisions, Convert.ToInt64(totalResults), pageNumber, pageSize);
|
||||
return new ListResult<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
|
||||
{
|
||||
ListResult<Revision<T>> items = await GetPagedWithModel<T>(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
|
||||
{
|
||||
/// <summary>
|
||||
/// Get revision list (without content JSON) for an entity
|
||||
/// Get revision list including models for an entity
|
||||
/// </summary>
|
||||
Task<ListResult<Revision>> GetPaged<T>(string id, int pageNumber = 1, int pageSize = 10, bool includeContent = false) where T : ZeroEntity;
|
||||
Task<ListResult<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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace zero.Core.Collections
|
||||
public abstract class CollectionBase<T> : ICollectionBase<T>, 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
|
||||
/// </summary>
|
||||
protected readonly IValidator<T> Validator;
|
||||
|
||||
/// <summary>
|
||||
/// Manage revisions
|
||||
/// </summary>
|
||||
protected IRevisionsApi Revisions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_revisions != null)
|
||||
{
|
||||
return _revisions;
|
||||
}
|
||||
|
||||
_revisions = new RevisionsApi(Session);
|
||||
return _revisions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an an async document session
|
||||
/// </summary>
|
||||
@@ -108,12 +126,16 @@ namespace zero.Core.Collections
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<T> GetById(string id)
|
||||
public virtual async Task<T> GetById(string id, string changeVector = null)
|
||||
{
|
||||
if (id.IsNullOrWhiteSpace())
|
||||
{
|
||||
return default;
|
||||
}
|
||||
if (!changeVector.IsNullOrEmpty())
|
||||
{
|
||||
return WhenActive(await GetRevision(changeVector));
|
||||
}
|
||||
|
||||
return WhenActive(await Session.LoadAsync<T>(id));
|
||||
}
|
||||
@@ -158,6 +180,25 @@ namespace zero.Core.Collections
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<ListResult<Revision>> GetRevisions(string id, int page = 1, int pageSize = 10)
|
||||
{
|
||||
if (id.IsNullOrWhiteSpace())
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return await Revisions.GetPaged<T>(id, page, pageSize);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<T> GetRevision(string changeVector)
|
||||
{
|
||||
return await Session.Advanced.Revisions.GetAsync<T>(changeVector);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IAsyncEnumerable<T> Stream() => Stream(null);
|
||||
|
||||
@@ -445,7 +486,7 @@ namespace zero.Core.Collections
|
||||
/// <summary>
|
||||
/// Get an entity by Id
|
||||
/// </summary>
|
||||
Task<T> GetById(string id);
|
||||
Task<T> GetById(string id, string changeVector = null);
|
||||
|
||||
/// <summary>
|
||||
/// Get entities by ids
|
||||
@@ -463,6 +504,16 @@ namespace zero.Core.Collections
|
||||
/// </summary>
|
||||
Task<List<T>> GetAll();
|
||||
|
||||
/// <summary>
|
||||
/// Get page revisions for the specified entity
|
||||
/// </summary>
|
||||
Task<ListResult<Revision>> GetRevisions(string id, int page = 1, int pageSize = 10);
|
||||
|
||||
/// <summary>
|
||||
/// Get a revision by change vector
|
||||
/// </summary>
|
||||
Task<T> GetRevision(string changeVector);
|
||||
|
||||
/// <summary>
|
||||
/// Stream the collection
|
||||
/// </summary>
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace zero.Core.Collections
|
||||
protected IPaths Paths { get; set; }
|
||||
|
||||
|
||||
public override Task<Media> GetById(string id)
|
||||
public override Task<Media> GetById(string id, string changeVector = null)
|
||||
{
|
||||
ApplyScopeBasedOnId(id);
|
||||
return base.GetById(id);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -2,15 +2,20 @@
|
||||
|
||||
namespace zero.Core.Entities
|
||||
{
|
||||
public class Revision<T> : 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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"request.js","sourceRoot":"","sources":["request.ts"],"names":[],"mappings":"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"}
|
||||
@@ -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 } })
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace zero.Web.Controllers
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<EditModel<TEntity>> GetById([FromQuery] string id) => Edit(await Collection.GetById(id));
|
||||
public virtual async Task<EditModel<TEntity>> GetById([FromQuery] string id, [FromQuery] string changeVector = null) => Edit(changeVector.IsNullOrEmpty() ? await Collection.GetById(id) : await Collection.GetRevision(changeVector));
|
||||
|
||||
|
||||
public virtual async Task<Dictionary<string, TEntity>> GetByIds([FromQuery] string[] ids) => await Collection.GetByIds(ids);
|
||||
@@ -57,6 +57,12 @@ namespace zero.Web.Controllers
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<ListResult<Revision>> GetRevisions([FromQuery] string id, [FromQuery] ListBackofficeQuery<TEntity> query)
|
||||
{
|
||||
return await Collection.GetRevisions(id, query.Page, query.PageSize);
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<IEnumerable<SelectModel>> GetForPicker() => await SelectList(Collection.Stream(), PickerTransform);
|
||||
|
||||
|
||||
|
||||
@@ -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<ListResult<Revision>> GetRevisions([FromQuery] string id, [FromQuery] int page = 1) => await RevisionsApi.GetPaged<Page>(id, page);
|
||||
//public async Task<ListResult<Revision>> GetRevisions([FromQuery] string id, [FromQuery] int page = 1) => await RevisionsApi.GetPaged<Page>(id, page);
|
||||
// TODO this endpoint is available when pages controller moved to BackofficeCollectionController
|
||||
|
||||
|
||||
public async Task<EntityResult<Page>> Save([FromBody] Page model) => await Api.Save(model);
|
||||
|
||||
@@ -99,7 +99,6 @@ namespace zero.Web.Defaults
|
||||
services.AddTransient<IToken, Token>();
|
||||
services.AddTransient<ISpacesApi, SpacesApi>();
|
||||
services.AddTransient<IPermissionsApi, PermissionsApi>();
|
||||
services.AddTransient<IRevisionsApi, RevisionsApi>();
|
||||
services.AddTransient<IMediaApi, MediaApi>();
|
||||
services.AddTransient<IMediaFolderApi, MediaFolderApi>();
|
||||
services.AddTransient<IModulesApi, ModulesApi>();
|
||||
|
||||
Reference in New Issue
Block a user