Before separating auth

This commit is contained in:
Wvader 2022-09-26 02:05:23 +01:00
parent 058b75193b
commit 3e1555d052
76 changed files with 1190 additions and 185 deletions

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3"/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,32 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Authorization.Controllers;
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}

View File

@ -0,0 +1,25 @@
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@ -0,0 +1,31 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:23917",
"sslPort": 44315
}
},
"profiles": {
"BlueWest.Authorization": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7246;http://localhost:5269",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,12 @@
namespace BlueWest.Authorization;
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}

View File

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

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<SupportedPlatform Include="browser"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.3"/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,3 @@
<div class="my-component">
This component is defined in the <strong>BlueWest.Razor.Library</strong> library.
</div>

View File

@ -0,0 +1,6 @@
.my-component {
border: 2px dashed red;
padding: 1em;
margin: 1em 0;
background-image: url('background.png');
}

View File

@ -0,0 +1,36 @@
using Microsoft.JSInterop;
namespace BlueWest.Razor.Library;
// This class provides an example of how JavaScript functionality can be wrapped
// in a .NET class for easy consumption. The associated JavaScript module is
// loaded on demand when first needed.
//
// This class can be registered as scoped DI service and then injected into Blazor
// components for use.
public class ExampleJsInterop : IAsyncDisposable
{
private readonly Lazy<Task<IJSObjectReference>> moduleTask;
public ExampleJsInterop(IJSRuntime jsRuntime)
{
moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
"import", "./_content/BlueWest.Razor.Library/exampleJsInterop.js").AsTask());
}
public async ValueTask<string> Prompt(string message)
{
var module = await moduleTask.Value;
return await module.InvokeAsync<string>("showPrompt", message);
}
public async ValueTask DisposeAsync()
{
if (moduleTask.IsValueCreated)
{
var module = await moduleTask.Value;
await module.DisposeAsync();
}
}
}

View File

@ -0,0 +1 @@
@using Microsoft.AspNetCore.Components.Web

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 B

View File

@ -0,0 +1,6 @@
// This is a JavaScript module that is loaded on demand. It can export any number of
// functions, and may import other JavaScript modules if required.
export function showPrompt(message) {
return prompt(message, 'Type anything here');
}

View File

@ -8,6 +8,10 @@
<RootNamespace>BlueWest.Views</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BlueWest.Domain\BlueWest.Domain.csproj" />
</ItemGroup>
@ -58,6 +62,37 @@
<_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.min.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.min.js.map" />
<_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\LICENSE" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation-unobtrusive\jquery.validate.unobtrusive.min.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation-unobtrusive\LICENSE.txt" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation\dist\additional-methods.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation\dist\additional-methods.min.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation\dist\jquery.validate.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation\dist\jquery.validate.min.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery-validation\LICENSE.md" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\dist\jquery.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\dist\jquery.min.js" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\dist\jquery.min.map" />
<_ContentIncludedByDefault Remove="wwwroot\lib\jquery\LICENSE.txt" />
<_ContentIncludedByDefault Remove="Views\Data\Roles\Index.cshtml" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Views\Jobs\Index.cshtml" />
</ItemGroup>
<ItemGroup>
<None Include="Web.config">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Compile Remove="Controllers\RolesController.cs" />
<Compile Remove="Controllers\LogsController.cs" />
<Compile Remove="Controllers\DataController.cs" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers
{
public class AuthController : Controller
{
}
}

View File

@ -1,24 +0,0 @@
using System.Diagnostics;
using BlueWest.Views.Models;
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers
{
public class CapitalController : Controller
{
public IActionResult Index()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
}
}
}

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers.Data;
public class BanksController : Controller
{
// GET
public IActionResult Index()
{
return View();
}
}

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers;
public class CompaniesController : Controller
{
// GET
public IActionResult Index()
{
return View("../Data/Companies/Index");
}
}

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers;
public class CountriesController : Controller
{
// GET
public IActionResult Index()
{
return View("../Data/Countries/Index");
}
}

