Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revamp Web UI #173

Open
wants to merge 1 commit into
base: release-3.0.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 22 additions & 26 deletions samples/Rules.Framework.WebUI.Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,22 @@ public static void Main(string[] args)
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddControllersWithViews()
.AddRulesFrameworkWebUI(registrar =>
{
registrar.AddInstance("Readme example", (_, _) => new BasicRulesEngineExample().RulesEngine)
.AddInstance("Random rules example", async (_, _) =>
{
var rulesProvider = new RulesEngineProvider(new RulesBuilder(new List<IRuleSpecificationsProvider>()
{
new RulesRandomFactory()
}));
return await rulesProvider.GetRulesEngineAsync();
});
});

builder.Logging.SetMinimumLevel(LogLevel.Trace).AddConsole();

var app = builder.Build();

Expand All @@ -24,43 +39,24 @@ public static void Main(string[] args)
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAntiforgery();

app.UseEndpoints(endpoints => { endpoints.MapControllers(); });

AddRulesFrameworkUI(app, useReadmeExample: false);
app.UseRulesFrameworkWebUI(opt =>
{
opt.DocumentTitle = "Sample rules";
});

app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
}

private static void AddRulesFrameworkUI(IApplicationBuilder app, bool useReadmeExample = false)
{
if (useReadmeExample)
{
app.UseRulesFrameworkWebUI(new BasicRulesEngineExample().RulesEngine);

return;
}

var rulesProvider = new RulesEngineProvider(new RulesBuilder(new List<IRuleSpecificationsProvider>()
{
new RulesRandomFactory()
}));

var rulesEngine = rulesProvider
.GetRulesEngineAsync()
.GetAwaiter()
.GetResult();

app.UseRulesFrameworkWebUI(rulesEngine);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "rules/index.html",
"launchUrl": "rules-ui/instance-selection",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ namespace Rules.Framework.WebUI.Sample.ReadmeExample
{
using System;
using global::Rules.Framework.WebUI.Sample.Engine;
using global::Rules.Framework.WebUI.Sample.Enums;

internal class BasicRulesEngineExample
{
Expand Down Expand Up @@ -35,7 +34,7 @@ protected void AddRules(IEnumerable<RuleSpecificationBase<BasicRulesetNames, Bas

protected void CreateRulesets()
{
foreach (var rulesetName in Enum.GetValues<RulesetNames>())
foreach (var rulesetName in Enum.GetValues<BasicRulesetNames>())
{
this.RulesEngine.CreateRulesetAsync(rulesetName.ToString())
.GetAwaiter()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
}
}
135 changes: 135 additions & 0 deletions src/Rules.Framework.WebUI/Assets/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

a, .btn-link {
color: #006bb7;
}

.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
padding-top: 1.1rem;
}

h1:focus {
outline: none;
}

.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}

.invalid {
outline: 1px solid #e50000;
}

.validation-message {
color: #e50000;
}

.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}

.blazor-error-boundary::after {
content: "An error has occurred."
}

.darker-border-checkbox.form-check-input {
border-color: #929292;
}

.page {
position: relative;
display: flex;
flex-direction: column;
}

main {
max-height: calc(100vh - 3.5rem);
height: calc(100vh - 3.5rem);
}

.sidebar {
background-color: rgb(255, 255, 255, 100);
}

.top-row {
height: 3.5rem;
background-color: rgb(255, 255, 255, 100);
}

@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}

.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}

@media (min-width: 641px) {
article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}

.page {
flex-direction: row;
}

.sidebar {
width: 250px;
height: calc(100vh - 3.5rem);
position: sticky;
top: 0;
}

.top-row {
position: sticky;
top: 0;
z-index: 1;
}

.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}

.top-row {
padding-left: 0 !important;
padding-right: 0 !important;
}
}

#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}

#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
15 changes: 15 additions & 0 deletions src/Rules.Framework.WebUI/Assets/engine.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/Rules.Framework.WebUI/Assets/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/Rules.Framework.WebUI/Assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions src/Rules.Framework.WebUI/Components/Layout/MainLayout.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@attribute [ExcludeFromCodeCoverage]
@inherits LayoutComponentBase

<div class="page">
<div class="container-fluid">
<div class="row top-row shadow-sm align-items-center">
<div class="" style="width: 250px;">
<a class="link-underline link-underline-opacity-0 align-middle" style="color: black; font-size: 1.5em;" href="/rules-ui">
<Image Src="rules-ui/logo.svg" Style="width: 24px; height: 24px;" />
<span class="fw-medium">Rules.Framework</span>
</a>
</div>
<div class="col">
<span style="font-size: 1.5em; color: rgba(0,0,0,0.37);">Web UI</span>
</div>
</div>
<div class="row">
<div class="sidebar border-end">
<NavMenu />
</div>

<main class="row">
<article class="content">
@Body
</article>
</main>
</div>
</div>
</div>

<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
Loading