Updating Blazor Admin (#442)
* Updating Blazor services * Adding Settings and Refactoring Services * WIP - Fighting with DI * Configuring dependencies in both Web Startup and BlazorAdmin Program.cs has them working again. * Everything works; need to optimize calls to ListBrands * LocalStorageBrandService decorator working * Added cache duration of 1 minute * Refactoring to reduce token storage Fixed issue with dropdowns binding to int * Remove token stuff from login; moved to CustomAuthStateProvider * Migrated CatalogTypes to separate service Implemented cache decorator * Ardalis/blazor refactor (#440) * 1. Migrate CatalogItemServices -> CatalogItemService. 3. Add caching to CatalogItemService. * change to $"Loading {key} from local storage" ? * docker settings added. (#441) * docker settings added. * InDocker Removed * InDocker removed from web startup. * removed unused using * no reload list if close without save * startup patch for localhost * file name fixed * removed docker from launchSettings. * Configure logging via appsettings Co-authored-by: Shady Nagy <info@shadynagy.com>
This commit is contained in:
1 parent
98fb0ee8ce
commit
e9a9dc06d7
77 files changed
+865
-533
No files matched your search
@@ -22,16 +22,12 @@ namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly ILogger<LoginModel> _logger;
|
||||
private readonly IBasketService _basketService;
|
||||
private readonly AuthService _authService;
|
||||
private readonly ITokenClaimsService _tokenClaimsService;
|
||||
|
||||
public LoginModel(SignInManager<ApplicationUser> signInManager, ILogger<LoginModel> logger, IBasketService basketService, AuthService authService, ITokenClaimsService tokenClaimsService)
|
||||
public LoginModel(SignInManager<ApplicationUser> signInManager, ILogger<LoginModel> logger, IBasketService basketService)
|
||||
{
|
||||
_signInManager = signInManager;
|
||||
_logger = logger;
|
||||
_basketService = basketService;
|
||||
_authService = authService;
|
||||
_tokenClaimsService = tokenClaimsService;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
@@ -88,8 +84,6 @@ namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
var token = await _tokenClaimsService.GetTokenAsync(Input.Email);
|
||||
CreateAuthCookie(Input.Email, token, Startup.InDocker);
|
||||
_logger.LogInformation("User logged in.");
|
||||
await TransferAnonymousBasketToUserAsync(Input.Email);
|
||||
return LocalRedirect(returnUrl);
|
||||
@@ -114,15 +108,6 @@ namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account
|
||||
return Page();
|
||||
}
|
||||
|
||||
private void CreateAuthCookie(string username, string token, bool inDocker)
|
||||
{
|
||||
var cookieOptions = new CookieOptions();
|
||||
cookieOptions.Expires = DateTime.Today.AddYears(10);
|
||||
Response.Cookies.Append("token", token, cookieOptions);
|
||||
Response.Cookies.Append("username", username, cookieOptions);
|
||||
Response.Cookies.Append("inDocker", inDocker.ToString(), cookieOptions);
|
||||
}
|
||||
|
||||
private async Task TransferAnonymousBasketToUserAsync(string userName)
|
||||
{
|
||||
if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<environment include="Development">
|
||||
<environment include="Development,Docker">
|
||||
<script src="~/Identity/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<environment exclude="Development,Docker">
|
||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js"
|
||||
asp-fallback-src="~/Identity/lib/jquery-validation/dist/jquery.validate.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator"
|
||||
|
||||
@@ -4,6 +4,8 @@ using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using BlazorShared.Authorization;
|
||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopWeb.Web.Controllers
|
||||
{
|
||||
@@ -11,13 +13,20 @@ namespace Microsoft.eShopWeb.Web.Controllers
|
||||
[ApiController]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private readonly ITokenClaimsService _tokenClaimsService;
|
||||
|
||||
public UserController(ITokenClaimsService tokenClaimsService)
|
||||
{
|
||||
_tokenClaimsService = tokenClaimsService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
[AllowAnonymous]
|
||||
public IActionResult GetCurrentUser() =>
|
||||
Ok(User.Identity.IsAuthenticated ? CreateUserInfo(User) : UserInfo.Anonymous);
|
||||
public async Task<IActionResult> GetCurrentUser() =>
|
||||
Ok(User.Identity.IsAuthenticated ? await CreateUserInfo(User) : UserInfo.Anonymous);
|
||||
|
||||
private UserInfo CreateUserInfo(ClaimsPrincipal claimsPrincipal)
|
||||
private async Task<UserInfo> CreateUserInfo(ClaimsPrincipal claimsPrincipal)
|
||||
{
|
||||
if (!claimsPrincipal.Identity.IsAuthenticated)
|
||||
{
|
||||
@@ -57,6 +66,9 @@ namespace Microsoft.eShopWeb.Web.Controllers
|
||||
userInfo.Claims = claims;
|
||||
}
|
||||
|
||||
var token = await _tokenClaimsService.GetTokenAsync(claimsPrincipal.Identity.Name);
|
||||
userInfo.Token = token;
|
||||
|
||||
return userInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>@ViewData["Title"] - Microsoft.eShopOnWeb</title>
|
||||
<base href="~/" />
|
||||
<environment include="Development">
|
||||
<environment include="Development,Docker">
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<environment exclude="Development,Docker">
|
||||
<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"
|
||||
|
||||
@@ -7,6 +7,7 @@ using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.eShopWeb.Web
|
||||
{
|
||||
@@ -42,6 +43,13 @@ namespace Microsoft.eShopWeb.Web
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration((builderContext, config) =>
|
||||
{
|
||||
var env = builderContext.HostingEnvironment;
|
||||
config
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
|
||||
+18
-8
@@ -25,13 +25,13 @@ using Blazored.LocalStorage;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||
using BlazorShared;
|
||||
|
||||
namespace Microsoft.eShopWeb.Web
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
private IServiceCollection _services;
|
||||
public static bool InDocker => Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true";
|
||||
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
@@ -49,6 +49,15 @@ namespace Microsoft.eShopWeb.Web
|
||||
//ConfigureProductionServices(services);
|
||||
}
|
||||
|
||||
public void ConfigureDockerServices(IServiceCollection services)
|
||||
{
|
||||
services.AddDataProtection()
|
||||
.SetApplicationName("eshopwebmvc")
|
||||
.PersistKeysToFileSystem(new DirectoryInfo(@"./"));
|
||||
|
||||
ConfigureDevelopmentServices(services);
|
||||
}
|
||||
|
||||
private void ConfigureInMemoryDatabases(IServiceCollection services)
|
||||
{
|
||||
// use in-memory database
|
||||
@@ -88,12 +97,6 @@ namespace Microsoft.eShopWeb.Web
|
||||
{
|
||||
services.AddCookieSettings();
|
||||
|
||||
if (InDocker)
|
||||
{
|
||||
services.AddDataProtection()
|
||||
.SetApplicationName("eshopwebmvc")
|
||||
.PersistKeysToFileSystem(new DirectoryInfo(@"./"));
|
||||
}
|
||||
|
||||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
.AddCookie(options =>
|
||||
@@ -141,15 +144,22 @@ namespace Microsoft.eShopWeb.Web
|
||||
config.Path = "/allservices";
|
||||
});
|
||||
|
||||
|
||||
var baseUrlConfig = new BaseUrlConfiguration();
|
||||
Configuration.Bind(BaseUrlConfiguration.CONFIG_NAME, baseUrlConfig);
|
||||
services.AddScoped<BaseUrlConfiguration>(sp => baseUrlConfig);
|
||||
// Blazor Admin Required Services for Prerendering
|
||||
services.AddScoped<HttpClient>(s => new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(BlazorShared.Authorization.Constants.GetWebUrl(InDocker))
|
||||
BaseAddress = new Uri(baseUrlConfig.WebBase)
|
||||
});
|
||||
|
||||
// add blazor services
|
||||
services.AddBlazoredLocalStorage();
|
||||
services.AddServerSideBlazor();
|
||||
services.AddScoped<AuthService>();
|
||||
|
||||
services.AddScoped<HttpService>();
|
||||
services.AddBlazorServices();
|
||||
|
||||
_services = services; // used to debug registered services
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - Microsoft.eShopOnWeb</title>
|
||||
<environment names="Development">
|
||||
<environment names="Development,Docker">
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
|
||||
<link rel="stylesheet" href="~/css/app.css" />
|
||||
<link rel="stylesheet" href="~/css/app.component.css" />
|
||||
@@ -49,7 +49,7 @@
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<environment names="Development">
|
||||
<environment names="Development,Docker">
|
||||
<script src="~/lib/jquery/jquery.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<environment names="Development">
|
||||
<environment names="Development,Docker">
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
</environment>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"baseUrls": {
|
||||
"apiBase": "https://localhost:5099/api/",
|
||||
"webBase": "https://localhost:44315/"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"CatalogConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.CatalogDb;",
|
||||
"IdentityConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.Identity;"
|
||||
},
|
||||
"baseUrls": {
|
||||
"apiBase": "http://localhost:5200/api/",
|
||||
"webBase": "http://host.docker.internal:5106/"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"baseUrls": {
|
||||
"apiBase": "https://localhost:5099/api/",
|
||||
"webBase": "https://localhost:44315/"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"CatalogConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.CatalogDb;",
|
||||
"IdentityConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.Identity;"
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
@font-face{font-family:Montserrat;font-weight:400;src:url(".../fonts/Montserrat-Regular.eot?") format("eot"),url("../fonts/Montserrat-Regular.woff") format("woff"),url("../fonts/Montserrat-Regular.ttf") format("truetype"),url("../fonts/Montserrat-Regular.svg#Montserrat") format("svg")}@font-face{font-family:Montserrat;font-weight:700;src:url("../fonts/Montserrat-Bold.eot?") format("eot"),url("../fonts/Montserrat-Bold.woff") format("woff"),url("../fonts/Montserrat-Bold.ttf") format("truetype"),url("../fonts/Montserrat-Bold.svg#Montserrat") format("svg")}html,body{font-family:Montserrat,sans-serif;font-size:16px;font-weight:400;z-index:10}*,*::after,*::before{box-sizing:border-box}.preloading{color:#00a69c;display:block;font-size:1.5rem;left:50%;position:fixed;top:50%;transform:translate(-50%,-50%)}select::-ms-expand{display:none}@media screen and (min-width:992px){.form-input{max-width:360px;width:360px}}.form-input{border-radius:0;height:45px;padding:10px}.form-input-small{max-width:100px !important}.form-input-medium{width:150px !important}.alert{padding-left:0}.alert-danger{background-color:transparent;border:0;color:#fb0d0d;font-size:12px}a,a:active,a:hover,a:visited{color:#000;text-decoration:none;transition:color .35s}a:hover,a:active{color:#75b918;transition:color .35s}.esh-app-footer{background-color:#000;border-top:1px solid #eee;margin-top:2.5rem;padding-bottom:2.5rem;padding-top:2.5rem;width:100%;bottom:0}.esh-app-footer-brand{height:50px;width:230px}.esh-app-header{margin:15px}.esh-app-wrapper{display:flex;min-height:100vh;flex-direction:column;justify-content:space-between}.esh-header{background-color:#00a69c;height:4rem}.esh-header-back{color:rgba(255,255,255,.5);line-height:4rem;text-decoration:none;text-transform:uppercase;transition:color .35s}.esh-header-back:hover{color:#fff;transition:color .35s}.esh-identity{line-height:3rem;position:relative;text-align:right}.esh-identity-section{display:inline-block;width:100%}.esh-identity-name{display:inline-block}.esh-identity-name--upper{text-transform:uppercase}@media screen and (max-width:768px){.esh-identity-name{font-size:.85rem}}.esh-identity-image{display:inline-block}.esh-identity-drop{background:#fff;height:10px;width:10rem;overflow:hidden;padding:.5rem;position:absolute;right:0;top:2.5rem;transition:height .35s}.esh-identity:hover .esh-identity-drop{border:1px solid #eee;height:10rem;transition:height .35s}.esh-identity-item{cursor:pointer;transition:color .35s}.esh-identity-item:hover{color:#75b918;transition:color .35s}.esh-pager-wrapper{padding-top:1rem;text-align:center}.esh-pager-item{margin:0 5vw}.esh-pager-item.is-disabled{opacity:.5;pointer-events:none}.esh-pager-item--navigable{cursor:pointer;display:inline-block}.esh-pager-item--navigable:hover{color:#83d01b}@media screen and (max-width:1280px){.esh-pager-item{font-size:.85rem}}@media screen and (max-width:1024px){.esh-pager-item{margin:0 2.5vw}}.esh-basket{min-height:80vh}.esh-basket-titles{padding-bottom:1rem;padding-top:2rem}.esh-basket-titles--clean{padding-bottom:0;padding-top:0}.esh-basket-title{text-transform:uppercase}.esh-basket-items--border{border-bottom:1px solid #eee;padding:.5rem 0}.esh-basket-items--border:last-of-type{border-color:transparent}.esh-basket-items-margin-left1{margin-left:1px}.esh-basket-item{font-size:1rem;font-weight:300}.esh-basket-item--middle{line-height:8rem}@media screen and (max-width:1024px){.esh-basket-item--middle{line-height:1rem}}.esh-basket-item--mark{color:#00a69c}.esh-basket-image{height:8rem}.esh-basket-input{line-height:1rem;width:100%}.esh-basket-checkout{background-color:#83d01b;border:0;border-radius:0;color:#fff;display:inline-block;font-size:1rem;font-weight:400;margin-top:1rem;padding:1rem 1.5rem;text-align:center;text-transform:uppercase;transition:all .35s}.esh-basket-checkout:hover{background-color:#4a760f;transition:all .35s}.esh-basketstatus{cursor:pointer;display:inline-block;float:right;position:relative;transition:all .35s}.esh-basketstatus.is-disabled{opacity:.5;pointer-events:none}.esh-basketstatus-image{height:36px;margin-top:.5rem}.esh-basketstatus-badge{background-color:#83d01b;border-radius:50%;color:#fff;display:block;height:1.5rem;left:50%;position:absolute;text-align:center;top:0;transform:translateX(-38%);transition:all .35s;width:1.5rem}.esh-basketstatus-badge-inoperative{background-color:#f00;border-radius:50%;color:#fff;display:block;height:1.5rem;left:50%;position:absolute;text-align:center;top:0;transform:translateX(-38%);transition:all .35s;width:1.5rem}.esh-basketstatus:hover .esh-basketstatus-badge{background-color:transparent;color:#75b918;transition:all .35s}.esh-catalog-hero{background-image:url("../images/main_banner.png");background-size:cover;height:260px;width:100%}.esh-catalog-title{position:relative;top:74.28571px}.esh-catalog-filters{background-color:#00a69c;height:65px}.esh-catalog-filter{-webkit-appearance:none;background-color:transparent;border-color:#00d9cc;color:#fff;cursor:pointer;marLine truncated
|
||||
@font-face{font-family:Montserrat;font-weight:400;src:url(".../fonts/Montserrat-Regular.eot?") format("eot"),url("../fonts/Montserrat-Regular.woff") format("woff"),url("../fonts/Montserrat-Regular.ttf") format("truetype"),url("../fonts/Montserrat-Regular.svg#Montserrat") format("svg")}@font-face{font-family:Montserrat;font-weight:700;src:url("../fonts/Montserrat-Bold.eot?") format("eot"),url("../fonts/Montserrat-Bold.woff") format("woff"),url("../fonts/Montserrat-Bold.ttf") format("truetype"),url("../fonts/Montserrat-Bold.svg#Montserrat") format("svg")}html,body{font-family:Montserrat,sans-serif;font-size:16px;font-weight:400;z-index:10}*,*::after,*::before{box-sizing:border-box}.preloading{color:#00a69c;display:block;font-size:1.5rem;left:50%;position:fixed;top:50%;transform:translate(-50%,-50%)}select::-ms-expand{display:none}@media screen and (min-width:992px){.form-input{max-width:360px;width:360px}}.form-input{border-radius:0;height:45px;padding:10px}.form-input-small{max-width:100px !important}.form-input-medium{width:150px !important}.alert{padding-left:0}.alert-danger{background-color:transparent;border:0;color:#fb0d0d;font-size:12px}a,a:active,a:hover,a:visited{color:#000;text-decoration:none;transition:color .35s}a:hover,a:active{color:#75b918;transition:color .35s}.esh-app-footer{background-color:#000;border-top:1px solid #eee;margin-top:2.5rem;padding-bottom:2.5rem;padding-top:2.5rem;width:100%;bottom:0}.esh-app-footer-brand{height:50px;width:230px}.esh-app-header{margin:15px}.esh-app-wrapper{display:flex;min-height:100vh;flex-direction:column;justify-content:space-between}.esh-header{background-color:#00a69c;height:4rem}.esh-header-back{color:rgba(255,255,255,.5);line-height:4rem;text-decoration:none;text-transform:uppercase;transition:color .35s}.esh-header-back:hover{color:#fff;transition:color .35s}.esh-identity{line-height:3rem;position:relative;text-align:right}.esh-identity-section{display:inline-block;width:100%}.esh-identity-name{display:inline-block}.esh-identity-name--upper{text-transform:uppercase}@media screen and (max-width:768px){.esh-identity-name{font-size:.85rem}}.esh-identity-image{display:inline-block}.esh-identity-drop{background:#fff;height:10px;width:10rem;overflow:hidden;padding:.5rem;position:absolute;right:0;top:2.5rem;transition:height .35s}.esh-identity:hover .esh-identity-drop{border:1px solid #eee;height:14rem;transition:height .35s;z-index:10}.esh-identity-item{cursor:pointer;transition:color .35s}.esh-identity-item:hover{color:#75b918;transition:color .35s}.esh-pager-wrapper{padding-top:1rem;text-align:center}.esh-pager-item{margin:0 5vw}.esh-pager-item.is-disabled{opacity:.5;pointer-events:none}.esh-pager-item--navigable{cursor:pointer;display:inline-block}.esh-pager-item--navigable:hover{color:#83d01b}@media screen and (max-width:1280px){.esh-pager-item{font-size:.85rem}}@media screen and (max-width:1024px){.esh-pager-item{margin:0 2.5vw}}.esh-basket{min-height:80vh}.esh-basket-titles{padding-bottom:1rem;padding-top:2rem}.esh-basket-titles--clean{padding-bottom:0;padding-top:0}.esh-basket-title{text-transform:uppercase}.esh-basket-items--border{border-bottom:1px solid #eee;padding:.5rem 0}.esh-basket-items--border:last-of-type{border-color:transparent}.esh-basket-items-margin-left1{margin-left:1px}.esh-basket-item{font-size:1rem;font-weight:300}.esh-basket-item--middle{line-height:8rem}@media screen and (max-width:1024px){.esh-basket-item--middle{line-height:1rem}}.esh-basket-item--mark{color:#00a69c}.esh-basket-image{height:8rem}.esh-basket-input{line-height:1rem;width:100%}.esh-basket-checkout{background-color:#83d01b;border:0;border-radius:0;color:#fff;display:inline-block;font-size:1rem;font-weight:400;margin-top:1rem;padding:1rem 1.5rem;text-align:center;text-transform:uppercase;transition:all .35s}.esh-basket-checkout:hover{background-color:#4a760f;transition:all .35s}.esh-basket-checkout:visited{color:#fff}.esh-basketstatus{cursor:pointer;display:inline-block;float:right;position:relative;transition:all .35s}.esh-basketstatus.is-disabled{opacity:.5;pointer-events:none}.esh-basketstatus-image{height:36px;margin-top:.5rem}.esh-basketstatus-badge{background-color:#83d01b;border-radius:50%;color:#fff;display:block;height:1.5rem;left:50%;position:absolute;text-align:center;top:0;transform:translateX(-38%);transition:all .35s;width:1.5rem}.esh-basketstatus-badge-inoperative{background-color:#f00;border-radius:50%;color:#fff;display:block;height:1.5rem;left:50%;position:absolute;text-align:center;top:0;transform:translateX(-38%);transition:all .35s;width:1.5rem}.esh-basketstatus:hover .esh-basketstatus-badge{background-color:transparent;color:#75b918;transition:all .35s}.esh-catalog-hero{background-image:url("../images/main_banner.png");background-size:cover;height:260px;width:100%}.esh-catalog-title{position:relative;top:74.28571px}.esh-catalog-filters{background-color:#00a69c;height:65px}.esh-catalog-filter{-webkit-appearance:none;background-color:transparentLine truncated
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Reference in new issue
Block a user