diff --git a/zero.Core/Api/RevisionsApi.cs b/zero.Core/Api/RevisionsApi.cs
index e416879b..1ddaab3d 100644
--- a/zero.Core/Api/RevisionsApi.cs
+++ b/zero.Core/Api/RevisionsApi.cs
@@ -81,7 +81,7 @@ namespace zero.Core.Api
{
revision.User = new RevisionUser()
{
- AvatarId = user.AvatarId?.Id,
+ AvatarId = user.AvatarId,
Id = user.Id,
Name = user.Name
};
diff --git a/zero.Core/Collections/CollectionBase.cs b/zero.Core/Collections/CollectionBase.cs
index 1ce1c61b..f3b56e78 100644
--- a/zero.Core/Collections/CollectionBase.cs
+++ b/zero.Core/Collections/CollectionBase.cs
@@ -98,28 +98,6 @@ namespace zero.Core.Collections
}
- ///
- public void ResetScope()
- {
- Database = Store.ResolvedDatabase;
- }
-
-
- ///
- public async Task Scoped(string scope, Func action)
- {
- if (scope.IsNullOrEmpty())
- {
- await action();
- return;
- }
-
- ApplyScope(scope);
- await action();
- ResetScope();
- }
-
-
///
public virtual async Task GetById(string id)
{
@@ -460,16 +438,6 @@ namespace zero.Core.Collections
///
void ApplyScope(string scope);
- ///
- /// Resets the scope to the initial value
- ///
- void ResetScope();
-
- ///
- /// Execute scoped actions
- ///
- Task Scoped(string scope, Func action);
-
///
/// Get an entity by Id
///
diff --git a/zero.Core/Entities/Applications/Application.cs b/zero.Core/Entities/Applications/Application.cs
index ce6c7001..87bd341a 100644
--- a/zero.Core/Entities/Applications/Application.cs
+++ b/zero.Core/Entities/Applications/Application.cs
@@ -19,10 +19,10 @@ namespace zero.Core.Entities
public string Email { get; set; }
///
- public Ref ImageId { get; set; }
+ public MediaRef ImageId { get; set; }
///
- public Ref IconId { get; set; }
+ public MediaRef IconId { get; set; }
///
public Uri[] Domains { get; set; } = new Uri[] { };
@@ -53,12 +53,12 @@ namespace zero.Core.Entities
///
/// Image of the application
///
- Ref ImageId { get; set; }
+ MediaRef ImageId { get; set; }
///
/// Simple image of the application (can be used as favicon)
///
- Ref IconId { get; set; }
+ MediaRef IconId { get; set; }
///
/// All assigned domains for this application
diff --git a/zero.Core/Entities/PreviewModel.cs b/zero.Core/Entities/PreviewModel.cs
index 7cbcd6a8..efeb61ca 100644
--- a/zero.Core/Entities/PreviewModel.cs
+++ b/zero.Core/Entities/PreviewModel.cs
@@ -6,8 +6,6 @@
public string Icon { get; set; }
- public Ref Image { get; set; }
-
public string Text { get; set; }
public string Name { get; set; }
diff --git a/zero.Core/Entities/Refs/MediaRef.cs b/zero.Core/Entities/Refs/MediaRef.cs
new file mode 100644
index 00000000..b610e7fb
--- /dev/null
+++ b/zero.Core/Entities/Refs/MediaRef.cs
@@ -0,0 +1,17 @@
+namespace zero.Core.Entities
+{
+ public class MediaRef : Ref
+ {
+ public bool IsCore { get; set; }
+
+ public MediaRef() : base() { }
+ public MediaRef(string id, bool isCore) : base(id)
+ {
+ IsCore = isCore;
+ }
+
+ public static implicit operator string(MediaRef reference) => reference.Id;
+
+ public static implicit operator MediaRef(string id) => new MediaRef(id, false);
+ }
+}
diff --git a/zero.Core/Entities/Refs/Ref.cs b/zero.Core/Entities/Refs/Ref.cs
index c5a963f6..48c3478e 100644
--- a/zero.Core/Entities/Refs/Ref.cs
+++ b/zero.Core/Entities/Refs/Ref.cs
@@ -1,36 +1,36 @@
-using Newtonsoft.Json;
-using zero.Core.Extensions;
-
-namespace zero.Core.Entities
+namespace zero.Core.Entities
{
+ public class Ref : Ref where T : IZeroIdEntity
+ {
+ public Ref() : base() { }
+ public Ref(string id) : base(id) { }
+
+ public static implicit operator Ref(string id) => new Ref(id);
+
+ public static implicit operator string(Ref reference) => reference.Id;
+ }
+
+
public class Ref
{
- public string Id { get; set; }
-
- [JsonProperty("Core")]
- public bool IsCore { get; set; }
-
public Ref() { }
- public Ref(string id) : this()
+ public Ref(string id)
{
Id = id;
}
- public Ref(string id, bool isCore) : this(id)
- {
- IsCore = isCore;
- }
+ public string Id { get; set; }
public override string ToString()
{
- return (IsCore ? "core:" : string.Empty) + Id;
+ return Id;
}
- public static Ref Create(string id, bool isCore = false)
- {
- return id.IsNullOrWhiteSpace() ? null : new Ref(id, isCore);
- }
+
+ public static implicit operator Ref(string id) => new Ref(id);
+
+ public static implicit operator string(Ref reference) => reference.Id;
}
}
diff --git a/zero.Core/Entities/Refs/ValueRef.cs b/zero.Core/Entities/Refs/ValueRef.cs
new file mode 100644
index 00000000..b3782db8
--- /dev/null
+++ b/zero.Core/Entities/Refs/ValueRef.cs
@@ -0,0 +1,42 @@
+namespace zero.Core.Entities
+{
+ public class ValueRef : ValueRef where T : IZeroIdEntity
+ {
+ public ValueRef() : base() { }
+ public ValueRef(string id, string value) : base(id, value) { }
+
+ public static implicit operator string(ValueRef reference) => reference.Id;
+ }
+
+
+ public class ValueRef : Ref where TEntity : IZeroIdEntity
+ {
+ public ValueRef() : base() { }
+ public ValueRef(string id, TValue value) : base(id)
+ {
+ Value = value;
+ }
+
+ public TValue Value { get; set; }
+
+ public static implicit operator string(ValueRef reference) => reference.Id;
+ }
+
+ //public class ValueRef : Ref
+ //{
+ // public ValueRef() : base() { }
+
+ // public ValueRef(string id, string value) : base(id)
+ // {
+ // Value = value;
+ // }
+
+ // public string Value { get; set; }
+
+
+ // public override string ToString()
+ // {
+ // return (Id, Value).ToString();
+ // }
+ //}
+}
diff --git a/zero.Core/Entities/User/BackofficeUser.cs b/zero.Core/Entities/User/BackofficeUser.cs
index ebe1b1ec..74f426dc 100644
--- a/zero.Core/Entities/User/BackofficeUser.cs
+++ b/zero.Core/Entities/User/BackofficeUser.cs
@@ -32,7 +32,7 @@ namespace zero.Core.Entities
public string SecurityStamp { get; set; }
///
- public Ref AvatarId { get; set; }
+ public MediaRef AvatarId { get; set; }
///
public string LanguageId { get; set; }
@@ -99,7 +99,7 @@ namespace zero.Core.Entities
///
/// Avatar image
///
- Ref AvatarId { get; set; }
+ MediaRef AvatarId { get; set; }
///
/// Backoffice display language
diff --git a/zero.Core/Extensions/ObjectExtensions.cs b/zero.Core/Extensions/ObjectExtensions.cs
index 34c5b613..c62b534c 100644
--- a/zero.Core/Extensions/ObjectExtensions.cs
+++ b/zero.Core/Extensions/ObjectExtensions.cs
@@ -21,12 +21,12 @@ namespace zero.Core.Extensions
public static T Clone(this T obj)
{
Type type = obj.GetType();
- return (T)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(obj), type);
+ return (T)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(obj, new RefJsonConverter()), type, new RefJsonConverter());
}
public static T CloneLax(this object obj)
{
- return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(obj));
+ return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(obj, new RefJsonConverter()), new RefJsonConverter());
}
}
}
diff --git a/zero.Core/Extensions/RavenDocumentStoreExtensions.cs b/zero.Core/Extensions/RavenDocumentStoreExtensions.cs
index 2bce6ed7..8f889893 100644
--- a/zero.Core/Extensions/RavenDocumentStoreExtensions.cs
+++ b/zero.Core/Extensions/RavenDocumentStoreExtensions.cs
@@ -15,6 +15,7 @@ namespace zero.Core.Extensions
{
public static class RavenDocumentStoreExtensions
{
+ const char DOT = '.';
///
/// Setup conventions for the document store
///
@@ -24,7 +25,7 @@ namespace zero.Core.Extensions
Type dbConventionType = typeof(IZeroDbConventions);
- store.Conventions.IdentityPartsSeparator = '.';
+ store.Conventions.IdentityPartsSeparator = DOT;
store.Conventions.RegisterAsyncIdConvention((_, entity) =>
{
@@ -39,6 +40,15 @@ namespace zero.Core.Extensions
return store.Conventions.AsyncDocumentIdGenerator(_, entity);
});
+ (store.Conventions.Serialization as NewtonsoftJsonSerializationConventions).CustomizeJsonDeserializer = x =>
+ {
+ x.Converters.Add(new RefJsonConverter());
+ };
+ (store.Conventions.Serialization as NewtonsoftJsonSerializationConventions).CustomizeJsonSerializer = x =>
+ {
+ x.Converters.Add(new RefJsonConverter());
+ };
+
store.Conventions.FindCollectionName = type =>
{
Type finalType = type;
diff --git a/zero.Core/Utils/RefJsonConverter.cs b/zero.Core/Utils/RefJsonConverter.cs
new file mode 100644
index 00000000..fb4b7b17
--- /dev/null
+++ b/zero.Core/Utils/RefJsonConverter.cs
@@ -0,0 +1,61 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using zero.Core.Entities;
+using zero.Core.Extensions;
+
+namespace zero.Core.Utils
+{
+ public class RefJsonConverter : JsonConverter
+ {
+ private readonly Type type;
+
+ public RefJsonConverter()
+ {
+ type = typeof(Ref<>);
+ }
+
+
+ public override bool CanRead => true;
+
+ public override bool CanWrite => true;
+
+ public override bool CanConvert(Type objectType) => objectType.IsGenericType && objectType.GetGenericTypeDefinition() == type;
+
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ string id = null;
+
+ if (value is Ref)
+ {
+ id = (value as Ref).Id;
+ }
+
+ if (id.IsNullOrEmpty())
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ writer.WriteValue(id);
+ }
+ }
+
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (!(reader.Value is string))
+ {
+ return null;
+ }
+
+ if (((string)reader.Value).IsNullOrEmpty())
+ {
+ return null;
+ }
+
+ return Activator.CreateInstance(objectType, new object[1] { reader.Value });
+ }
+ }
+}
diff --git a/zero.Web.UI/App/components/pickers/mediaPicker/mediapicker.vue b/zero.Web.UI/App/components/pickers/mediaPicker/mediapicker.vue
index d168289e..63a207b7 100644
--- a/zero.Web.UI/App/components/pickers/mediaPicker/mediapicker.vue
+++ b/zero.Web.UI/App/components/pickers/mediaPicker/mediapicker.vue
@@ -69,7 +69,7 @@
props: {
value: {
- type: [Array, Object, String],
+ type: [Array, String],
default: null
},
disabled: {
diff --git a/zero.Web.UI/App/editor/fields/media.vue b/zero.Web.UI/App/editor/fields/media.vue
index dd8e20c3..a30d63e1 100644
--- a/zero.Web.UI/App/editor/fields/media.vue
+++ b/zero.Web.UI/App/editor/fields/media.vue
@@ -7,7 +7,7 @@
export default {
props: {
value: {
- type: [String, Object, Array],
+ type: [String, Array],
default: null
},
disabled: {
diff --git a/zero.Web.UI/app/api/media.js b/zero.Web.UI/app/api/media.js
index 28a42953..5e0b09d8 100644
--- a/zero.Web.UI/app/api/media.js
+++ b/zero.Web.UI/app/api/media.js
@@ -23,11 +23,6 @@ const upload = async (file, folderId, onProgress, isTemporary) =>
const getImageSource = (id, thumb, shared) =>
{
- if (typeof id === 'object')
- {
- shared = id.isCore;
- id = id.id;
- }
if (!id || id.indexOf('http') === 0)
{
return id;
diff --git a/zero.Web/Controllers/UsersController.cs b/zero.Web/Controllers/UsersController.cs
index a75b4262..ed4f27de 100644
--- a/zero.Web/Controllers/UsersController.cs
+++ b/zero.Web/Controllers/UsersController.cs
@@ -47,7 +47,7 @@ namespace zero.Web.Controllers
return Previews(await Api.GetByIds(ids.ToArray()), item => new PreviewModel()
{
Id = item.Id,
- Image = item.AvatarId,
+ Icon = item.AvatarId,
Name = item.Name
});
}
diff --git a/zero.Web/Models/UserEditModel.cs b/zero.Web/Models/UserEditModel.cs
index eb34831b..3425009b 100644
--- a/zero.Web/Models/UserEditModel.cs
+++ b/zero.Web/Models/UserEditModel.cs
@@ -14,7 +14,7 @@ namespace zero.Web.Models
public bool IsEmailConfirmed { get; set; }
- public Ref AvatarId { get; set; }
+ public string AvatarId { get; set; }
public string LanguageId { get; set; }
diff --git a/zero.Web/ViewHelpers/ZeroMediaHelper.cs b/zero.Web/ViewHelpers/ZeroMediaHelper.cs
index 6282910e..c309a4ca 100644
--- a/zero.Web/ViewHelpers/ZeroMediaHelper.cs
+++ b/zero.Web/ViewHelpers/ZeroMediaHelper.cs
@@ -6,7 +6,6 @@ using zero.Core.Api;
using zero.Core.Entities;
using zero.Core.Routing;
using zero.Core.Extensions;
-using zero.Core.Collections;
namespace zero.Web.ViewHelpers
{
@@ -14,7 +13,7 @@ namespace zero.Web.ViewHelpers
{
HttpContext HttpContext;
- IMediaCollection MediaCollection;
+ IMediaApi MediaApi;
///
/// Media cache for repetitive queries within an HTTP request
@@ -22,10 +21,10 @@ namespace zero.Web.ViewHelpers
Dictionary Cache { get; set; } = new Dictionary();
- public ZeroMediaHelper(IHttpContextAccessor httpContextAccessor, IMediaCollection mediaCollection)
+ public ZeroMediaHelper(IHttpContextAccessor httpContextAccessor, IMediaApi mediaApi)
{
HttpContext = httpContextAccessor.HttpContext;
- MediaCollection = mediaCollection;
+ MediaApi = mediaApi;
}
@@ -39,30 +38,7 @@ namespace zero.Web.ViewHelpers
if (!Cache.TryGetValue(id, out IMedia media))
{
- media = await MediaCollection.GetById(id);
- Cache.Add(id, media);
- }
-
- return media;
- }
-
-
- ///
- public async Task GetById(Ref reference)
- {
- if (reference == null)
- {
- return null;
- }
-
- string id = reference.ToString();
-
- if (!Cache.TryGetValue(id, out IMedia media))
- {
- await MediaCollection.Scoped(reference.IsCore ? "shared" : null, async() =>
- {
- media = await MediaCollection.GetById(reference.Id);
- });
+ media = await MediaApi.GetById(id);
Cache.Add(id, media);
}
@@ -90,7 +66,7 @@ namespace zero.Web.ViewHelpers
if (remoteIds.Count > 0)
{
- Dictionary remoteItems = await MediaCollection.GetByIds(remoteIds.ToArray());
+ Dictionary remoteItems = await MediaApi.GetById(remoteIds);
foreach (var item in remoteItems)
{
@@ -103,39 +79,6 @@ namespace zero.Web.ViewHelpers
}
- ///
- public async Task> GetByIds(Ref[] references)
- {
- HashSet[ remoteIds = new HashSet][();
- Dictionary items = new Dictionary();
-
- foreach (Ref reference in references)
- {
- string id = reference.ToString();
-
- if (Cache.TryGetValue(id, out IMedia media))
- {
- items.Add(id, media);
- }
- else
- {
- remoteIds.Add(reference);
- }
- }
-
- if (remoteIds.Count > 0)
- {
- foreach (Ref reference in remoteIds)
- {
- // TODO this is super unperformant as we are switching scopes per request here
- items.Add(reference.Id, await GetById(reference));
- }
- }
-
- return items;
- }
-
-
///
public async Task GetUrl(string id, bool isAbsolute = false)
{
@@ -144,28 +87,12 @@ namespace zero.Web.ViewHelpers
}
- ///
- public async Task GetUrl(Ref reference, bool isAbsolute = false)
- {
- IMedia media = await GetById(reference);
- return media?.Source;
- }
-
-
///
public async Task> GetUrls(string[] ids, bool isAbsolute = false)
{
Dictionary medias = await GetByIds(ids);
return medias.ToDictionary(x => x.Key, x => x.Value?.Source);
}
-
-
- ///
- public async Task> GetUrls(Ref[] references, bool isAbsolute = false)
- {
- Dictionary medias = await GetByIds(references);
- return medias.ToDictionary(x => x.Key, x => x.Value?.Source);
- }
}
@@ -190,25 +117,5 @@ namespace zero.Web.ViewHelpers
/// Get source for media items
/// ]
Task> GetUrls(string[] ids, bool isAbsolute = false);
-
- ///
- /// Get media by Id
- ///
- Task GetById(Ref reference);
-
- ///
- /// Get media items by Ids
- ///
- Task> GetByIds(Ref[] references);
-
- ///
- /// Get source for a media item
- ///
- Task GetUrl(Ref reference, bool isAbsolute = false);
-
- ///
- /// Get source for media items
- ///
- Task> GetUrls(Ref[] references, bool isAbsolute = false);
}
}