renderer updates
This commit is contained in:
+2
-1
@@ -270,4 +270,5 @@ Temp/
|
||||
**/Assets/setup.*
|
||||
**/Assets/*.js
|
||||
deps/*.dll
|
||||
zero.Commerce/
|
||||
zero.Commerce/
|
||||
Hofbauer.To.Zero/
|
||||
@@ -40,7 +40,7 @@ namespace zero.Core.Api
|
||||
|
||||
public class TranslationsApi<T> : AppAwareBackofficeApi, ITranslationsApi<T> where T : ITranslation
|
||||
{
|
||||
IValidator<T> Validator;
|
||||
//IValidator<T> Validator;
|
||||
|
||||
|
||||
public TranslationsApi(IBackofficeStore store) : base(store)
|
||||
@@ -91,7 +91,7 @@ namespace zero.Core.Api
|
||||
/// <inheritdoc />
|
||||
public async Task<EntityResult<T>> Save(T model)
|
||||
{
|
||||
return await SaveModel(model, Validator);
|
||||
return await SaveModel(model, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace zero.Core.Entities
|
||||
{
|
||||
public enum Gender
|
||||
{
|
||||
Undisclosed = 0,
|
||||
Male = 1,
|
||||
Female = 2,
|
||||
NonBinary = 3
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace zero.Core.Entities
|
||||
{
|
||||
@@ -29,6 +30,14 @@ namespace zero.Core.Entities
|
||||
Items = items;
|
||||
}
|
||||
|
||||
public ListResult<TTarget> MapTo<TTarget>(Func<T, TTarget> convertItem)
|
||||
{
|
||||
return new ListResult<TTarget>(Items.Select(x => convertItem(x)).ToList(), TotalItems, Page, PageSize)
|
||||
{
|
||||
Statistics = Statistics
|
||||
};
|
||||
}
|
||||
|
||||
public long Page { get; private set; }
|
||||
|
||||
public long PageSize { get; private set; }
|
||||
|
||||
@@ -12,9 +12,11 @@ namespace zero.Core.Extensions
|
||||
{
|
||||
public static class RavenQueryableExtensions
|
||||
{
|
||||
public static IRavenQueryable<T> Scope<T>(this IRavenQueryable<T> source, string appId, bool includeShared = true) where T : IZeroIdEntity
|
||||
static Type _appAwareEntity = typeof(IAppAwareEntity);
|
||||
|
||||
public static IRavenQueryable<T> Scope<T>(this IRavenQueryable<T> source, string appId, bool includeShared = true)
|
||||
{
|
||||
if (appId.IsNullOrEmpty() || source.ElementType.Is<IAppAwareEntity>())
|
||||
if (appId.IsNullOrEmpty() || !_appAwareEntity.IsAssignableFrom(source.ElementType))
|
||||
{
|
||||
return source;
|
||||
}
|
||||
@@ -31,14 +33,14 @@ namespace zero.Core.Extensions
|
||||
}
|
||||
|
||||
|
||||
public static IRavenQueryable<T> Scope<T>(this IRavenQueryable<T> source, ApiScope scope) where T : IZeroIdEntity
|
||||
public static IRavenQueryable<T> Scope<T>(this IRavenQueryable<T> source, ApiScope scope)
|
||||
{
|
||||
if (scope == null || scope.Global)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
if (scope.AppId.IsNullOrEmpty() || source.ElementType.Is<IAppAwareEntity>())
|
||||
if (scope.AppId.IsNullOrEmpty() || !_appAwareEntity.IsAssignableFrom(source.ElementType))
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
using Lambda2Js;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using zero.Core.Extensions;
|
||||
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public abstract class AbstractRenderer2<T>
|
||||
{
|
||||
const string METHOD_FIELD = "field";
|
||||
|
||||
const string METHOD_TAB = "tab";
|
||||
|
||||
const string METHOD_BOX = "box";
|
||||
|
||||
protected List<RenderProperty> Properties { get; set; } = new List<RenderProperty>();
|
||||
|
||||
RenderProperty ParentProperty = null;
|
||||
|
||||
int CurrentDepth = 0;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a field
|
||||
/// </summary>
|
||||
protected virtual IRendererFieldBuilder Field(Expression<Func<T, object>> mapExpression, bool required = false)
|
||||
{
|
||||
RendererFieldBuilder builder = new RendererFieldBuilder();
|
||||
|
||||
Add(new RenderProperty()
|
||||
{
|
||||
Method = METHOD_FIELD,
|
||||
Compile = property =>
|
||||
{
|
||||
string field = mapExpression.CompileToJavascript().ToCamelCaseId();
|
||||
|
||||
RendererFieldBuilder.Data fieldData = builder.Build();
|
||||
|
||||
property.NestedRenderer = fieldData.Renderer;
|
||||
property.Params = new
|
||||
{
|
||||
Field = field,
|
||||
View = fieldData.View,
|
||||
ComponentPath = fieldData.ComponentPath,
|
||||
Options = fieldData.Options ?? new List<string>() { },
|
||||
//Label = FindLabelName?.Invoke(field),
|
||||
//Description = FindLabelDescriptionName?.Invoke(field),
|
||||
Required = required
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a tab
|
||||
/// </summary>
|
||||
protected virtual void Tab(string name, Action contentBuilder)
|
||||
{
|
||||
Add(new RenderProperty()
|
||||
{
|
||||
Method = METHOD_TAB,
|
||||
Builder = contentBuilder,
|
||||
Params = new
|
||||
{
|
||||
Name = name
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a visual box
|
||||
/// </summary>
|
||||
protected virtual void Box(string name, string description, Action contentBuilder)
|
||||
{
|
||||
Add(new RenderProperty()
|
||||
{
|
||||
Method = METHOD_BOX,
|
||||
Builder = contentBuilder,
|
||||
Params = new
|
||||
{
|
||||
Name = name,
|
||||
Description = description
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a property to the list
|
||||
/// </summary>
|
||||
void Add(RenderProperty property)
|
||||
{
|
||||
if (property.Method == METHOD_TAB && CurrentDepth > 0)
|
||||
{
|
||||
throw new Exception("Tabs have to be defined on the root level of the renderer");
|
||||
}
|
||||
if (property.Method == METHOD_BOX && (CurrentDepth > 1 || (CurrentDepth == 1 && ParentProperty?.Method != METHOD_TAB)))
|
||||
{
|
||||
throw new Exception("Boxes have to be defined on the root level of the renderer or as direct descendents of a tab");
|
||||
}
|
||||
|
||||
if (CurrentDepth == 0)
|
||||
{
|
||||
Properties.Add(property);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentProperty.Children.Add(property);
|
||||
}
|
||||
|
||||
if (property.Builder != null)
|
||||
{
|
||||
CurrentDepth += 1;
|
||||
|
||||
RenderProperty previousParent = ParentProperty;
|
||||
|
||||
ParentProperty = property;
|
||||
|
||||
property.Builder();
|
||||
|
||||
CurrentDepth -= 1;
|
||||
ParentProperty = previousParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public abstract class AbstractFieldInputOptions
|
||||
{
|
||||
public bool HideLabel { get; set; }
|
||||
|
||||
public List<string> Classes { get; set; } = new List<string>();
|
||||
|
||||
public string HelpText { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace zero.Core.Renderer
|
||||
namespace zero.Core.Renderer.Options
|
||||
{
|
||||
public abstract class AbstractFieldOptions
|
||||
public class AbstractFieldOptions
|
||||
{
|
||||
public bool HideLabel { get; set; }
|
||||
|
||||
public List<string> Classes { get; set; } = new List<string>();
|
||||
|
||||
public string HelpText { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public class DefaultRendererOptions : AbstractFieldOptions
|
||||
public class DefaultRendererOptions : AbstractFieldInputOptions
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public class MediaOptions : AbstractFieldOptions
|
||||
public class MediaOptions : AbstractFieldInputOptions
|
||||
{
|
||||
public uint Limit { get; set; } = 1;
|
||||
|
||||
@@ -20,4 +18,22 @@ namespace zero.Core.Renderer
|
||||
|
||||
public bool DisallowUpload { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public enum MediaOptionsDisplay
|
||||
{
|
||||
Default = 0,
|
||||
Big = 1,
|
||||
Grid = 2
|
||||
}
|
||||
|
||||
|
||||
public enum MediaOptionsType
|
||||
{
|
||||
All = 0,
|
||||
Image = 1,
|
||||
Video = 2,
|
||||
Document = 3,
|
||||
Other = 99
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public enum MediaOptionsDisplay
|
||||
{
|
||||
Default = 0,
|
||||
Big = 1,
|
||||
Grid = 2
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public enum MediaOptionsType
|
||||
{
|
||||
All = 0,
|
||||
Image = 1,
|
||||
Video = 2,
|
||||
Document = 3,
|
||||
Other = 99
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Text;
|
||||
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public class NestedOptions : AbstractFieldOptions
|
||||
public class NestedOptions : AbstractFieldInputOptions
|
||||
{
|
||||
public int Limit { get; set; } = 10;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public class NumberOptions : AbstractFieldOptions
|
||||
public class NumberOptions : AbstractFieldInputOptions
|
||||
{
|
||||
public int MaxLength { get; set; }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public class StateOptions : AbstractFieldOptions
|
||||
public class StateOptions : AbstractFieldInputOptions
|
||||
{
|
||||
public class Item
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace zero.Core.Renderer
|
||||
{
|
||||
public class TextOptions : AbstractFieldOptions
|
||||
public class TextOptions : AbstractFieldInputOptions
|
||||
{
|
||||
public int MaxLength { get; set; }
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
|
||||
&:before
|
||||
{
|
||||
background: var(--color-line);
|
||||
background: var(--color-primary);
|
||||
}
|
||||
|
||||
&:after
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import Vue from 'vue';
|
||||
import Strings from 'zero/services/strings';
|
||||
|
||||
/// <summary>
|
||||
/// Outputs a currency
|
||||
/// </summary>
|
||||
Vue.directive('currency', (el, binding) =>
|
||||
{
|
||||
if (binding.value !== binding.oldValue)
|
||||
{
|
||||
el.innerHTML = Strings.currency(binding.value);
|
||||
}
|
||||
});
|
||||
@@ -10,7 +10,7 @@ Vue.directive('date', (el, binding) =>
|
||||
{
|
||||
if (!binding.value)
|
||||
{
|
||||
el.innerHTML = '';
|
||||
el.innerHTML = '-';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
import './date';
|
||||
import './localize';
|
||||
import './resizable';
|
||||
import './dropdown';
|
||||
import './clickoutside';
|
||||
import './filesize';
|
||||
import './filesize';
|
||||
import './currency';
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="app-nav theme-dark">
|
||||
<div class="app-nav theme-light">
|
||||
|
||||
<h1 class="app-nav-headline" v-localize="'@zero.name'">zero</h1>
|
||||
|
||||
|
||||
@@ -69,5 +69,21 @@ export default {
|
||||
selector = selector.replace(/\[(\w+)\]/g, '.$1');
|
||||
selector = selector.replace(/^\./, '');
|
||||
return selector.split('.');
|
||||
},
|
||||
|
||||
|
||||
currency(value, decimals, hideSymbol, noEncode)
|
||||
{
|
||||
if (isNaN(value))
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
|
||||
var fixedDecimals = typeof decimals !== 'undefined';
|
||||
decimals = !fixedDecimals ? 2 : decimals;
|
||||
var hasDecimals = ~~value !== value;
|
||||
var val = (hasDecimals || fixedDecimals) ? (value / 1).toFixed(decimals) : ~~value;
|
||||
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, noEncode ? " " : " ") + (hideSymbol === true ? "" : (noEncode ? " €" : " €"));
|
||||
// TODO we have dynamic currencies, not fixed to €
|
||||
}
|
||||
};
|
||||
@@ -2,7 +2,7 @@
|
||||
:root, .theme-light
|
||||
{
|
||||
// accent colors
|
||||
--color-primary: #00aea2; // #86bcaf
|
||||
--color-primary: #292b2c; // #292b2c; // #00aea2
|
||||
--color-primary-fg: #fff;
|
||||
--color-secondary: #1f3053;
|
||||
--color-negative: #d82853;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using zero.Core.Entities;
|
||||
using System.Threading.Tasks;
|
||||
using zero.Core.Entities;
|
||||
using zero.Core.Mapper;
|
||||
using zero.Web.Models;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using FluentValidation;
|
||||
using zero.Core.Entities;
|
||||
using zero.Core.Entities;
|
||||
using zero.Core.Renderer;
|
||||
|
||||
namespace zero.Web.Renderers
|
||||
@@ -39,13 +38,4 @@ namespace zero.Web.Renderers
|
||||
//RuleFor(x => x.Name).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//public class ApplicationValidator : AbstractValidator<Application>
|
||||
//{
|
||||
// public ApplicationValidator()
|
||||
// {
|
||||
// RuleFor(x => x.Name).NotNull()
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
"active": "Published",
|
||||
"inactive": "Unpublished",
|
||||
"delete": "Delete",
|
||||
"default": "Default",
|
||||
"remove": "Remove",
|
||||
"pagination": {
|
||||
"xofy": "Page {x} of {y}",
|
||||
|
||||
@@ -7,6 +7,7 @@ using Microsoft.Extensions.Options;
|
||||
using Raven.Client.Documents;
|
||||
using Raven.Client.Documents.Indexes;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using zero.Core;
|
||||
@@ -129,7 +130,13 @@ namespace zero.Web
|
||||
IDocumentStore raven = store.Setup(options).Initialize();
|
||||
|
||||
// create all indexes
|
||||
IndexCreation.CreateIndexes(Assembly.GetAssembly(typeof(MediaFolder_ByHierarchy)), store);
|
||||
var assemblies = AssemblyDiscovery.Current.GetAssemblies().ToList();
|
||||
|
||||
// TODO maybe we shouldn't use all auto-registered assemblies but specify them directly via options?
|
||||
foreach (Assembly assembly in assemblies)
|
||||
{
|
||||
IndexCreation.CreateIndexes(assembly, store);
|
||||
}
|
||||
|
||||
return raven;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user