Add a benchmark app

This commit is contained in:
Pranav K 2019-09-09 16:02:05 -07:00
parent 6594d8bb7c
commit 07df9cfcf5
No known key found for this signature in database
GPG Key ID: 1963DA6D96C3057A
50 changed files with 2153 additions and 0 deletions

View File

@ -0,0 +1,6 @@
<Router AppAssembly="typeof(Program).Assembly">
<NotFound>Page not found</NotFound>
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)"></RouteView>
</Found>
</Router>

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework Condition="'$(BenchmarksTargetFramework)' != ''">$(BenchmarksTargetFramework)</TargetFramework>
<IsTestAssetProject>true</IsTestAssetProject>
</PropertyGroup>
<!-- These references are used when building on the Benchmarks Server. -->
<ItemGroup Condition="'$(BenchmarksTargetFramework)' != ''">
<FrameworkReference Update="Microsoft.AspNetCore.App" RuntimeFrameworkVersion="$(MicrosoftAspNetCoreAppPackageVersion)" />
<FrameworkReference Update="Microsoft.NETCore.App" RuntimeFrameworkVersion="$(MicrosoftNETCoreAppPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,13 @@
using Microsoft.JSInterop;
using System.Threading.Tasks;
namespace BlazingPizza.Server
{
public static class JSRuntimeExtensions
{
public static ValueTask<bool> Confirm(this IJSRuntime jsRuntime, string message)
{
return jsRuntime.InvokeAsync<bool>("confirm", message);
}
}
}

View File

@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;
namespace BlazingPizza
{
public class Address
{
public int Id { get; set; }
[Required, MaxLength(100)]
public string Name { get; set; }
[Required, MaxLength(100)]
public string Line1 { get; set; }
[MaxLength(100)]
public string Line2 { get; set; }
[Required, MaxLength(50)]
public string City { get; set; }
[Required, MaxLength(20)]
public string Region { get; set; }
[Required, MaxLength(20)]
public string PostalCode { get; set; }
}
}

View File

