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