View File

@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers;
public class CurrenciesController : Controller
{
}

View File

@ -0,0 +1,17 @@
using BlueWest.Views.Utils;
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers
{
public class DataController : Controller
{
public IActionResult Index()
{
this.HandleGlobalization();
ViewData[FooterMenuId] = LayoutCache.DataRoute.Children;
return View();
}
}
}

View File

@ -1,31 +1,24 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using BlueWest.Views.Models;
using Microsoft.AspNetCore.Mvc;
using BlueWest.Views.Utils;
using Microsoft.Extensions.Options;
using Controller = Microsoft.AspNetCore.Mvc.Controller;
namespace BlueWest.Views.Controllers;
[System.Web.Mvc.Route("/")]
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
public HomeController(ILogger<HomeController> logger, IOptions<RequestLocalizationOptions> options)
{
_logger = logger;
}
public IActionResult Index()
{
this.HandleGlobalization();
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
}
}

View File

@ -0,0 +1,33 @@
using System.Diagnostics;
using System.Web.Mvc;
using Microsoft.AspNetCore.Mvc;
using BlueWest.Views.Models;
using BlueWest.Views.Utils;
using Controller = Microsoft.AspNetCore.Mvc.Controller;
namespace BlueWest.Views.Controllers;
public class JobsController : Controller
{
private readonly ILogger<JobsController> _logger;
public JobsController(ILogger<JobsController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
this.HandleGlobalization();
ViewData["Title"] = "Home Page";
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
}
}

View File

@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers;
public class ApplicationUsersController : Controller
{
}

View File

@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers;
public class DataUsersController : Controller
{
}

View File

@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers;
public class LogsController : Controller
{
}

View File

@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers;
[System.Web.Mvc.Route($"{SystemRouteLocation}/roles")]
public class RolesController : Controller
{
// GET
public IActionResult Index()
{
return View("../System/Roles/Index");
}
}

View File

@ -1,3 +1,4 @@
using BlueWest.Views.Utils;
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers
@ -14,6 +15,8 @@ namespace BlueWest.Views.Controllers
public IActionResult Index()
{
this.HandleGlobalization();
ViewData[FooterMenuId] = LayoutCache.SystemRoute.Children;
return View();
}
@ -21,15 +24,6 @@ namespace BlueWest.Views.Controllers
{
return View();
}
public IActionResult Roles()
{
return View();
}
}
}

View File

@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Controllers;
public class UsersController : Controller
{
}

View File

@ -0,0 +1,3 @@
// Global using directives
global using static BlueWest.Views.Utils.Routes;

View File

@ -0,0 +1,9 @@
using System.Globalization;
namespace BlueWest.Localization.Models;
public class CultureSwitch
{
public CultureInfo CurrentUICulture { get; set; }
public List<CultureInfo> SupportedCultures { get; set; }
}

View File

@ -0,0 +1,27 @@
using BlueWest.Localization.Models;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.Extensions.Options;
namespace BlueWest.Views.Localization.ViewComponents;
public class CultureSwitchViewComponent : ViewComponent
{
private readonly IOptions<RequestLocalizationOptions> localizationOptions;
public CultureSwitchViewComponent(IOptions<RequestLocalizationOptions> localizationOptions) =>
this.localizationOptions = localizationOptions;
// public IViewComponentResult Invoke()
// {
// var cultureFeature = HttpContext.Features.Get<IRequestCultureFeature>();
// var model = new CultureSwitch()
// {
// SupportedCultures = localizationOptions.Value.SupportedUICultures.ToList(),
// CurrentUICulture = cultureFeature.RequestCulture.UICulture
// };
// return View(model);
// }
}

View File

@ -1,8 +0,0 @@
namespace BlueWest.Views.Models
{
public class SystemPageModel
{
}
}

View File

@ -1,10 +0,0 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace BlueWest.Views.Models
{
public class UserPageModel : PageModel
{
}
}

View File