@ -0,0 +1,27 @@
namespace BlazingPizza
{
public class LatLong
{
public LatLong()
{
}
public LatLong(double latitude, double longitude) : this()
{
Latitude = latitude;
Longitude = longitude;
}
public double Latitude { get; set; }
public double Longitude { get; set; }
public static LatLong Interpolate(LatLong start, LatLong end, double proportion)
{
// The Earth is flat, right? So no need for spherical interpolation.
return new LatLong(
start.Latitude + (end.Latitude - start.Latitude) * proportion,
start.Longitude + (end.Longitude - start.Longitude) * proportion);
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace BlazingPizza
{
public class Order
{
public int OrderId { get; set; }
public string UserId { get; set; }
public DateTime CreatedTime { get; set; }
public Address DeliveryAddress { get; set; } = new Address();
public LatLong DeliveryLocation { get; set; }
public List<Pizza> Pizzas { get; set; } = new List<Pizza>();
public decimal GetTotalPrice() => Pizzas.Sum(p => p.GetTotalPrice());
public string GetFormattedTotalPrice() => GetTotalPrice().ToString("0.00");
}
}

View File

@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Linq;
namespace BlazingPizza
{
/// <summary>
/// Represents a customized pizza as part of an order
/// </summary>
public class Pizza
{
public const int DefaultSize = 12;
public const int MinimumSize = 9;
public const int MaximumSize = 17;
public int Id { get; set; }
public int OrderId { get; set; }
public PizzaSpecial Special { get; set; }
public int SpecialId { get; set; }
public int Size { get; set; }
public List<PizzaTopping> Toppings { get; set; }
public decimal GetBasePrice()
{
return ((decimal)Size / (decimal)DefaultSize) * Special.BasePrice;
}
public decimal GetTotalPrice()
{
return GetBasePrice() + Toppings.Sum(t => t.Topping.Price);
}
public string GetFormattedTotalPrice()
{
return GetTotalPrice().ToString("0.00");
}
}
}

View File

@ -0,0 +1,20 @@
namespace BlazingPizza
{
/// <summary>
/// Represents a pre-configured template for a pizza a user can order
/// </summary>
public class PizzaSpecial
{
public int Id { get; set; }
public string Name { get; set; }
public int BasePrice { get; set; }
public string Description { get; set; }
public string ImageUrl { get; set; }
public string GetFormattedBasePrice() => BasePrice.ToString("0.00");
}
}

View File

@ -0,0 +1,11 @@
namespace BlazingPizza
{
public class PizzaTopping
{
public Topping Topping { get; set; }
public int ToppingId { get; set; }
public int PizzaId { get; set; }
}
}

View File

@ -0,0 +1,13 @@
namespace BlazingPizza
{
public class Topping
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string GetFormattedPrice() => Price.ToString("0.00");
}
}

View File

@ -0,0 +1,9 @@
namespace BlazingPizza
{
public class UserInfo
{
public bool IsAuthenticated { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,68 @@
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
namespace BlazingPizza.Server
{
public class OrderState
{
private readonly ILogger<OrderState> logger;
public OrderState(ILogger<OrderState> logger)
{
this.logger = logger;
}
public bool ShowingConfigureDialog { get; private set; }
public Pizza ConfiguringPizza { get; private set; }
public Order Order { get; private set; } = new Order();
public void ShowConfigurePizzaDialog(PizzaSpecial special)
{
logger.LogInformation($"Configuring pizza {special.Id}");
ConfiguringPizza = new Pizza()
{
Special = special,
SpecialId = special.Id,
Size = Pizza.DefaultSize,
Toppings = new List<PizzaTopping>(),
};
ShowingConfigureDialog = true;
}
public void CancelConfigurePizzaDialog()
{
ConfiguringPizza = null;
ShowingConfigureDialog = false;
}
public void ConfirmConfigurePizzaDialog()
{
logger.LogInformation($"Adding pizza {ConfiguringPizza.SpecialId}");
Order.Pizzas.Add(ConfiguringPizza);
ConfiguringPizza = null;
ShowingConfigureDialog = false;
}
public void RemoveConfiguredPizza(Pizza pizza)
{
Order.Pizzas.Remove(pizza);
}
public void ResetOrder()
{
Order = new Order();
}
public void ReplaceOrder(Order order)
{
Order = order;
}
}
}

View File

@ -0,0 +1,34 @@
@page "/checkout"
@inject OrderState OrderState
<div class="main">
<EditForm Model="@OrderState.Order.DeliveryAddress">
<div class="checkout-cols">
<div class="checkout-order-details">
<h4>Review order</h4>
<OrderReview Order="@OrderState.Order" />
</div>
<div class="checkout-delivery-address">
<h4>Deliver to...</h4>
<AddressEditor Address="@OrderState.Order.DeliveryAddress" />
</div>
</div>
<button type="submit" class="checkout-button btn btn-warning">
Place order
</button>
<DataAnnotationsValidator />
</EditForm>
</div>
@functions {
protected override void OnInitialized()
{
// Try to recover any temporary saved order
OrderState.ReplaceOrder(new Order
{
});
}
}

View File

@ -0,0 +1,74 @@
@page "/"
@inject OrderState OrderState
@inject IJSRuntime JS
@inject SpecialsService Specials
<div class="main">
<ul class="pizza-cards">
@if (specials != null)
{
@foreach (var special in specials)
{
var id = $"pizza{special.Id}";
<li id="@id" @onclick="@(() => OrderState.ShowConfigurePizzaDialog(special))">
<div class="pizza-info">
<span class="title">@special.Name</span>
@special.Description
<span class="price">@special.GetFormattedBasePrice()</span>
</div>
</li>
}
}
</ul>
</div>
<div class="sidebar" id="pizzaOrders" pizzaCount="@Order.Pizzas.Count">
@if (Order.Pizzas.Any())
{
<div class="order-contents">
<h2>Your order</h2>
@foreach (var configuredPizza in Order.Pizzas)
{
<ConfiguredPizzaItem Pizza="configuredPizza" OnRemoved="@(() => RemovePizza(configuredPizza))" />
}
</div>
}
else
{
<div class="empty-cart">Choose a pizza<br>to get started</div>
}
<div class="order-total @(Order.Pizzas.Any() ? "" : "hidden")">
Total:
<span class="total-price">@Order.GetFormattedTotalPrice()</span>
<a href="checkout" class="btn btn-warning" disabled="@(Order.Pizzas.Count == 0)">
Order >
</a>
</div>
</div>
<TemplatedDialog Show="OrderState.ShowingConfigureDialog">
<ConfigurePizzaDialog
Pizza="OrderState.ConfiguringPizza"
OnCancel="OrderState.CancelConfigurePizzaDialog"
OnConfirm="OrderState.ConfirmConfigurePizzaDialog" />
</TemplatedDialog>
@functions {
IList<PizzaSpecial> specials;
Order Order => OrderState.Order;
protected override void OnInitialized()
{
specials = Specials.GetSpecials();
}
async Task RemovePizza(Pizza configuredPizza)
{
if (await JS.Confirm($"Remove {configuredPizza.Special.Name} pizza from the order?"))
{
OrderState.RemoveConfiguredPizza(configuredPizza);
}
}
}

View File

@ -0,0 +1,22 @@
@page "/"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BlazorServerSIde</title>
<base href="~/" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
asp-fallback-href="css/bootstrap/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
crossorigin="anonymous"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"/>
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<app>@(await Html.RenderComponentAsync<BlazingPizza.Server.App>(RenderMode.ServerPrerendered))</app>
<script src="_framework/blazor.server.js"></script>
</body>
</html>

View File

@ -0,0 +1 @@
@layout MainLayout

View File

@ -0,0 +1,23 @@
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace BlazingPizza.Server
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

View File

@ -0,0 +1,51 @@
<div class="form-field">
<label>Name:</label>
<div>
<InputText @bind-Value="@Address.Name" />
<ValidationMessage For="@(() => Address.Name)" />
</div>
</div>
<div class="form-field">
<label>Line 1:</label>
<div>
<InputText @bind-Value="@Address.Line1" id="Line1" />
<ValidationMessage For="@(() => Address.Line1)" />
</div>
</div>
<div class="form-field">
<label>Line 2:</label>
<div>
<InputText @bind-Value="@Address.Line2" />
<ValidationMessage For="@(() => Address.Line2)" />
</div>
</div>
<div class="form-field">
<label>City:</label>
<div>
<InputText @bind-Value="@Address.City" />
<ValidationMessage For="@(() => Address.City)" />
</div>
</div>
<div class="form-field">
<label>Region:</label>
<div>
<InputText @bind-Value="@Address.Region" />
<ValidationMessage For="@(() => Address.Region)" />
</div>
</div>
<div class="form-field">
<label>Postal code:</label>
<div>
<InputText @bind-Value="@Address.PostalCode" />
<ValidationMessage For="@(() => Address.PostalCode)" />
</div>
</div>
@functions {
[Parameter] public Address Address { get; set; }
}

View File

@ -0,0 +1,92 @@
@inject ToppingsService ToppingsService
<div class="dialog-title">
<h2>@Pizza.Special.Name</h2>
@Pizza.Special.Description
</div>
<form class="dialog-body">
<div>
<label>Size:</label>
<input type="range" min="@Pizza.MinimumSize" max="@Pizza.MaximumSize" step="1" @bind-value="@Pizza.Size" @bind-value:event="oninput" />
<span class="size-label">
@(Pizza.Size)" (£@(Pizza.GetFormattedTotalPrice()))
</span>
</div>
<div>
<label>Extra Toppings:</label>
@if (toppings == null)
{
<select class="custom-select" disabled>
<option>(loading...)</option>
</select>
}
else if (Pizza.Toppings.Count >= 6)
{
<div>(maximum reached)</div>
}
else
{
<select id="custom-select" class="custom-select" @onchange="@ToppingSelected">
<option value="-1" disabled selected>(select)</option>
@for (var i = 0; i < toppings.Count; i++)
{
<option value="@i">@toppings[i].Name - (£@(toppings[i].GetFormattedPrice()))</option>
}
</select>
}
</div>
<div class="toppings">
@foreach (var topping in Pizza.Toppings)
{
<div class="topping">
@topping.Topping.Name
<span class="topping-price">@topping.Topping.GetFormattedPrice()</span>
<button type="button" class="delete-topping" @onclick="@(() => RemoveTopping(topping.Topping))">x</button>
</div>
}
</div>
</form>
<div class="dialog-buttons">
<button class="btn btn-secondary mr-auto" @onclick="@OnCancel" id="cancel">Cancel</button>
<span class="mr-center">
Price: <span class="price">@(Pizza.GetFormattedTotalPrice())</span>
</span>
<button class="btn btn-success ml-auto" @onclick="@OnConfirm" id="confirm">Order ></button>
</div>
@functions {
IList<Topping> toppings;
[Parameter] public Pizza Pizza { get; set; }
[Parameter] public EventCallback OnCancel { get; set; }
[Parameter] public EventCallback OnConfirm { get; set; }
protected override void OnInitialized()
{
toppings = ToppingsService.GetToppings();
}
void ToppingSelected(ChangeEventArgs e)
{
if (int.TryParse((string)e.Value, out var index) && index >= 0)
{
AddTopping(toppings[index]);
}
}
void AddTopping(Topping topping)
{
if (Pizza.Toppings.Find(pt => pt.Topping == topping) == null)
{
Pizza.Toppings.Add(new PizzaTopping() { Topping = topping });
}
}
void RemoveTopping(Topping topping)
{
Pizza.Toppings.RemoveAll(pt => pt.Topping == topping);
StateHasChanged();
}
}

View File

@ -0,0 +1,18 @@
<div class="cart-item">
<a @onclick="@OnRemoved" class="delete-item">x</a>
<div class="title">@(Pizza.Size)" @Pizza.Special.Name</div>
<ul>
@foreach (var topping in Pizza.Toppings)
{
<li>+ @topping.Topping.Name</li>
}
</ul>
<div class="item-price">
@Pizza.GetFormattedTotalPrice()
</div>
</div>
@functions {
[Parameter] public Pizza Pizza { get; set; }
[Parameter] public EventCallback OnRemoved { get; set; }
}

View File

@ -0,0 +1,20 @@
@inherits LayoutComponentBase
<div class="top-bar">
<img class="logo" src="img/logo.svg" />
<NavLink href="" class="nav-tab" Match="NavLinkMatch.All">
<img src="img/pizza-slice.svg" />
<div>Get Pizza</div>
</NavLink>
<NavLink href="myorders" class="nav-tab">
<img src="img/bike.svg" />
<div>My Orders</div>
</NavLink>
</div>
<div class="content">
@Body
</div>

View File

@ -0,0 +1,28 @@
@foreach (var pizza in Order.Pizzas)
{
<p>
<strong>
@(pizza.Size)"
@pizza.Special.Name
(£@pizza.GetFormattedTotalPrice())
</strong>
</p>
<ul>
@foreach (var topping in pizza.Toppings)
{
<li>+ @topping.Topping.Name</li>
}
</ul>
}
<p>
<strong>
Total price:
£@Order.GetFormattedTotalPrice()
</strong>
</p>
@functions {
[Parameter] public Order Order { get; set; }
}

View File

@ -0,0 +1,13 @@
@if (Show)
{
<div class="dialog-container">
<div class="dialog">
@ChildContent
</div>
</div>
}
@functions {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public bool Show { get; set; }
}

View File

@ -0,0 +1,36 @@
@typeparam TItem
@if (items == null)
{
@LoadingContent
}
else if (items.Count == 0)
{
@EmptyContent
}
else
{
<div class="list-group @ListGroupClass">
@foreach (var item in items)
{
<div class="list-group-item">
@ItemContent(item)
</div>
}
</div>
}
@functions {
List<TItem> items;
[Parameter] public Func<Task<List<TItem>>> Loader { get; set; }
[Parameter] public RenderFragment LoadingContent { get; set; }
[Parameter] public RenderFragment EmptyContent { get; set; }
[Parameter] public RenderFragment<TItem> ItemContent { get; set; }
[Parameter] public string ListGroupClass { get; set; }
protected override async Task OnParametersSetAsync()
{
items = await Loader();
}
}

View File

@ -0,0 +1,77 @@
using System.Collections.Generic;
namespace BlazingPizza.Server
{
public class SpecialsService
{
public IList<PizzaSpecial> GetSpecials()
{
return new PizzaSpecial[]
{
new PizzaSpecial()
{
Name = "Basic Cheese Pizza",
Description = "It's cheesy and delicious. Why wouldn't you want one?",
BasePrice = 9,
ImageUrl = "img/pizzas/cheese.jpg",
},
new PizzaSpecial()
{
Id = 2,
Name = "The Baconatorizor",
Description = "It has EVERY kind of bacon",
BasePrice = 12,
ImageUrl = "img/pizzas/bacon.jpg",
},
new PizzaSpecial()
{
Id = 3,
Name = "Classic pepperoni",
Description = "It's the pizza you grew up with, but Blazing hot!",
BasePrice = 10,
ImageUrl = "img/pizzas/pepperoni.jpg",
},
new PizzaSpecial()
{
Id = 4,
Name = "Buffalo chicken",
Description = "Spicy chicken, hot sauce and bleu cheese, guaranteed to warm you up",
BasePrice = 12,
ImageUrl = "img/pizzas/meaty.jpg",
},
new PizzaSpecial()
{
Id = 5,
Name = "Mushroom Lovers",
Description = "It has mushrooms. Isn't that obvious?",
BasePrice = 11,
ImageUrl = "img/pizzas/mushroom.jpg",
},
new PizzaSpecial()
{
Id = 6,
Name = "The Brit",
Description = "When in London...",
BasePrice = 10,
ImageUrl = "img/pizzas/brit.jpg",
},
new PizzaSpecial()
{
Id = 7,
Name = "Veggie Delight",
Description = "It's like salad, but on a pizza",
BasePrice = 11,
ImageUrl = "img/pizzas/salad.jpg",
},
new PizzaSpecial()
{
Id = 8,
Name = "Margherita",
Description = "Traditional Italian pizza with tomatoes and basil",
BasePrice = 9,
ImageUrl = "img/pizzas/margherita.jpg",
},
};
}
}
}

View File

@ -0,0 +1,58 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Linq;
using System.Net.Mime;
namespace BlazingPizza.Server
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddServerSideBlazor(options => options.DetailedErrors = true);
services.AddScoped<OrderState>();
services.AddScoped<SpecialsService>();
services.AddScoped<ToppingsService>();
services.AddResponseCompression(options =>
{
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { MediaTypeNames.Application.Octet });
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseResponseCompression();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}

View File

@ -0,0 +1,124 @@
using System.Collections.Generic;
namespace BlazingPizza.Server
{
public class ToppingsService
{
public IList<Topping> GetToppings()
{
return new Topping[]
{
new Topping()
{
Name = "Extra cheese",
Price = 2.50m,
},
new Topping()
{
Name = "American bacon",
Price = 2.99m,
},
new Topping()
{
Name = "British bacon",
Price = 2.99m,
},
new Topping()
{
Name = "Canadian bacon",
Price = 2.99m,
},
new Topping()
{
Name = "Tea and crumpets",
Price = 5.00m
},
new Topping()
{
Name = "Fresh-baked scones",
Price = 4.50m,
},
new Topping()
{
Name = "Bell peppers",
Price = 1.00m,
},
new Topping()
{
Name = "Onions",
Price = 1.00m,
},
new Topping()
{
Name = "Mushrooms",
Price = 1.00m,
},
new Topping()
{
Name = "Pepperoni",
Price = 1.00m,
},
new Topping()
{
Name = "Duck sausage",
Price = 3.20m,
},
new Topping()
{
Name = "Venison meatballs",
Price = 2.50m,
},
new Topping()
{
Name = "Served on a silver platter",
Price = 250.99m,
},
new Topping()
{
Name = "Lobster on top",
Price = 64.50m,
},
new Topping()
{
Name = "Sturgeon caviar",
Price = 101.75m,
},
new Topping()
{
Name = "Artichoke hearts",
Price = 3.40m,
},
new Topping()
{
Name = "Fresh tomatos",
Price = 1.50m,
},
new Topping()
{
Name = "Basil",
Price = 1.50m,
},
new Topping()
{
Name = "Steak (medium-rare)",
Price = 8.50m,
},
new Topping()
{
Name = "Blazing hot peppers",
Price = 4.20m,
},
new Topping()
{
Name = "Buffalo chicken",
Price = 5.00m,
},
new Topping()
{
Name = "Blue cheese",
Price = 2.50m,
},
};
}
}
}

View File

@ -0,0 +1,9 @@
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using BlazingPizza.Server
@using BlazingPizza.Server.Shared
@using System.Security.Claims

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,40 @@
/* quicksand-300 - latin */
@font-face {
font-family: 'Quicksand';
font-style: normal;
font-weight: 300;
src: local('Quicksand Light'), local('Quicksand-Light'),
url('quicksand-v8-latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('quicksand-v8-latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* quicksand-regular - latin */
@font-face {
font-family: 'Quicksand';
font-style: normal;
font-weight: 400;
src: local('Quicksand Regular'), local('Quicksand-Regular'),
url('quicksand-v8-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('quicksand-v8-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* quicksand-500 - latin */
@font-face {
font-family: 'Quicksand';
font-style: normal;
font-weight: 500;
src: local('Quicksand Medium'), local('Quicksand-Medium'),
url('quicksand-v8-latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('quicksand-v8-latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* quicksand-700 - latin */
@font-face {
font-family: 'Quicksand';
font-style: normal;
font-weight: 700;
src: local('Quicksand Bold'), local('Quicksand-Bold'),
url('quicksand-v8-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('quicksand-v8-latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

View File

@ -0,0 +1,736 @@
@import url('font/quicksand.css');
body, html {
height: 100%;
}
body {
padding-top: 5rem;
flex-direction: column;
font-family: 'quicksand';
overflow-y: hidden;
}
form {
width: 100%;
}
.form-group.row > .col-form-label {
text-align: right;
}
.top-bar {
height: 5rem;
background-color: rgb(192,0,0);
background-image: linear-gradient(rgba(0,0,0,0.3) 0%, rgba(0,0,0,0) 70%);
display: flex;
align-items: stretch;
color: white;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
padding: 0 3rem;
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 1030;
}
.logo {
margin-right: 3rem;
width: 9rem;
}
.content {
display: flex;
height: 100%;
z-index: 1;
background-color: white;
}
.main {
flex-grow: 1;
overflow-y: auto;
background: linear-gradient(rgba(0,0,0,0) 40%, rgba(0,0,0,0.4) 80%);
padding: 1.5rem !important;
}
.nav-tab {
margin: 0;
padding: 0.3rem 1.8rem;
display: inline-block;
background-color: rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 0.9rem;
color: white;
position: relative;
text-transform: uppercase;
transition: 0.2s ease-out;
}
.nav-tab:hover {
color: white;
text-decoration: none;
background-color: rgba(255,255,255,0.3);
}
.nav-tab.active {
background-color: rgba(255,255,255,0.2);
color: #fff2cc;
}
.nav-tab img {
height: 2rem;
margin-bottom: 0.25rem;
}
.nav-tab.active img {
filter: brightness(0) saturate(100%) invert(93%) sepia(18%) saturate(797%) hue-rotate(316deg) brightness(109%) contrast(101%);
}
.nav-tab.active:after {
content: "";
position: absolute;
bottom: -1rem;
z-index: 1;
width: 0px;
height: 0px;
border-left: 0.6rem solid transparent;
border-right: 0.6rem solid transparent;
border-top: 1rem solid rgb(205,51,51);
}
.user-info {
margin-left: auto;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.user-info img {
margin-right: 0.7rem;
width: 2.6rem;
}
.user-info .username {
display: block;
font-weight: 700;
line-height: 0.7rem;
margin-top: 0.5rem;
}
.user-info a {
color: #fff2cc;
font-size: 0.8rem;
}
.pizza-cards {
display: grid;
grid-template-columns: repeat(auto-fill, 20rem);
grid-gap: 2rem;
justify-content: center;
padding-left: 0;
}
.pizza-cards > li {
height: 10rem;
position: relative;
background-size: cover;
border-radius: 0.5rem;
list-style-type: none;
box-shadow: 0 3px 4px rgba(0,0,0,0.4);
transition: 0.1s ease-out;
}
.pizza-cards > li:hover {
transform: scale(1.02);
}
.pizza-info {
border-radius: 0.5rem;
top: 0;
left: 0;
right: 0;
bottom: 0;
position: absolute;
background: linear-gradient(rgba(0,0,0,0.7) 30%, rgba(0,0,0,0) 80%);
padding: 1rem 1rem;
color: #fff2cc;
cursor: pointer;
text-shadow: 0 2px 2px rgba(0,0,0,0.5);
line-height: 1.25rem;
}
.pizza-info .title {
color: white;
font-size: 1.4rem;
display: block;
margin: 0.2rem 0 0.4rem 0;
font-family: 'Bahnschrift', Arial, Helvetica, sans-serif;
text-transform: uppercase;
}
.pizza-info .price {
position: absolute;
bottom: 0.5rem;
right: 1rem;
font-size: 1.5rem;
font-weight: 700;
padding: 0rem 0.7rem;
border-radius: 4px;
background-color: #08af08;
color: white;
line-height: 2rem;
}
.price::before {
content: '£';
font-weight: 300;
font-size: 1.2rem;
margin-right: 0.2rem;
}
.sidebar {
background-color: #2b2b2b;
width: 20rem;
display: flex;
flex-direction: column;
color: white;
}
.order-contents {
overflow-y: auto;
padding: 2rem 1.5rem 1.5rem 1.5rem;
flex-grow: 1;
}
.order-contents h2 {
color: #fff2cc;
font-size: 1.3rem;
font-weight: 300;
margin-bottom: 1rem;
font-family: 'Bahnschrift', Arial, Helvetica, sans-serif;
text-transform: uppercase;
}
.order-total {
background-color: rgb(191, 52, 52);
height: 4rem;
flex-shrink: 0;
display: flex;
flex-direction: row;
align-items: center;
color: white;
font-size: 1.2rem;
transition: all 600ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
padding: 0 1.5rem;
}
.order-total.hidden {
transform: translate3d(0, 4rem, 0);
}
.order-total .total-price {
font-weight: 700;
font-size: 1.5rem;
}
.order-total .total-price::before {
content: '£';
font-weight: 300;
margin: 0 0.1rem 0 0.4rem;
}
.order-total .btn {
margin-left: auto;
font-weight: 700;
border-radius: 20px;
padding: 0.4rem 1.2rem;
}
.checkout-button {
margin: auto;
display: block;
font-weight: 700;
border-radius: 20px;
padding: 0.4rem 1.2rem;
}
.cart-item {
background-color: #333333;
padding: 0.8rem 1.2rem;
border-radius: 6px;
font-weight: 100;
margin-top: 1rem;
position: relative;
}
.cart-item .title {
font-weight: 700;
}
.cart-item ul {
padding: 0;
margin: 0.4rem 0.6rem;
}
.cart-item li {
list-style-type: none;
margin-left: 0rem;
font-size: 0.8rem;
}
.empty-cart {
text-align: center;
margin: auto;
font-size: 1.5rem;
font-weight: 100;
color: #676767;
}
.item-price {
font-weight: 500;
}
.item-price::before {
content: '£';
font-weight: 100;
margin-right: 0.3rem;
}
.delete-item {
position: absolute;
top: 0;
right: 0;
content: 'X';
cursor: pointer;
color: #fff2cc;
width: 2rem;
height: 2rem;
text-align: center;
}
.delete-item:hover {
text-decoration: none;
color: #fff2cc;
background-color: rgba(255,255,255,0.1);
}
.configured-pizza-item {
display: flex;
flex-direction: row;
}
.dialog-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0,0,0,0.5);
z-index: 2000;
display: flex;
animation: dialog-container-entry 0.2s;
}
@keyframes dialog-container-entry {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.dialog {
background-color: white;
box-shadow: 0 0 12px rgba(0,0,0,0.6);
display: flex;
flex-direction: column;
z-index: 2000;
align-self: center;
margin: auto;
width: 700px;
max-height: calc(100% - 3rem);
animation: dialog-entry 0.4s;
animation-timing-function: cubic-bezier(0.075, 0.820, 0.165, 1.000);
}
@keyframes dialog-entry {
0% {
transform: translateY(30px) scale(0.95);
}
100% {
transform: translateX(0px) scale(1.0);
}
}
.dialog-title {
background-color: #444;
color: #fff2cc;
padding: 1.3rem 2rem;
}
.dialog-title h2 {
color: white;
font-size: 1.4rem;
margin: 0;
font-family: 'Bahnschrift', Arial, Helvetica, sans-serif;
text-transform: uppercase;
line-height: 1.3rem;
}
.dialog-body {
flex-grow: 1;
padding: 0.5rem 3rem 1rem 0;
}
.dialog-buttons {
height: 4rem;
flex-shrink: 0;
display: flex;
align-items: center;
background-color: #eee;
padding: 0 1rem;
}
.dialog-body > div {
display: flex;
margin-top: 1rem;
align-items: center;
}
.dialog-body label {
text-align: right;
width: 200px;
margin: 0 1.5rem;
}
.dialog-body input, .dialog-body select {
flex-grow: 1;
width: unset;
}
.dialog-body .size-label {
min-width: 110px;
text-align: right;
}
.dialog .toppings {
text-align: center;
display: block;
padding-left: 4rem;
}
.dialog .topping {
display: inline-block;
background-color: #a04343;
color: white;
padding: 0.2rem 1rem;
border-radius: 2rem;
margin: 0.4rem 0.3rem;
font-weight: 700;
}
.dialog .topping-price {
font-weight: 100;
font-size: 0.8rem;
}
.dialog .topping-price::before {
content: '£';
}
.delete-topping {
background: none;
border: none;
color: white;
padding: 0.2rem 0.2rem 0.3rem 0.2rem;
cursor: pointer;
}
.delete-topping:hover {
color: yellow;
}
.form-message {
padding: 0.5rem;
font-weight: 700;
}
.dialog .price {
font-weight: 700;
font-size: 1.5rem;
}
.orders-list .list-group-item {
display: flex;
}
.orders-list .col {
margin: auto;
}
.orders-list h5 {
color: #c03939;
font-size: 1.3rem;
font-weight: 300;
margin: 0.2rem 0 0 0;
font-family: 'Bahnschrift', Arial, Helvetica, sans-serif;
text-transform: uppercase;
}
.track-order {
background-color: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.4);
height: 100%;
display: flex;
flex-direction: column;
}
.track-order > div {
overflow-y: hidden;
}
.track-order-title {
background-color: #eee;
display: flex;
align-items: center;
padding: 1rem 3rem;
}
.track-order-title h2 {
color: #c03939;
font-size: 1.3rem;
font-weight: 300;
margin: 0rem;
font-family: 'Bahnschrift', Arial, Helvetica, sans-serif;
text-transform: uppercase;
}
.track-order-body {
flex-grow: 1;
display: flex;
}
.track-order-details {
overflow-y: auto;
padding: 1.5rem 3rem;
flex-grow: 1;
}
.track-order-map {
width: 350px;
flex-shrink: 0;
}
a.sign-in {
background: none;
border: 1.5px solid white;
border-radius: 0.7em;
color: white;
text-transform: uppercase;
padding: 0.2rem 0.8rem 0.1rem 0.8rem;
font-family: 'Bahnschrift', Arial, Helvetica, sans-serif;
font-weight: 100;
cursor: pointer;
transition: 0.2s ease-out;
}
a.sign-in:hover {
background-color: rgba(255,255,255,0.3);
color: #fff2cc;
border-color: #fff2cc;
}
.user-info a.sign-out {
color: #fff2cc;
font-size: 0.8rem;
cursor: pointer;
}
.user-info a.sign-out:hover {
text-decoration: underline;
}
input[type=range] {
-webkit-appearance: none;
margin: 7.1px 0;
height: 21px;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 5.8px;
cursor: pointer;
box-shadow: 0px 0px 1px #000000, 0px 0px 0px #0d0d0d;
background: #dcdcdc;
border-radius: 1.3px;
border: 0px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0.9px 0.9px 1px rgba(0, 0, 49, 0.43), 0px 0px 0.9px rgba(0, 0, 75, 0.43);
border: 0px solid #00001e;
height: 20px;
width: 20px;
border-radius: 10px;
background: #d45352;
cursor: pointer;
-webkit-appearance: none;
margin-top: -7.1px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #e1e1e1;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 5.8px;
cursor: pointer;
box-shadow: 0px 0px 1px #000000, 0px 0px 0px #0d0d0d;
background: #dcdcdc;
border-radius: 1.3px;
border: 0px solid #010101;
}
input[type=range]::-moz-range-thumb {
box-shadow: 0.9px 0.9px 1px rgba(0, 0, 49, 0.43), 0px 0px 0.9px rgba(0, 0, 75, 0.43);
border: 0px solid #00001e;
height: 20px;
width: 20px;
border-radius: 10px;
background: #d45352;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 5.8px;
cursor: pointer;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #d7d7d7;
border: 0px solid #010101;
border-radius: 2.6px;
box-shadow: 0px 0px 1px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: #dcdcdc;
border: 0px solid #010101;
border-radius: 2.6px;
box-shadow: 0px 0px 1px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 0.9px 0.9px 1px rgba(0, 0, 49, 0.43), 0px 0px 0.9px rgba(0, 0, 75, 0.43);
border: 0px solid #00001e;
height: 20px;
width: 20px;
border-radius: 10px;
background: #d45352;
cursor: pointer;
margin-top: 0;
}
.checkout-cols {
display: flex;
}
.checkout-cols h4 {
margin-bottom: 1.5rem;
}
.checkout-cols > div {
flex: 1;
margin: 1rem;
border: 1px solid #ddd;
background: rgba(255,255,255,0.3);
padding: 1.25rem 1rem;
}
.checkout-cols > div:first-child {
margin-left: 0;
}
.checkout-cols > div:last-child {
margin-right: 0;
}
.loading-bar {
position: absolute;
top: calc(50% - 3px);
left: calc(50% - 250px);
width: 500px;
height: 6px;
background-color: white;
overflow: hidden;
box-shadow: 0 1px 3px rgba(0,0,0,0.2)
}
.loading-bar::after {
content: '';
display: block;
width: 200px;
height: 100%;
background-color: #dc105a;
animation: progressbar-slide 1s infinite;
animation-timing-function: ease-in-out;
}
.form-field {
display: flex;
margin: 0.5rem;
}
.form-field > label {
width: 8rem;
}
.form-field > div {
flex-grow: 1;
}
.form-field input {
width: 100%;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid red;
}
.validation-message {
color: red;
}
@keyframes progressbar-slide {
0% {
transform: translateX(-200px);
}
70% {
transform: translateX(500px);
}
100% {
transform: translateX(500px);
}
}

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="14.566216mm"
height="12.915195mm"
viewBox="0 0 14.566216 12.915195"
version="1.1"
id="svg6773"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="bike.svg">
<defs
id="defs6767" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="-495.3304"
inkscape:cy="-464.16476"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3018"
inkscape:window-height="1744"
inkscape:window-x="665"
inkscape:window-y="3070"
inkscape:window-maximized="1" />
<metadata
id="metadata6770">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-14.639502,-13.107878)">
<path
d="m 24.422045,14.741241 c 0,0.80786 -0.65263,1.4605 -1.4605,1.4605 -0.80786,0 -1.46402,-0.65264 -1.46402,-1.4605 0,-0.80786 0.65616,-1.46403 1.46402,-1.46403 0.80787,0 1.4605,0.65617 1.4605,1.46403 z"
style="fill:none;stroke:#ffffff;stroke-width:0.33866665;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4889"
inkscape:connector-curvature="0" />
<path
d="m 19.426715,23.546573 c 0,1.273528 -1.03364,2.307167 -2.30717,2.307167 -1.27352,0 -2.30716,-1.033639 -2.30716,-2.307167 0,-1.273528 1.03364,-2.307166 2.30716,-2.307166 1.27353,0 2.30717,1.033638 2.30717,2.307166 z"
style="fill:none;stroke:#ffffff;stroke-width:0.33866665;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4891"
inkscape:connector-curvature="0" />
<path
d="m 29.036385,23.546573 c 0,1.273528 -1.03364,2.307167 -2.30717,2.307167 -1.27353,0 -2.30717,-1.033639 -2.30717,-2.307167 0,-1.273528 1.03364,-2.307166 2.30717,-2.307166 1.27353,0 2.30717,1.033638 2.30717,2.307166 z"
style="fill:none;stroke:#ffffff;stroke-width:0.33866665;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4893"
inkscape:connector-curvature="0" />
<path
d="m 22.587605,19.711881 -1.04422,-0.10231 0.98072,-1.70039 2.23661,1.21709 c -0.0212,0.0212 -0.0212,0.0423 -0.0423,0.0635 l -1.7533,0.98425 v -0.0423 c 0,-0.20814 -0.16934,-0.39864 -0.37748,-0.4198 z m 4.13808,0.88194 c 0.39864,0 0.77611,0.0847 1.10772,0.22931 0.21167,-0.37747 0.35631,-0.81845 0.35631,-1.27706 0,-1.38289 -1.12889,-2.5153 -2.50825,-2.5153 -0.2928,0 -0.56444,0.0635 -0.83608,0.14816 0.10583,0.20814 0.1658,0.43745 0.18697,0.69145 l -2.82222,-1.55222 c -0.0423,-0.0212 -0.0811,-0.0423 -0.12347,-0.0423 -0.48331,-0.18697 -1.02659,-0.0212 -1.29823,0.44097 l -1.46402,2.51531 c -0.0176,0.0423 -0.0388,0.10231 -0.06,0.14464 l -4.45558,-0.45861 v 0.83608 l 3.13619,0.96308 c 1.21356,0.35631 2.09198,1.488727 2.09198,2.808115 0,0.296334 -0.0423,0.567973 -0.127,0.839612 h 4.01461 c -0.0811,-0.271639 -0.12347,-0.543278 -0.12347,-0.839612 0,-1.612194 1.31586,-2.931585 2.92452,-2.931585 z"
style="fill:none;stroke:#ffffff;stroke-width:0.33866665;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4895"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="12.864264mm"
height="12.890507mm"
viewBox="0 0 12.864264 12.890507"
version="1.1"
id="svg7666"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="pizza-slice.svg">
<defs
id="defs7660">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath4885">
<path
d="M -3.9725e-5,540 H 960 V 1.2207e-4 L -4.3448e-5,6.1035e-5"
id="path4883"
inkscape:connector-curvature="0"
style="clip-rule:evenodd" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath4875">
<path
d="M -1.9395e-5,540 H 960 V 1.2207e-4 L -2.3118e-5,6.1035e-5"
id="path4873"
inkscape:connector-curvature="0"
style="clip-rule:evenodd" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="-538.54671"
inkscape:cy="-372.78284"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3018"
inkscape:window-height="1744"
inkscape:window-x="665"
inkscape:window-y="3070"
inkscape:window-maximized="1" />
<metadata
id="metadata7663">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-26.073816,-37.310701)">
<g
id="g4869"
transform="matrix(0.35277777,0,0,-0.35277777,-82.464891,223.70045)"
style="stroke:#ffffff;stroke-opacity:1">
<g
id="g4871"
clip-path="url(#clipPath4875)"
style="stroke:#ffffff;stroke-opacity:1">
<path
d="m 331.92,516.06 c 0,0 -0.03,0.03 0,0 -0.03,0.03 -0.03,0.03 -0.03,0.03 -3.14,3.13 -6.77,5.57 -10.84,7.23 0,0 0,0 0,0 l -12.47,-30.6 30.61,12.47 c 0,0 0,0 0,0 -1.7,4.1 -4.13,7.73 -7.27,10.87 z m -10.3,-1.7 c -1.13,1.13 -1.13,2.93 -0.03,4.03 1.1,1.1 2.9,1.1 4.03,-0.03 1.13,-1.14 1.13,-2.94 0.03,-4.04 -1.1,-1.1 -2.9,-1.1 -4.03,0.04 z m -8.27,-14.94 2.3,5.63 c 0.5,-0.16 0.97,-0.36 1.37,-0.76 1.2,-1.2 1.2,-3.14 0,-4.34 -1,-1 -2.5,-1.16 -3.67,-0.53 z m 12.14,5.07 c -1.14,1.13 -1.14,2.93 -0.04,4.03 1.1,1.1 2.9,1.1 4.04,-0.03 1.13,-1.14 1.13,-2.94 0.03,-4.04 -1.1,-1.1 -2.9,-1.1 -4.03,0.04 z"
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4877"
inkscape:connector-curvature="0" />
</g>
</g>
<g
id="g4879"
transform="matrix(0.35277777,0,0,-0.35277777,-82.464891,223.70045)"
style="stroke:#ffffff;stroke-opacity:1">
<g
id="g4881"
clip-path="url(#clipPath4885)"
style="stroke:#ffffff;stroke-opacity:1">
<path
d="m 343.52,506.99 c -1.93,4.67 -4.73,8.87 -8.3,12.43 -3.6,3.6 -7.77,6.37 -12.37,8.31 -0.73,0.33 -1.56,-0.04 -1.83,-0.77 -0.27,-0.73 0.07,-1.53 0.8,-1.87 4.23,-1.76 8.07,-4.33 11.4,-7.67 3.34,-3.33 5.9,-7.16 7.7,-11.5 0.07,-0.2 0.2,-0.33 0.34,-0.47 0.4,-0.4 1,-0.53 1.53,-0.33 0.7,0.3 1.03,1.17 0.73,1.87 z"
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4887"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="15.113004mm"
height="15.113004mm"
viewBox="0 0 15.113004 15.113004"
version="1.1"
id="svg7709"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="user.svg">
<defs
id="defs7703" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="-578.58286"
inkscape:cy="28.560012"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3018"
inkscape:window-height="1744"
inkscape:window-x="665"
inkscape:window-y="3070"
inkscape:window-maximized="1" />
<metadata
id="metadata7706">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-98.276833,-141.27683)">
<path
d="m 98.806,148.83333 c 0,-3.88055 3.14678,-7.02733 7.02733,-7.02733 3.88056,0 7.02734,3.14678 7.02734,7.02733 0,3.88056 -3.14678,7.02734 -7.02734,7.02734 -3.88055,0 -7.02733,-3.14678 -7.02733,-7.02734 z"
style="fill:none;stroke:#ffffff;stroke-width:1.05833328;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="path4913"
inkscape:connector-curvature="0" />
<path
d="m 108.23222,147.28111 c 0,1.2947 -1.04775,2.34245 -2.34244,2.34245 -1.29117,0 -2.33892,-1.04775 -2.33892,-2.34245 0,-1.29117 1.04775,-2.33892 2.33892,-2.33892 1.29469,0 2.34244,1.04775 2.34244,2.33892 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.35277775"
id="path4915"
inkscape:connector-curvature="0" />
<path
d="m 110.51117,153.92392 0.0847,-1.66864 c 0,-0.35278 -0.17639,-0.70203 -0.46919,-0.93839 -0.64206,-0.52564 -1.4605,-0.87842 -2.27895,-1.11125 -0.58561,-0.17639 -1.22766,-0.29281 -1.92969,-0.29281 -0.64206,0 -1.28764,0.11642 -1.92969,0.29281 -0.81845,0.23283 -1.63689,0.64558 -2.27895,1.11125 -0.2928,0.23636 -0.46919,0.58561 -0.46919,0.93839 v 1.73214 c 1.46755,0.40569 0.98777,1.64747 4.70605,1.54869 4.36034,-0.25753 2.94217,-1.18533 4.56495,-1.61219 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.35277775"
id="path4917"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,2 @@
<Project>
</Project>

View File

@ -0,0 +1,3 @@
<!-- This file prevents any other Directory.Build.targets from a parent folder to be loaded -->
<Project>
</Project>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
<add key="extensions" value="https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json" />
<add key="entityframeworkcore" value="https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json" />
<add key="aspnetcore-tooling" value="https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json" />
<add key="aspnetcore" value="https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore/index.json" />
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View File

@ -0,0 +1,6 @@
## Blazor benchamrks
These projects assist in Benchmarking Components.
See https://github.com/aspnet/Benchmarks#benchmarks for usage guidance on using the Benchmarking tool with your application