Add object enumerable table generator
This commit is contained in:
parent
03910cd724
commit
bcdd6bb660
|
@ -1,4 +1,8 @@
|
|||
using System.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
|
||||
|
@ -14,4 +18,31 @@ public static class Extensions
|
|||
return writer.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetCSharpName(this Type type)
|
||||
{
|
||||
string name = type.Name;
|
||||
|
||||
if (!type.IsGenericType)
|
||||
return name;
|
||||
|
||||
StringBuilder sb = new();
|
||||
|
||||
// Get just the name without the generic parameters
|
||||
sb.Append(name[..name.IndexOf('`')]);
|
||||
|
||||
// Add the generic parameters surrounded by < and >
|
||||
sb.Append('<');
|
||||
sb.Append(type.GetGenericArguments()
|
||||
.Select(t => t.GetCSharpName())
|
||||
.Join(", "));
|
||||
sb.Append('>');
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string Join(this IEnumerable<string> strings, string separator)
|
||||
{
|
||||
return string.Join(separator, strings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Cauldron.Core;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Collections;
|
||||
|
||||
namespace Cauldron.Macos;
|
||||
|
||||
|
@ -22,7 +26,11 @@ public static class ScriptRunner
|
|||
{
|
||||
window.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
body.InnerHtml.AppendHtml(GenerateValueOutput(obj));
|
||||
TagBuilder outputSection = new("section");
|
||||
outputSection.AddCssClass("output-section");
|
||||
outputSection.InnerHtml.AppendHtml(GenerateValueOutput(obj));
|
||||
body.InnerHtml.AppendHtml(outputSection);
|
||||
|
||||
window.ScriptOutputWebView.SetOutputPanelContent(body);
|
||||
});
|
||||
|
||||
|
@ -54,34 +62,36 @@ public static class ScriptRunner
|
|||
});
|
||||
}
|
||||
}, window.ScriptCancellationTokenSource.Token)
|
||||
.ContinueWith((t) => window.SetScriptRunState(false),
|
||||
uiThread);
|
||||
.ContinueWith((t) => window.SetScriptRunState(false), uiThread);
|
||||
}
|
||||
|
||||
private static TagBuilder GenerateValueOutput(object value)
|
||||
{
|
||||
if (value is string str)
|
||||
if (value is null)
|
||||
{
|
||||
TagBuilder tag = new("p");
|
||||
tag.InnerHtml.Append(str);
|
||||
TagBuilder code = new("code");
|
||||
code.InnerHtml.Append("null");
|
||||
tag.InnerHtml.AppendHtml(code);
|
||||
return tag;
|
||||
}
|
||||
if (value.GetType().IsPrimitive)
|
||||
if (value.GetType().IsPrimitive || value is string)
|
||||
{
|
||||
TagBuilder tag = new("p");
|
||||
tag.InnerHtml.Append(value.ToString());
|
||||
return tag;
|
||||
}
|
||||
if (value is IEnumerable<object> enumberable)
|
||||
if (value is IEnumerable<object> enumerable)
|
||||
{
|
||||
|
||||
return GenerateTable(enumerable);
|
||||
}
|
||||
|
||||
return null;
|
||||
TagBuilder defaultTag = new("p");
|
||||
defaultTag.InnerHtml.Append(value.ToString());
|
||||
return defaultTag;
|
||||
}
|
||||
|
||||
private static void SetOutputPanelContent(this WebKit.WKWebView webView,
|
||||
TagBuilder body)
|
||||
private static void SetOutputPanelContent(this WebKit.WKWebView webView, TagBuilder body)
|
||||
{
|
||||
TagBuilder head = new("head");
|
||||
TagBuilder style = new("style");
|
||||
|
@ -97,9 +107,117 @@ public static class ScriptRunner
|
|||
webView.LoadHtmlString(new Foundation.NSString(contents), null);
|
||||
}
|
||||
|
||||
private static TagBuilder GenerateTable(IEnumerable<object> enumerable)
|
||||
{
|
||||
var listType = enumerable.GetType().GenericTypeArguments[0];
|
||||
|
||||
if (enumerable.GetType().GenericTypeArguments[0].IsPrimitive
|
||||
|| enumerable.GetType().GenericTypeArguments[0] == typeof(string))
|
||||
return GenerateSimpleTable(enumerable);
|
||||
|
||||
TagBuilder output = new("table");
|
||||
|
||||
IList<PropertyInfo> properties = enumerable.GetType()
|
||||
.GenericTypeArguments[0].GetProperties()
|
||||
.Where(p => !p.GetCustomAttributes<DisplayAttribute>(false)
|
||||
.Any(a => a.GetAutoGenerateField() == false))
|
||||
.ToList();
|
||||
|
||||
// Caption
|
||||
TagBuilder caption = new("caption");
|
||||
caption.InnerHtml.Append(enumerable.GetType().GetCSharpName());
|
||||
output.InnerHtml.AppendHtml(caption);
|
||||
|
||||
// Header Row
|
||||
List<TagBuilder> tableHeadCells = properties
|
||||
.Select(p =>
|
||||
{
|
||||
string displayName = p.GetCustomAttributes<DisplayAttribute>(false)
|
||||
.Where(a => !string.IsNullOrEmpty(a.GetName()))
|
||||
.FirstOrDefault()
|
||||
?.GetName()
|
||||
?? p.Name;
|
||||
|
||||
TagBuilder th = new("th");
|
||||
th.InnerHtml.Append(displayName);
|
||||
|
||||
return th;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
TagBuilder theadTr = new("tr");
|
||||
tableHeadCells.ForEach(th => theadTr.InnerHtml.AppendHtml(th));
|
||||
|
||||
TagBuilder thead = new("thead");
|
||||
thead.InnerHtml.AppendHtml(theadTr);
|
||||
output.InnerHtml.AppendHtml(thead);
|
||||
|
||||
// Content Rows
|
||||
List<TagBuilder> tableRows = enumerable
|
||||
.Select(item =>
|
||||
{
|
||||
List<TagBuilder> cells = properties
|
||||
.Select(p =>
|
||||
{
|
||||
var content = p.GetValue(item);
|
||||
|
||||
TagBuilder td = new("td");
|
||||
td.InnerHtml.AppendHtml(GenerateValueOutput(content));
|
||||
return td;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
TagBuilder tr = new("tr");
|
||||
cells.ForEach(td => tr.InnerHtml.AppendHtml(td));
|
||||
return tr;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
TagBuilder tbody = new("tbody");
|
||||
tableRows.ForEach(tr => tbody.InnerHtml.AppendHtml(tr));
|
||||
output.InnerHtml.AppendHtml(tbody);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static TagBuilder GenerateSimpleTable(IEnumerable<object> enumerable)
|
||||
{
|
||||
TagBuilder output = new("table");
|
||||
|
||||
// Caption
|
||||
TagBuilder caption = new("caption");
|
||||
caption.InnerHtml.Append(enumerable.GetType().GetCSharpName());
|
||||
output.InnerHtml.AppendHtml(caption);
|
||||
|
||||
// Content Rows
|
||||
List<TagBuilder> tableRows = enumerable
|
||||
.Select(item =>
|
||||
{
|
||||
List<TagBuilder> cells = enumerable
|
||||
.Select(v =>
|
||||
{
|
||||
TagBuilder td = new("td");
|
||||
td.InnerHtml.AppendHtml(v.ToString());
|
||||
return td;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
TagBuilder tr = new("tr");
|
||||
cells.ForEach(td => tr.InnerHtml.AppendHtml(td));
|
||||
return tr;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
TagBuilder tbody = new("tbody");
|
||||
tableRows.ForEach(tr => tbody.InnerHtml.AppendHtml(tr));
|
||||
output.InnerHtml.AppendHtml(tbody);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private const string outputCss = """
|
||||
body {
|
||||
font-family: -apple-system;
|
||||
font-family: system-ui;
|
||||
}
|
||||
|
||||
* {
|
||||
|
|
Loading…
Reference in a new issue