@ -1,6 +1,26 @@
using BlueWest.Views.Utils;
using System.Globalization;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<LayoutCache>();
// Add services to the container.
builder.Services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(cookieOptions => {
cookieOptions.LoginPath = "/";
});
builder.Services.AddControllersWithViews();
var app = builder.Build();
@ -18,6 +38,14 @@ app.UseStaticFiles();
app.UseRouting();
app.UseRequestLocalization(options =>
{
var supportedCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
options.DefaultRequestCulture = new RequestCulture("en-GB");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
app.UseAuthorization();
app.MapControllerRoute(

View File

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
namespace BlueWest.Views.Utils;
public static class ControllerExtensions
{
public static void HandleGlobalization(this Controller controller)
{
var context = controller.HttpContext;
var requestCultureFeature = context.Features.Get<IRequestCultureFeature>();
var currentCultureName = Routes.DefaultCultureName;
if (requestCultureFeature != null)
{
currentCultureName = requestCultureFeature.RequestCulture.Culture.Name;
}
controller.ViewData[LanguageViewStorage] = currentCultureName;
}
public static void HandlePageName(this Controller controller, string location)
{
}
}

View File

@ -0,0 +1,180 @@
using BlueWest.Views.Controllers;
using BlueWest.Views.Controllers.Data;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace BlueWest.Views.Utils;
internal class LayoutCache
{
#region Route Tree
private static readonly RouteRecord Root = new RouteRecord(
RootKeyName,
RootLocation,
nameof(HomeController),
new List<RouteRecord>()
{
new RouteRecord(
DataKeyName,
DataLocation,
nameof(DataController),
new List<RouteRecord>()
{
new RouteRecord(
CompaniesKeyName,
CompaniesLocation,
nameof(CompaniesController),
new List<RouteRecord>()
),
new RouteRecord(
CountriesKeyName,
CountriesLocation,
nameof(CountriesController),
new List<RouteRecord>()
),
new RouteRecord(
CurrenciesKeyName,
CurrenciesLocation,
nameof(CurrenciesController),
new List<RouteRecord>()
),
new RouteRecord(
BanksKeyName,
BanksLocation,
nameof(BanksController),
new List<RouteRecord>()
),
new RouteRecord(
DataUsersKeyName,
DataUsersLocation,
nameof(DataUsersController),
new List<RouteRecord>()
),
},
ViewType.Data
),
new RouteRecord(
SystemKeyName,
SystemRouteLocation,
nameof(SystemController),
new List<RouteRecord>()
{
new RouteRecord(
RolesKeyName,
RolesLocation,
nameof(RolesController),
new List<RouteRecord>()
),
new RouteRecord(
ApplicationUsersKeyName,
ApplicationUsersLocation,
nameof(ApplicationUsersController),
new List<RouteRecord>()
),
new RouteRecord(
LogsKeyName,
LogsLocation,
nameof(LogsController),
new List<RouteRecord>()
)
},
ViewType.System
),
new RouteRecord(
JobsKeyName,
JobsRouteLocation,
nameof(JobsController),
new List<RouteRecord>(),
ViewType.Jobs
),
}, ViewType.Root);
#endregion Route Tree
#region Routing Utils
internal static readonly RouteRecord SystemRoute =
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.System)!;
internal static readonly RouteRecord DataRoute =
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.Data)!;
internal static readonly RouteRecord JobRoute =
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.Jobs)!;
internal static readonly RouteRecord ProfileRoute =
Root.Children.FirstOrDefault(x => x.ViewType == ViewType.Profile)!;
#endregion Routing Utils
#region Internal Menus
internal static List<RouteView> GetDefaultFooterMenu(ViewDataDictionary dictionary)
{
var location = GetLocation(dictionary);
var menu = LayoutCache
.Root
.Children;
if (dictionary[FooterMenuId] is List<RouteRecord> footerMenu)
{
menu = footerMenu;
}
return menu
.Select(x =>
{
if (Translation[x.routeKey].ContainsKey(location))
{
return new RouteView(Translation[x.routeKey][location],
location);
}
return new RouteView(Translation[x.routeKey][DefaultCultureName],
x.location);
})
.ToList();
}
internal static List<RouteView> GetDefaultHeaderMenu(ViewDataDictionary dictionary)
{
var location = GetLocation(dictionary);
var menu = LayoutCache
.Root
.Children;
if (dictionary[HeaderMenuId] is List<RouteRecord> footerMenu)
{
menu = footerMenu;
}
return menu
.Select(x =>
{
if (Translation[x.routeKey].ContainsKey(location))
{
return new RouteView(Translation[x.routeKey][location],
x.Location);
}
return new RouteView(Translation[x.routeKey][DefaultCultureName],
x.location);
})
.ToList();
}
internal static string GetLocation(ViewDataDictionary dictionary)
{
return (dictionary[LanguageViewStorage] as string)!;
}
#endregion Internal Menus
}

