remove legacy renderer

This commit is contained in:
2020-07-06 13:13:19 +02:00
parent bcc22eb58c
commit b8c8cecde6
26 changed files with 1 additions and 1018 deletions
-231
View File
@@ -1,231 +0,0 @@
using FluentValidation;
using Lambda2Js;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using zero.Core.Extensions;
namespace zero.Core.Renderer
{
public class AbstractGenericRenderer : AbstractRenderer<object>
{
public Type TargetType { get; set; }
public AbstractGenericRenderer() { }
internal AbstractGenericRenderer(Type type, string alias, List<RenderProperty> properties)
{
Alias = alias;
TargetType = type;
Properties = properties;
}
}
public abstract class AbstractRenderer<T> : IRenderer<T>, IRenderer
{
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;
public string Alias { get; protected set; }
protected string LabelTemplate = "{0}";
protected string DescriptionTemplate = "{0}";
protected Func<string, string> FindLabelName = field => "@" + field;
protected Func<string, string> FindLabelDescriptionName = field => null;
public RendererConfig Build()
{
RendererConfig config = new RendererConfig();
config.Type = typeof(T);
// compile fields
static void compile(List<RenderProperty> properties)
{
foreach (RenderProperty property in properties)
{
property.Compile?.Invoke(property);
if (property.Children.Count > 0)
{
compile(property.Children);
}
}
}
compile(Properties);
// move top-level properties into tab in case other tabs exist
int countTabs = Properties.Count(x => x.Method == METHOD_TAB);
if (countTabs > 0 && countTabs < Properties.Count)
{
int index = Properties.FindIndex(x => x.Method != METHOD_TAB);
List<RenderProperty> children = Properties.Where(x => x.Method != METHOD_TAB).ToList();
Properties.Insert(index, new RenderProperty()
{
Method = METHOD_TAB,
Children = children,
Params = new
{
Name = "@ui.tab_general"
}
});
Properties = Properties.Where(x => x.Method == METHOD_TAB).ToList();
}
// map to result
static RendererComponent Map(RenderProperty property)
{
RendererComponent component = new RendererComponent()
{
Method = property.Method,
Params = property.Params
};
if (property.Children.Count > 0)
{
component.Components = property.Children.Select(x => Map(x)).ToList();
}
else if (property.NestedRenderer != null)
{
component.Components = property.NestedRenderer.Build().Components;
}
return component;
}
config.Components = Properties.Select(x => Map(x)).ToList();
return config;
}
public AbstractGenericRenderer ToGenericRenderer()
{
return new AbstractGenericRenderer(typeof(T), Alias, Properties);
}
protected virtual IRendererFieldBuilder Field(Expression<Func<T, object>> mapExpression, bool required = false, string label = null, string description = null)
{
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 = label != null ? label : FindLabelName?.Invoke(field),
Description = description != null ? description : FindLabelDescriptionName?.Invoke(field),
Required = required
};
}
});
return builder;
}
protected virtual IRendererFieldBuilder Field(Expression<Func<T, object>> mapExpression, string label, string description = null, bool required = false, bool noDescription = false)
{
return Field(mapExpression, required, label, description);
}
protected virtual void Tab(string name, Action builder)
{
builder(); // TODO re-enable tabs
return;
Add(new RenderProperty()
{
Method = METHOD_TAB,
Builder = builder,
Params = new
{
Name = name
}
});
}
protected virtual void Box(string name, string description, Action builder)
{
Add(new RenderProperty()
{
Method = METHOD_BOX,
Builder = builder,
Params = new
{
Name = name,
Description = description
}
});
}
private 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;
}
}
}
}
-132
View File
@@ -1,132 +0,0 @@
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;
}
}
}
}
-14
View File
@@ -1,14 +0,0 @@
namespace zero.Core.Renderer
{
public interface IRenderer<T> : IRenderer { }
public interface IRenderer
{
string Alias { get; }
RendererConfig Build();
AbstractGenericRenderer ToGenericRenderer();
}
}
@@ -1,33 +0,0 @@
using System;
namespace zero.Core.Renderer
{
public interface IRendererFieldBuilder
{
void Text(Action<TextOptions> optionsBuilder = null);
void TextList(Action<TextListOptions> optionsBuilder = null);
void Number(Action<NumberOptions> optionsBuilder = null);
void Textarea(Action<TextOptions> optionsBuilder = null);
void Rte();
void IconPicker();
void Toggle();
void State(Action<StateOptions> optionsBuilder = null);
void Media(Action<MediaOptions> optionsBuilder = null);
void Output();
void Nested<T>(IRenderer<T> renderer, Action<NestedOptions> optionsBuilder = null);
void Renderer<T>(IRenderer<T> renderer, Action<DefaultRendererOptions> optionsBuilder = null);
void Custom(string path, Func<object> optionsBuilder = null);
}
}
-9
View File
@@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace zero.Core.Renderer
{
public interface IRendererOptions
{
string ComponentPath { get; set; }
}
}
@@ -1,13 +0,0 @@
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,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace zero.Core.Renderer.Options
{
public class AbstractFieldOptions
{
}
}
@@ -1,7 +0,0 @@
namespace zero.Core.Renderer
{
public class DefaultRendererOptions : AbstractFieldInputOptions
{
}
}
@@ -1,39 +0,0 @@
using System.Collections.Generic;
namespace zero.Core.Renderer
{
public class MediaOptions : AbstractFieldInputOptions
{
public uint Limit { get; set; } = 1;
public decimal MaxFileSize { get; set; } = 10;
public MediaOptionsType Type { get; set; }
public MediaOptionsDisplay Display { get; set; }
public List<string> FileExtensions { get; set; } = new List<string>();
public bool DisallowSelect { get; set; }
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,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace zero.Core.Renderer
{
public class NestedOptions : AbstractFieldInputOptions
{
public int Limit { get; set; } = 10;
public string AddLabel { get; set; } = "@ui.add";
}
}
@@ -1,9 +0,0 @@
namespace zero.Core.Renderer
{
public class NumberOptions : AbstractFieldInputOptions
{
public int MaxLength { get; set; }
public string Placeholder { get; set; }
}
}
@@ -1,25 +0,0 @@
using System.Collections.Generic;
namespace zero.Core.Renderer
{
public class StateOptions : AbstractFieldInputOptions
{
public class Item
{
public string Label { get; set; }
public object Value { get; set; }
}
public List<Item> Items { get; set; } = new List<Item>();
public void Add(string label, object value)
{
Items.Add(new Item()
{
Label = label,
Value = value
});
}
}
}
@@ -1,9 +0,0 @@
namespace zero.Core.Renderer
{
public class TextListOptions : TextOptions
{
public int Limit { get; set; } = 10;
public string AddLabel { get; set; } = "@ui.add";
}
}
@@ -1,9 +0,0 @@
namespace zero.Core.Renderer
{
public class TextOptions : AbstractFieldInputOptions
{
public int MaxLength { get; set; }
public string Placeholder { get; set; }
}
}
-21
View File
@@ -1,21 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace zero.Core.Renderer
{
public class RenderProperty
{
public string Method { get; set; }
public dynamic Params { get; set; }
public Action Builder { get; set; }
public Action<RenderProperty> Compile { get; set; }
public AbstractGenericRenderer NestedRenderer { get; set; }
public List<RenderProperty> Children { get; set; } = new List<RenderProperty>();
}
}
-21
View File
@@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using zero.Core.Renderer;
namespace zero.Core.Entities
{
public class RendererCollection : List<AbstractGenericRenderer>
{
public void Add<T, TRenderer>() where TRenderer : IRenderer<T>, new()
{
Add(new TRenderer().ToGenericRenderer());
}
public void Add<T, TRenderer>(TRenderer renderer) where TRenderer : IRenderer<T>, new()
{
Add(renderer.ToGenericRenderer());
}
}
}
-25
View File
@@ -1,25 +0,0 @@
using FluentValidation;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace zero.Core.Renderer
{
public class RendererConfig
{
public Type Type { get; set; }
public List<RendererComponent> Components { get; set; } = new List<RendererComponent>();
}
public class RendererComponent
{
public string Method { get; set; }
public dynamic Params { get; set; }
public List<RendererComponent> Components { get; set; } = new List<RendererComponent>();
}
}
-123
View File
@@ -1,123 +0,0 @@
using System;
namespace zero.Core.Renderer
{
public class RendererFieldBuilder : IRendererFieldBuilder
{
string View = null;
string ComponentPath = null;
object Options = null;
AbstractGenericRenderer CustomRenderer = null;
internal class Data
{
public string View = null;
public string ComponentPath = null;
public object Options = null;
public AbstractGenericRenderer Renderer = null;
}
internal Data Build()
{
return new Data()
{
View = View,
ComponentPath = ComponentPath,
Options = Options,
Renderer = CustomRenderer
};
}
T BuildOptions<T>(Action<T> builder) where T : new()
{
T options = new T();
builder?.Invoke(options);
return options;
}
public void Custom(string path, Func<object> optionsBuilder = null)
{
View = "custom";
ComponentPath = path;
Options = optionsBuilder?.Invoke();
}
public void IconPicker()
{
View = "iconPicker";
}
public void Media(Action<MediaOptions> optionsBuilder = null)
{
View = "media";
Options = BuildOptions(optionsBuilder);
}
public void Nested<T>(IRenderer<T> renderer, Action<NestedOptions> optionsBuilder = null)
{
View = "nested";
CustomRenderer = renderer.ToGenericRenderer();
Options = BuildOptions(optionsBuilder);
}
public void Output()
{
View = "output";
}
public void Rte()
{
View = "rte";
}
public void Renderer<T>(IRenderer<T> renderer, Action<DefaultRendererOptions> optionsBuilder = null)
{
View = "renderer";
CustomRenderer = renderer.ToGenericRenderer();
Options = BuildOptions(optionsBuilder);
}
public void State(Action<StateOptions> optionsBuilder = null)
{
View = "state";
Options = BuildOptions(optionsBuilder);
}
public void Text(Action<TextOptions> optionsBuilder = null)
{
View = "text";
Options = BuildOptions(optionsBuilder);
}
public void TextList(Action<TextListOptions> optionsBuilder = null)
{
View = "textlist";
Options = BuildOptions(optionsBuilder);
}
public void Number(Action<NumberOptions> optionsBuilder = null)
{
View = "number";
Options = BuildOptions(optionsBuilder);
}
public void Textarea(Action<TextOptions> optionsBuilder = null)
{
View = "textarea";
Options = BuildOptions(optionsBuilder);
}
public void Toggle()
{
View = "toggle";
}
}
}
-37
View File
@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace zero.Core.Renderer
{
public class RendererFinder
{
static RendererFinder()
{
}
public static IRenderer<T> FindBy<T>()
{
return null;
}
public static AbstractGenericRenderer FindBy(Type type)
{
//Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
//List<Type> types = assemblies
// .Where(assembly => !assembly.IsDynamic)
// .SelectMany(assembly => assembly.GetExportedTypes())
// .ToList();
List<Type> types = Assembly.GetExecutingAssembly().GetExportedTypes().ToList();
return null;
}
}
}
-130
View File
@@ -1,130 +0,0 @@
<template>
<component v-if="loaded" :is="rootNode" class="editor">
<ui-tab v-if="hasTabs" :class="renderInfo && index === 0 ? 'ui-view-box has-sidebar' : 'ui-box'" :label="component.params.name" v-for="(component, index) in components" :key="index">
<div v-if="renderInfo && index === 0" class="ui-box">
<editor-component v-for="(child, index) in component.components" :key="index" :field="child.params.field" v-model="value" :component="child" />
</div>
<aside v-if="renderInfo && index === 0" class="ui-view-box-aside">
<ui-property label="@ui.active" :vertical="true" :is-text="true">
<ui-toggle v-model="value.isActive" />
</ui-property>
<ui-property label="@ui.id" :vertical="true" :is-text="true">
{{value.id}}
</ui-property>
<ui-property label="@ui.createdDate" :vertical="true" :is-text="true">
<ui-date v-model="value.createdDate" />
</ui-property>
</aside>
<editor-component v-if="!renderInfo || index > 0" v-for="(child, cindex) in component.components" :key="cindex" :field="child.params.field" v-model="value" :component="child" />
</ui-tab>
<div v-if="!hasTabs" :class="renderInfo ? 'ui-view-box has-sidebar' : 'ui-box'">
<div v-if="renderInfo" class="ui-box">
<editor-component v-for="(component, index) in components" :key="index" :field="component.params.field" v-model="value" :component="component" />
</div>
<aside v-if="renderInfo" class="ui-view-box-aside">
<ui-property label="@ui.active" :vertical="true" :is-text="true">
<ui-toggle v-model="value.isActive" />
</ui-property>
<ui-property label="@ui.id" :vertical="true" :is-text="true">
{{value.id}}
</ui-property>
<ui-property label="@ui.createdDate" :vertical="true" :is-text="true">
<ui-date v-model="value.createdDate" />
</ui-property>
</aside>
<editor-component v-if="!renderInfo" v-for="(component, index) in components" :key="index" :field="component.params.field" v-model="value" :component="component" />
</div>
</component>
</template>
<script>
import EditorComponent from 'zero/editor/editor-component';
import RendererApi from 'zero/resources/renderer';
export default {
name: 'uiEditorOld',
props: {
config: {
type: [ String, Object ],
required: true
},
value: {
type: Object
}
},
components: { EditorComponent },
data: () => ({
loaded: false,
hasTabs: false,
components: [],
renderInfo: true
}),
computed: {
rootNode()
{
return this.hasTabs ? 'ui-tabs' : 'div';
}
},
watch: {
config: {
deep: true,
handler: function()
{
this.load();
}
}
},
created()
{
this.load();
},
methods: {
load()
{
if (typeof this.config === 'string')
{
RendererApi.getByAlias(this.config).then(response =>
{
this.finishLoad(response);
});
}
else
{
this.finishLoad(this.config);
}
},
finishLoad(config)
{
if (!config.components)
{
return;
}
this.components = config.components;
this.hasTabs = this.components.length > 0 && this.components[0].method === 'tab';
this.loaded = true;
}
}
}
</script>
<style lang="scss">
.editor > .ui-view-box
{
padding-top: 0;
}
</style>
-1
View File
@@ -36,7 +36,6 @@
<script>
import EditorComponent from 'zero/editor/editor-component';
import RendererApi from 'zero/resources/renderer';
import { each as _each, map as _map, filter as _filter } from 'underscore';
export default {
-10
View File
@@ -1,10 +0,0 @@
import Axios from 'axios';
export default {
// get renderer by alias
getByAlias(alias)
{
return Axios.get('renderer/getByAlias', { params: { alias } }).then(res => Promise.resolve(res.data));
}
};
+1 -8
View File
@@ -10,7 +10,6 @@ using zero.Core.Entities;
using zero.Core.Identity;
using zero.Core.Mapper;
using zero.Core.Options;
using zero.Core.Renderer;
using zero.Web.Filters;
using zero.Web.Models;
@@ -57,13 +56,7 @@ namespace zero.Web.Controllers
/// <summary>
/// Creates an edit model with appropriate options and permissions
/// </summary>
public JsonResult Edit<T>(T data, bool typed = true, Action<dynamic> transform = null) where T : IZeroEntity => Edit(data, null, typed, transform);
/// <summary>
/// Creates an edit model with appropriate options and permissions
/// </summary>
public JsonResult Edit<T>(T data, IRenderer<T> renderer, bool typed = true, Action<dynamic> transform = null) where T : IZeroEntity
public JsonResult Edit<T>(T data, bool typed = true, Action<dynamic> transform = null) where T : IZeroEntity
{
Type type = typeof(T);
bool canBeShared = AppAwareShareableType.IsAssignableFrom(type);
@@ -1,24 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using zero.Core.Identity;
using zero.Core.Renderer;
namespace zero.Web.Controllers
{
[ZeroAuthorize]
public class RendererController : BackofficeController
{
/// <summary>
/// Get a renderer by alias
/// </summary>
public IActionResult GetByAlias([FromServices] IEnumerable<IRenderer> renderers, [FromQuery] string alias)
{
IRenderer renderer = renderers.FirstOrDefault(x => x.Alias == alias);
RendererConfig config = renderer?.Build();
return Json(config, false);
}
}
}
-41
View File
@@ -1,41 +0,0 @@
using zero.Core.Entities;
using zero.Core.Renderer;
namespace zero.Web.Renderers
{
public class ApplicationRenderer : AbstractRenderer<Application>
{
const string PREFIX = "@application.fields.";
public ApplicationRenderer()
{
Alias = "application";
FindLabelName = field => PREFIX + field;
FindLabelDescriptionName = field => PREFIX + field + "_text";
Field(x => x.Name, true).Text();
Field(x => x.FullName).Text();
Field(x => x.Email, true).Text();
Field(x => x.ImageId).Media(opts => opts.Type = MediaOptionsType.Image);
Field(x => x.IconId).Media(opts => opts.Type = MediaOptionsType.Image);
Tab("@application.tab_domains", () =>
{
Field(x => x.Domains).TextList(opts =>
{
opts.Limit = 10;
opts.AddLabel = PREFIX + "domains_add";
opts.HelpText = PREFIX + "domains_help";
});
});
Tab("@application.tab_features", () =>
{
});
//RuleFor(x => x.Name).NotEmpty();
}
}
}
-23
View File
@@ -1,23 +0,0 @@
using System;
using zero.Core.Entities;
using zero.Core.Renderer;
namespace zero.Web.Renderers
{
public class LanguageRenderer : AbstractRenderer<Language>
{
const string PREFIX = "@language.fields.";
public LanguageRenderer()
{
FindLabelName = field => PREFIX + field;
FindLabelDescriptionName = field => PREFIX + field + "_text";
Field(x => x.Name, description: String.Empty).Text();
Field(x => x.Code).Text();
Field(x => x.IsDefault).Toggle();
//RuleFor(x => x.Name).NotEmpty();
}
}
}