diff --git a/src/Money.UI.Blazor/Pages/Account/Login.cshtml b/src/Money.UI.Blazor/Pages/Account/Login.cshtml
index 12b38d6a..f1959860 100644
--- a/src/Money.UI.Blazor/Pages/Account/Login.cshtml
+++ b/src/Money.UI.Blazor/Pages/Account/Login.cshtml
@@ -1 +1,48 @@
-@page "/account/login"
\ No newline at end of file
+@page "/account/login"
+@inherits LoginBase
+
+
+
+ You can sign in as demo user with demo password or register your own account.
+
+
+
+
+
+ @if (IsError)
+ {
+
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Money.UI.Blazor/Pages/Account/Login.cshtml.cs b/src/Money.UI.Blazor/Pages/Account/Login.cshtml.cs
new file mode 100644
index 00000000..1a78d54d
--- /dev/null
+++ b/src/Money.UI.Blazor/Pages/Account/Login.cshtml.cs
@@ -0,0 +1,43 @@
+using Microsoft.AspNetCore.Blazor.Components;
+using Money.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Money.Pages
+{
+ public class LoginBase : BlazorComponent
+ {
+ [Inject]
+ internal Navigator Navigator { get; set; }
+
+ [Inject]
+ internal ApiClient ApiClient { get; set; }
+
+ protected string UserName { get; set; }
+ protected string Password { get; set; }
+ protected bool IsPermanent { get; set; }
+
+ protected bool IsError { get; set; }
+
+ protected Task OnSubmitAsync()
+ => LoginAsync(UserName, Password, IsPermanent);
+
+ protected Task OnDemoSubmitAsync()
+ => LoginAsync("demo", "demo", false);
+
+ private async Task LoginAsync(string userName, string password, bool isPermanent)
+ {
+ IsError = false;
+
+ string token = await ApiClient.LoginAsync(userName, password, isPermanent);
+ if (string.IsNullOrEmpty(token))
+ {
+ IsError = true;
+ return;
+ }
+ }
+ }
+}
diff --git a/src/Money.UI.Blazor/Services/ApiClient.cs b/src/Money.UI.Blazor/Services/ApiClient.cs
index 01641aa9..0f419229 100644
--- a/src/Money.UI.Blazor/Services/ApiClient.cs
+++ b/src/Money.UI.Blazor/Services/ApiClient.cs
@@ -34,6 +34,11 @@ public ApiClient(HttpClient http, CommandMapper commandMapper, QueryMapper query
//http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGVtbyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWVpZGVudGlmaWVyIjoiMjhmNGQxNzYtNjg5ZS00ZDRkLTlhMzgtYTg3MGQ5NzFhZDc5IiwiZXhwIjoxNTUyNzI2NDU2LCJpc3MiOiJodHRwczovL2xvY2FsaG9zdCIsImF1ZCI6Imh0dHBzOi8vbG9jYWxob3N0In0.4tSJlngLynld3Ul_HuicpO4zUERjYZ4FFjTrJxfE8Po");
}
+ public Task LoginAsync(string userName, string password, bool isPermanent)
+ {
+ throw new NotImplementedException();
+ }
+
private Request CreateRequest(Type type, string payload)
=> new Request() { Type = type.AssemblyQualifiedName, Payload = payload };
diff --git a/src/Money.UI.Blazor/Services/Navigator.cs b/src/Money.UI.Blazor/Services/Navigator.cs
index 62263fc3..cb9f98f6 100644
--- a/src/Money.UI.Blazor/Services/Navigator.cs
+++ b/src/Money.UI.Blazor/Services/Navigator.cs
@@ -67,6 +67,9 @@ public void OpenUserPassword()
=> uri.NavigateTo(UrlUserPassword());
public void OpenLogin()
- => uri.NavigateTo("/account/login");
+ => uri.NavigateTo(UrlAccountLogin());
+
+ public void OpenRegister()
+ => uri.NavigateTo(UrlAccountRegister());
}
}
diff --git a/src/Money.UI.Blazor/Services/NavigatorUrl.cs b/src/Money.UI.Blazor/Services/NavigatorUrl.cs
index f0b2bf16..1ea2b88e 100644
--- a/src/Money.UI.Blazor/Services/NavigatorUrl.cs
+++ b/src/Money.UI.Blazor/Services/NavigatorUrl.cs
@@ -45,6 +45,12 @@ public string UrlUserManage()
public string UrlUserPassword()
=> "/user/changepassword";
+ public string UrlAccountLogin()
+ => "/account/login";
+
+ public string UrlAccountRegister()
+ => "/account/register";
+
#region External
public string UrlMoneyProject()
diff --git a/src/Money.UI.Blazor/wwwroot/css/site.min.css b/src/Money.UI.Blazor/wwwroot/css/site.min.css
index 885c5da3..f78dc835 100644
--- a/src/Money.UI.Blazor/wwwroot/css/site.min.css
+++ b/src/Money.UI.Blazor/wwwroot/css/site.min.css
@@ -1 +1 @@
-@charset "UTF-8";.clear{clear:both;}body{min-width:380px;padding-top:50px;padding-bottom:20px;}h4{margin-bottom:20px;}.navbar{background-color:#0078d7;border-color:#398bf5;}.navbar .navbar-collapse{border-color:#398bf5;}.navbar .navbar-toggle,.navbar .navbar-toggle:focus,.navbar .navbar-toggle:hover{background-color:#0078d7;border-color:#398bf5;}.navbar .navbar-nav>li>a,.navbar .navbar-nav>li>button{color:#bcdbff;cursor:pointer;}@media(max-width:767px){.navbar .navbar-nav>.open ul.dropdown-menu>li>a{color:#bcdbff;}}.navbar .navbar-nav>.open>a,.navbar .navbar-nav>.open>a:hover{background:#245a9d;}.navbar .navbar-nav>li>button:hover{text-decoration:none;}.navbar a.navbar-brand{padding-left:50px;color:#fff;background:url("../images/logo.png") no-repeat left center;}@media(max-width:767px){.navbar a.navbar-brand{margin-left:10px;}}.nav-tabs>li>a:hover{cursor:pointer;}.nav-tabs>li.active>a:hover{cursor:default;}.header{position:absolute;width:100%;min-width:380px;left:0;background:#f5f5f5;border-bottom:1px solid #ddd;}.header .icon{font-size:26px;color:#0078d7;}.header h2 span.text{position:relative;top:3px;display:inline-block;overflow:hidden;max-width:calc(100% - 177px);text-overflow:ellipsis;white-space:nowrap;}.header h2 button{float:right;}.header h4{width:100%;margin-bottom:20px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;}.header-append{margin-bottom:130px;}.center{text-align:center;}.gray{opacity:.7;}.alert .navbar-nav{margin-top:-15px;}.alert .navbar-nav .btn-link{color:#333;}@media(max-width:768px){.alert .navbar-right{margin:0 -10px;}}.btn-icon{width:48px;height:48px;font-size:1.6em;padding:0;margin:4px;}.btn-color{width:48px;height:48px;margin:4px;}.btn-selectable{border-radius:4px;border:2px solid transparent;}.btn-selectable:focus,.btn-selectable:hover{text-decoration:none;}.btn-selectable.btn-selectable-selected,.btn-selectable:focus,.btn-selectable:hover{position:relative;outline:none;border-color:#000;}.btn-selectable.btn-selectable-selected::before,.btn-selectable:focus::before,.btn-selectable:hover::before{content:" ";content:"✓";padding:2px;background:#000;border-radius:0 0 4px 0;position:absolute;left:0;top:0;color:#fff;font-size:11px;}.panel-body .navbar-nav{margin-top:-15px;margin-bottom:-15px;}.panel-body p:last-child{margin:0;}.sort a{cursor:pointer;}.summary .sort{float:right;}.summary .sort .btn{border-color:transparent;}.summary .months{padding-right:70px;}.summary .graph{margin-bottom:-20px;}.bar-graph{margin:0;border-width:1px 0 0 0;box-shadow:none;cursor:pointer;}.bar-graph .panel-body{position:relative;height:60px;}.bar-graph .description{position:absolute;margin:0;font-weight:normal;display:inline;z-index:1;}.bar-graph .description .name{font-size:16px;white-space:nowrap;}.bar-graph .description .icon{display:inline-block;width:34px;text-align:center;}.bar-graph .value{position:absolute;width:calc(100% - 30px);}.bar-graph .amount{float:right;}.bar-graph .bar{height:10px;float:right;clear:both;transition:width 1s;}.bar-graph:hover{background-color:#f5f5f5;}.bar-graph-summary{border:none;}.bar-graph-summary .glyphicon{margin:0 4px;}.bar-graph-summary .category-name{font-weight:bold;}.bar-graph-summary .amount{font-weight:bold;}.overview{max-width:900px;margin:0 auto;}.overview .sort{float:right;margin-right:35px;}.search{max-width:900px;margin:0 auto;}.search .controls{display:none;}.cards{margin:20px 0;}.card{padding:30px;border-bottom:1px solid #eee;}.card:first-child{border-top:1px solid #eee;}.card:hover{background:#fcfcfc;}.card .data{float:left;}.card .controls{float:right;}.card .amount{margin-top:0;}.card .category{margin-bottom:0;}.splash{margin-top:-50px;height:350px;background:#0078d7;}.splash .background{position:absolute;left:0;top:0;width:100%;height:350px;opacity:.5;background:url("../images/city.png") no-repeat bottom center;background-size:contain;}.splash .head-content{position:relative;padding-top:50px;text-align:center;color:#fff;}.splash .head-content img{width:60px;height:60px;}.splash .head-content h1{font-size:50px;}.splash .head-content h2{font-size:25px;}.loading-bar{display:inline-block;position:relative;width:64px;height:84px;}.loading-bar div{display:inline-block;position:absolute;left:6px;width:13px;background:#193f6f;animation:loading-bar 1.2s cubic-bezier(0,.5,.5,1) infinite;}.loading-bar div:nth-child(1){left:6px;animation-delay:-.24s;}.loading-bar div:nth-child(2){left:26px;animation-delay:-.12s;}.loading-bar div:nth-child(3){left:45px;animation-delay:0;}@keyframes loading-bar{0%{top:6px;height:71px;}50%,100%{top:19px;height:26px;}}.loading{position:relative;}.loading .mask{position:absolute;left:0;top:0;width:100%;height:100%;display:none;opacity:.9;background:#fff;}.loading-active .mask{display:block;}.pager{margin:20px 0 40px 0;}.pager a{cursor:pointer;}.pager li{display:inline-block;}.pager .current{margin:0 16px;}.user{margin:20px 15px;}
\ No newline at end of file
+@charset "UTF-8";.clear{clear:both;}body{min-width:380px;padding-top:50px;padding-bottom:20px;}h4{margin-bottom:20px;}.navbar{background-color:#0078d7;border-color:#398bf5;}.navbar .navbar-collapse{border-color:#398bf5;}.navbar .navbar-toggle,.navbar .navbar-toggle:focus,.navbar .navbar-toggle:hover{background-color:#0078d7;border-color:#398bf5;}.navbar .navbar-nav>li>a,.navbar .navbar-nav>li>button{color:#bcdbff;cursor:pointer;}@media(max-width:767px){.navbar .navbar-nav>.open ul.dropdown-menu>li>a{color:#bcdbff;}}.navbar .navbar-nav>.open>a,.navbar .navbar-nav>.open>a:hover{background:#245a9d;}.navbar .navbar-nav>li>button:hover{text-decoration:none;}.navbar a.navbar-brand{padding-left:50px;color:#fff;background:url("../images/logo.png") no-repeat left center;}@media(max-width:767px){.navbar a.navbar-brand{margin-left:10px;}}.nav-tabs>li>a:hover{cursor:pointer;}.nav-tabs>li.active>a:hover{cursor:default;}.header{position:absolute;width:100%;min-width:380px;left:0;background:#f5f5f5;border-bottom:1px solid #ddd;}.header .icon{font-size:26px;color:#0078d7;}.header h2 span.text{position:relative;top:3px;display:inline-block;overflow:hidden;max-width:calc(100% - 177px);text-overflow:ellipsis;white-space:nowrap;}.header h2 button{float:right;}.header h4{width:100%;margin-bottom:20px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;}.header-append{margin-bottom:130px;}.center{text-align:center;}.gray{opacity:.7;}.alert .navbar-nav{margin-top:-15px;}.alert .navbar-nav .btn-link{color:#333;}@media(max-width:768px){.alert .navbar-right{margin:0 -10px;}}.btn-icon{width:48px;height:48px;font-size:1.6em;padding:0;margin:4px;}.btn-color{width:48px;height:48px;margin:4px;}.btn-selectable{border-radius:4px;border:2px solid transparent;}.btn-selectable:focus,.btn-selectable:hover{text-decoration:none;}.btn-selectable.btn-selectable-selected,.btn-selectable:focus,.btn-selectable:hover{position:relative;outline:none;border-color:#000;}.btn-selectable.btn-selectable-selected::before,.btn-selectable:focus::before,.btn-selectable:hover::before{content:" ";content:"✓";padding:2px;background:#000;border-radius:0 0 4px 0;position:absolute;left:0;top:0;color:#fff;font-size:11px;}.panel-body .navbar-nav{margin-top:-15px;margin-bottom:-15px;}.panel-body p:last-child{margin:0;}.sort a{cursor:pointer;}.summary .sort{float:right;}.summary .sort .btn{border-color:transparent;}.summary .months{padding-right:70px;}.summary .graph{margin-bottom:-20px;}.bar-graph{margin:0;border-width:1px 0 0 0;box-shadow:none;cursor:pointer;}.bar-graph .panel-body{position:relative;height:60px;}.bar-graph .description{position:absolute;margin:0;font-weight:normal;display:inline;z-index:1;}.bar-graph .description .name{font-size:16px;white-space:nowrap;}.bar-graph .description .icon{display:inline-block;width:34px;text-align:center;}.bar-graph .value{position:absolute;width:calc(100% - 30px);}.bar-graph .amount{float:right;}.bar-graph .bar{height:10px;float:right;clear:both;transition:width 1s;}.bar-graph:hover{background-color:#f5f5f5;}.bar-graph-summary{border:none;}.bar-graph-summary .glyphicon{margin:0 4px;}.bar-graph-summary .category-name{font-weight:bold;}.bar-graph-summary .amount{font-weight:bold;}.overview{max-width:900px;margin:0 auto;}.overview .sort{float:right;margin-right:35px;}.search{max-width:900px;margin:0 auto;}.search .controls{display:none;}.cards{margin:20px 0;}.card{padding:30px;border-bottom:1px solid #eee;}.card:first-child{border-top:1px solid #eee;}.card:hover{background:#fcfcfc;}.card .data{float:left;}.card .controls{float:right;}.card .amount{margin-top:0;}.card .category{margin-bottom:0;}.splash{margin-top:-50px;height:350px;background:#0078d7;}.splash .background{position:absolute;left:0;top:0;width:100%;height:350px;opacity:.5;background:url("../images/city.png") no-repeat bottom center;background-size:contain;}.splash .head-content{position:relative;padding-top:50px;text-align:center;color:#fff;}.splash .head-content img{width:60px;height:60px;}.splash .head-content h1{font-size:50px;}.splash .head-content h2{font-size:25px;}.loading-bar{display:inline-block;position:relative;width:64px;height:84px;}.loading-bar div{display:inline-block;position:absolute;left:6px;width:13px;background:#193f6f;animation:loading-bar 1.2s cubic-bezier(0,.5,.5,1) infinite;}.loading-bar div:nth-child(1){left:6px;animation-delay:-.24s;}.loading-bar div:nth-child(2){left:26px;animation-delay:-.12s;}.loading-bar div:nth-child(3){left:45px;animation-delay:0;}@keyframes loading-bar{0%{top:6px;height:71px;}50%,100%{top:19px;height:26px;}}.loading{position:relative;}.loading .mask{position:absolute;left:0;top:0;width:100%;height:100%;display:none;opacity:.9;background:#fff;}.loading-active .mask{display:block;}.pager{margin:20px 0 40px 0;}.pager a{cursor:pointer;}.pager li{display:inline-block;}.pager .current{margin:0 16px;}.user{margin:20px 15px;}.login{margin-top:20px;}
\ No newline at end of file
diff --git a/src/Money.UI.Blazor/wwwroot/css/site.scss b/src/Money.UI.Blazor/wwwroot/css/site.scss
index 9988298b..809a9480 100644
--- a/src/Money.UI.Blazor/wwwroot/css/site.scss
+++ b/src/Money.UI.Blazor/wwwroot/css/site.scss
@@ -470,4 +470,8 @@ h4 {
.user {
margin: 20px 15px;
+}
+
+.login {
+ margin-top: 20px;
}
\ No newline at end of file