View File

@ -0,0 +1,13 @@
namespace BlueWest.Views.Utils;
public record LinkViewInformation
{
public string Location;
public string Name;
public LinkViewInformation(LinkViewInformation linkInformation)
{
Location = linkInformation.Location;
Name = linkInformation.Name;
}
}

View File

@ -0,0 +1,7 @@
namespace BlueWest.Views.Utils.Static;
public static class Menus
{
internal const string FooterMenuId = "m1";
internal const string HeaderMenuId = "m2";
}

View File

@ -0,0 +1,14 @@
namespace BlueWest.Views.Utils
{
public record RouteRecord(string routeKey, string location, string controllerName, List<RouteRecord> children, ViewType viewType = ViewType.Undefined)
{
public string RouteKey = routeKey;
public string Location = location;
public string ControllerName;
public List<RouteRecord> Children = children;
public ViewType ViewType = viewType;
}
public record RouteView(string Name, string Location);
}

View File

@ -0,0 +1,190 @@
using System.Collections.Immutable;
namespace BlueWest.Views.Utils
{
internal static class Routes
{
public const string DefaultCultureName = "en-gb";
#region Layout Keys
internal const string FooterMenuId = "m1";
internal const string HeaderMenuId = "m2";
internal const string LanguageViewStorage = "i80";
#endregion Layout Keys
#region Route Keys
internal const string DataKeyName = "data";
internal const string RootKeyName = "root";
internal const string RootLocation = "/";
internal const string SystemKeyName = "system";
internal const string RolesKeyName = "roles";
internal const string CompaniesKeyName = "companies";
internal const string CountriesKeyName = "countries";
internal const string CurrenciesKeyName = "currencies";
internal const string IndustriesKeyName = "industries";
internal const string DataUsersKeyName = "users";
internal const string BanksKeyName = "banks";
internal const string JobsKeyName = "jobs";
internal const string SettingsKeyName = "settings";
internal const string LogsKeyName = "logs";
internal const string ApplicationUsersKeyName = "app_users";
#endregion Route Keys
// Translation Database Keys
#region Routes Data
// Routes
internal const string RolesLocation = $"{SystemRouteLocation}/roles";
internal const string ApplicationUsersLocation = $"{SystemRouteLocation}/users";
internal const string LogsLocation = $"{SystemRouteLocation}/logs";
internal const string SettingsRouteLocation = $"{SystemRouteLocation}/settings";
internal const string DataLocation = $"/data";
// Banks
// Data users
internal const string DataUsersLocation = "/data/users";
internal const string JobsRouteLocation = "/jobs";
internal const string SystemRouteLocation = $"/system";
internal const string BanksLocation = $"{DataLocation}/banks";
internal const string CountriesLocation = $"{DataLocation}/countries";
internal const string CurrenciesLocation = $"{DataLocation}/currencies";
internal const string CompaniesLocation = $"{DataLocation}/companies";
internal const string IndustriesLocation = $"{DataLocation}/industries";
#endregion Routes Data
internal static Dictionary<string, Dictionary<string, string>> Translation =
new Dictionary<string, Dictionary<string, string>>
{
{
RootKeyName, new Dictionary<string, string>()
{
{"pt", "Inicio"},
{"eng", "Home"},
{"en-gb", "Home"}
}
},
{
SystemKeyName, new Dictionary<string, string>()
{
{"pt", "Sistema"},
{"eng", "System"},
{"en-gb", "System"},
}
},
{
DataKeyName, new Dictionary<string, string>()
{
{"pt", "Dados"},
{"eng", "Data"},
{"en-gb", "Data"}
}
},
{
RolesKeyName, new Dictionary<string, string>()
{
{"pt", "Tipos de Utilizador"},
{"en-gb", "Roles"},
{"eng", "Roles"}
}
},
{
ApplicationUsersKeyName, new Dictionary<string, string>()
{
{"pt", "Utilizadores da Aplicação"},
{"en-gb", "Users"},
{"eng", "Users"}
}
},
{
LogsKeyName, new Dictionary<string, string>()
{
{"pt", "Logs"},
{"en-gb", "logs"},
{"eng", "logs"}
}
},
{
SettingsKeyName, new Dictionary<string, string>()
{
{"pt", "Personalização"},
{"eng", "Settings"},
{"en-gb", "Settings"},
}
},
{
CompaniesKeyName, new Dictionary<string, string>()
{
{"pt", "Empresas"},
{"eng", "Companies"},
{"en-gb", "Companies"},
}
},
{
IndustriesKeyName, new Dictionary<string, string>()
{
{"pt", "Indústrias"},
{"en-gb", "Industries"},
{"eng", "Industries"},
}
},
{
CurrenciesKeyName, new Dictionary<string, string>()
{
{"pt", "Moedas"},
{"en-gb", "Currencies"},
{"eng", "Currencies"},
}
},
{
CountriesKeyName, new Dictionary<string, string>()
{
{"pt", "Países"},
{"eng", "Countries"},
{"en-gb", "Countries"}
}
},
{
BanksKeyName, new Dictionary<string, string>()
{
{"pt", "Bancos"},
{"eng", "Banks"},
{"en-gb", "Banks"},
}
},
{
DataUsersKeyName, new Dictionary<string, string>()
{
{"pt", "Utilizadores"},
{"eng", "Users"},
{"en-gb", "Users"},
}
},
{
JobsKeyName, new Dictionary<string, string>()
{
{"pt", "Anúncios de trabalho"},
{"eng", "Jobs"},
{"en-gb", "Jobs"},
}
},
};
}
}

View File

@ -0,0 +1,16 @@
using System.Collections.Immutable;
namespace BlueWest.Views
{
public enum ViewType
{
System,
Data,
Jobs,
Profile,
Root,
Undefined
}
}

View File

@ -0,0 +1,18 @@
@model dynamic
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
<div>
</div>
</body>
</html>

View File

@ -1,8 +0,0 @@
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Capital</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

View File

@ -0,0 +1,11 @@
@using BlueWest.Views.Utils
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Companies Module</h1>
</div>
@Html.Partial("_FooterMenu");

View File

@ -0,0 +1,11 @@
@using BlueWest.Views.Utils
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Data Module</h1>
</div>
@Html.Partial("_FooterMenu");

View File

@ -0,0 +1,11 @@
@using BlueWest.Views.Utils
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Data Module</h1>
</div>
@Html.Partial("_FooterMenu");

View File

@ -1,8 +1,32 @@
@{
@using Microsoft.AspNetCore.Localization
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
<table class="table culture-table">
<tr>
<td>Date</td>
<td>@DateTime.Now.ToLongDateString()</td>
</tr>
<tr>
<td>Currency</td>
<td>
@(12345.00.ToString("c"))
</td>
</tr>
<tr>
<td>Number</td>
<td>
@(123.45m.ToString("F2"))
</td>
</tr>
</table>
</div>

View File

@ -0,0 +1,10 @@
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Data Module</h1>
</div>
@Html.Partial("_FooterMenu");

View File

@ -0,0 +1,59 @@
<footer class="q-footer q-layout__section--marginal absolute-bottom q-footer--bordered text-secondary">
<div class="q-tabs row no-wrap items-center q-tabs--not-scrollable q-tabs--horizontal q-tabs__arrows--inside text-white">
<div class="q-tabs__content row no-wrap items-center self-stretch hide-scrollbar relative-position q-tabs__content--align-center">
<div style="margin-right: 1rem;">
<a href="/geo" class="router-link-active router-link-exact-active">
<i class="q-icon text-white notranslate material-icons" style="font-size: 24px;">data_usage</i>
</a>
</div>
<a href="/system/roles" class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-tab--no-caps q-focusable q-hoverable cursor-pointer">
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">Roles</div>
</div>
<div class="q-tab__indicator absolute-bottom text-transparent">
</div>
</a>
<a href="/data/countries"
class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-tab--no-caps q-focusable q-hoverable cursor-pointer">
<div class="q-focus-helper"></div>
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">Sessions</div>
</div>
<div class="q-tab__indicator absolute-bottom text-transparent"></div>
</a><!--<FooterMenuItem>-->
<a href="/data/currencies"
class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-tab--no-caps q-focusable q-hoverable cursor-pointer">
<div class="q-focus-helper"></div>
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">Settings</div>
</div>
<div class="q-tab__indicator absolute-bottom text-transparent"></div>
</a><!--<FooterMenuItem>-->
<a href="/data/banks"
class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-tab--no-caps q-focusable q-hoverable cursor-pointer">
<div class="q-focus-helper"></div>
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">Banks</div>
</div>
<div class="q-tab__indicator absolute-bottom text-transparent"></div>
</a><!--<FooterMenuItem>-->
<!--<FooterMenuItem>-->
<button class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-btn--dense s-7IPF32Wcq3s8"
type="button">
<span class="q-focus-helper s-7IPF32Wcq3s8"></span>
<span
class="q-btn__content text-center col items-center q-anchor--skip justify-center row s-7IPF32Wcq3s8">
<i
class="q-icon notranslate material-icons s-7IPF32Wcq3s8">
menu
</i>
</span>
</button>
</div>
</div>
</footer>

View File

@ -0,0 +1,31 @@
@using BlueWest.Views.Utils
@{
Layout = null;
var menu = LayoutCache.GetDefaultFooterMenu(ViewData);
}
<footer class="q-footer q-layout__section--marginal absolute-bottom q-footer--bordered text-secondary">
<div class="q-tabs row no-wrap items-center q-tabs--not-scrollable q-tabs--horizontal q-tabs__arrows--inside text-white">
<div class="q-tabs__content row no-wrap items-center self-stretch hide-scrollbar relative-position q-tabs__content--align-center">
<div style="margin-right: 1rem;">
<a href="/geo" class="router-link-active router-link-exact-active">
<i class="q-icon text-white notranslate material-icons" style="font-size: 24px;">data_usage</i>
</a>
</div>
@if (menu is {Count: > 0 })
{
@foreach (var record in menu)
{
<a href="@record.Location" class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-tab--no-caps q-focusable q-hoverable cursor-pointer">
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">@record.Name</div>
</div>
<div class="q-tab__indicator absolute-bottom text-transparent"></div>
</a>
}
}
</div>
</div>
</footer>

View File

@ -1 +1,23 @@
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">BlueWest.Views</a>
@using BlueWest.Views.Utils
@{
Layout = null;
var menu = LayoutCache.GetDefaultHeaderMenu(ViewData);
}
<div class="q-tabs items-center row no-wrap items-center q-tabs--not-scrollable q-tabs--horizontal q-tabs__arrows--inside">
<div class="q-tabs__content row no-wrap items-center self-stretch hide-scrollbar relative-position q-tabs__content--align-center">
@if (menu is {Count: > 0 })
{
@foreach (var record in menu)
{
<a class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-focusable q-hoverable cursor-pointer " href="@record.Location">
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">@record.Name</div>
</div>
<div class="q-tab__indicator absolute-bottom"></div>
</a>
}
}
</div>
</div>

View File

@ -5,70 +5,39 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>@ViewData["Title"] - BlueWest.Views</title>
<link rel="stylesheet" href="~/static/main.css"/>
@*
<link rel="stylesheet" href="~/BlueWest.Views.styles.css" asp-append-version="true"/>
*@
<link rel="preload" href="/static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff" as="font" type="font/woff" crossorigin>
<link rel="preload" href="/static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2" as="font" type="font/woff2" crossorigin>
<style>
@@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
font-display: block;
src: url("/static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2") format('woff2'), url('/static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff') format('woff');
src: url("static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2") format('woff2'), url('static/material-icons/web-font/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff') format('woff');
font-display: swap;
}
</style>
</head>
<body class="desktop touch body--dark" style="--q-primary:#414141;">
<div id="q-app">
@RenderBody()
<div class="q-layout q-layout--standard" id="app-entry">
<div class="wrap s-7IPF32Wcq3s8"><ul class="_toastContainer s-lp0GEKiD9Hz6">
</ul></div>
<div class="q-layout q-layout--standard s-7IPF32Wcq3s8" id="app-entry"><header class="q-header q-layout__section--marginal fixed-top bg-primary text-white s-7IPF32Wcq3s8"><div class="q-tabs row no-wrap items-center q-tabs--not-scrollable q-tabs--horizontal q-tabs__arrows--inside s-7IPF32Wcq3s8"><div class="q-tabs__content row no-wrap items-center self-stretch hide-scrollbar relative-position q-tabs__content--align-left s-7IPF32Wcq3s8"><div></div>
<a class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-focusable q-hoverable cursor-pointer " href="/system"><div class="q-focus-helper"></div>
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column"><div class="q-tab__label">System</div></div>
<div class="q-tab__indicator absolute-bottom"></div></a><div></div>
<a class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-focusable q-hoverable cursor-pointer " href="/capital"><div class="q-focus-helper"></div>
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column"><div class="q-tab__label">Capital</div></div>
<div class="q-tab__indicator absolute-bottom"></div></a></div>
</div>
<div class="q-layout__shadow absolute-full overflow-hidden no-pointer-events s-7IPF32Wcq3s8"></div></header>
<div class="q-drawer-container s-7IPF32Wcq3s8"><div class="q-drawer__opener fixed-right s-7IPF32Wcq3s8"></div>
<div class="fullscreen q-drawer__backdrop hidden s-7IPF32Wcq3s8" style="background-color: rgba(0, 0, 0, 0);"></div>
<aside class="q-drawer q-drawer--right q-drawer--bordered q-drawer--dark q-dark q-layout--prevent-focus fixed q-drawer--on-top q-drawer--mobile q-drawer--top-padding s-7IPF32Wcq3s8" style="width: 300px; transform: translateX(300px);"><div show-if="" class="q-drawer__content fit scroll s-7IPF32Wcq3s8"></div></aside></div>
<header class="q-header q-layout__section--marginal fixed-top bg-primary text-white">
@await Html.PartialAsync("_HeaderMenu")
</header>
<div class="q-page-container s-7IPF32Wcq3s8" style="padding-top: 48px; padding-bottom: 49px;">
@RenderBody()
<footer class="q-footer q-layout__section--marginal absolute-bottom q-footer--bordered text-secondary s-7IPF32Wcq3s8">
<div class="q-tabs row no-wrap items-center q-tabs--not-scrollable q-tabs--horizontal q-tabs__arrows--inside text-white s-7IPF32Wcq3s8">
<div class="q-tabs__content row no-wrap items-center self-stretch hide-scrollbar relative-position q-tabs__content--align-center s-7IPF32Wcq3s8">
<div style="margin-right: 1rem;" class="s-7IPF32Wcq3s8"><a href="#/geo" class="router-link-active router-link-exact-active s-7IPF32Wcq3s8"><i class="q-icon text-white notranslate material-icons s-7IPF32Wcq3s8" style="font-size: 24px;">data_usage</i></a></div>
<a href="/system" class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-tab--no-caps q-focusable q-hoverable cursor-pointer">
<div class="q-focus-helper"></div>
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">System</div></div>
<div class="q-tab__indicator absolute-bottom text-transparent"></div></a>
<a href="/system/users" class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-tab--no-caps q-focusable q-hoverable cursor-pointer">
<div class="q-focus-helper"></div>
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">Users</div></div>
<div class="q-tab__indicator absolute-bottom text-transparent"></div></a>
<a href="/system/roles" class="q-tab relative-position self-stretch flex flex-center text-center q-tab--inactive q-tab--no-caps q-focusable q-hoverable cursor-pointer">
<div class="q-focus-helper"></div>
<div class="q-tab__content self-stretch flex-center relative-position q-anchor--skip non-selectable column">
<div class="q-tab__label">Roles</div></div>
<div class="q-tab__indicator absolute-bottom text-transparent"></div></a>
<button class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-btn--dense s-7IPF32Wcq3s8" type="button"><span class="q-focus-helper s-7IPF32Wcq3s8"></span>
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row s-7IPF32Wcq3s8"><i class="q-icon notranslate material-icons s-7IPF32Wcq3s8">menu</i></span></button></div>
</div></footer>
</div>
<div class="q-page-container" style="padding-top: 48px; padding-bottom: 49px;">
<div class="app-body">
@RenderBody()
</div>
</div>
</div>
</div>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>

View File

@ -1,24 +1 @@

.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
}

View File

@ -1,8 +1,12 @@
@using BlueWest.Views.Utils
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">System</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
<h1 class="display-4">System Module</h1>
</div>
@await Html.PartialAsync("_FooterMenu");

View File

@ -1,8 +0,0 @@
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Roles</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

View File

@ -6,3 +6,5 @@
<h1 class="display-4">Users</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
@Html.Partial("~/Views/Shared/UsersMenu.cshtml");

View File

@ -1,3 +1,8 @@
@using BlueWest.Views
@using System.Globalization
@using BlueWest.Views
@using BlueWest.Views.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using BlueWest.Localization
@using BlueWest.Localization.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Localisation

14
BlueWest.Views/Web.config Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<httpRuntime />
</system.web>
<staticContent>
<mimeMap fileExtension="woff2" mimeType="application/font-woff" />
</staticContent>
<appSettings>
</appSettings>
</configuration>

View File

@ -1,18 +0,0 @@
html {
font-size: 14px;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
}
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: 60px;
}

View File

@ -1,4 +0,0 @@
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
// for details on configuring this project to bundle and minify static web assets.
// Write your JavaScript code.

View File

@ -1,4 +1,29 @@
.router-link-active {
text-decoration: none !important;
}
.material-icons {
font-family: 'Material Icons', "Roboto", "-apple-system", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: normal;
font-style: normal;
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
}
/* * Normalizing -- forked from Normalize.css v8
* */
*, *:before, *:after {
@ -2928,7 +2953,7 @@ body.mobile .q-textarea .q-field__native,
.q-layout {
width: 100%;
height: 99.8%;
height: 100%;
}
.q-layout-container {

View File

@ -41,6 +41,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlueWest.Views", "BlueWest.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlueWest.Domain", "BlueWest.Domain\BlueWest.Domain.csproj", "{1085FF6E-E568-441E-9A2D-23F50AB613AF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlueWest.Razor.Library", "BlueWest.Razor.Library\BlueWest.Razor.Library.csproj", "{CA6DF60F-B33E-4688-A4ED-4427B446E852}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -91,6 +93,10 @@ Global
{1085FF6E-E568-441E-9A2D-23F50AB613AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1085FF6E-E568-441E-9A2D-23F50AB613AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1085FF6E-E568-441E-9A2D-23F50AB613AF}.Release|Any CPU.Build.0 = Release|Any CPU
{CA6DF60F-B33E-4688-A4ED-4427B446E852}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA6DF60F-B33E-4688-A4ED-4427B446E852}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA6DF60F-B33E-4688-A4ED-4427B446E852}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA6DF60F-B33E-4688-A4ED-4427B446E852}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE