From 4aa15c531da8a7760ca84d3bcd712c1a7543181e Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 12 May 2020 09:55:28 +0100 Subject: [PATCH 01/44] Split create & recover wallet --- .../UI/Pages/WalletCreate.razor | 41 ++------ .../UI/Pages/WalletRecover.razor | 99 +++++++++++++++++++ .../UI/Pages/Wallets.razor | 17 ++-- 3 files changed, 119 insertions(+), 38 deletions(-) create mode 100644 src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor index 8d627a465..5240cc030 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor @@ -1,4 +1,4 @@ -@page "/walletcrate" +@page "/walletcreate" @using Blockcore.Features.Wallet.Interfaces @using NBitcoin; @@ -10,18 +10,21 @@ @inject IWalletSyncManager WalletSyncManager

Create a Wallet

- +

Create your wallet by generating a Mnemonic & adding an optional phrase. Then give your wallet a name & password.

@{ +
+ +
Mnemonic
- +

Important: The Mnemonic is your wallet and must be kept safe and secure.

@@ -33,10 +36,6 @@

Important: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

-
- -
-
Wallet name: @@ -52,7 +51,6 @@
-
@@ -61,13 +59,11 @@ } @code { - public string WalletName { get; set; } public string AccountName { get; set; } public string Mnemonic { get; set; } private string Password { get; set; } private string Passphrase { get; set; } - string Alert { get; set; } private void GenerateMnemonic() @@ -90,28 +86,11 @@ { NavigationManager.NavigateTo("wallets"); } - - private void RecoverWallet() - { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "No Password"; return; } - if (string.IsNullOrEmpty(this.Mnemonic)) { this.Alert = "No Mnemonic"; return; } - if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "No WalletName"; return; } - - if (this.Passphrase == null) - this.Passphrase = string.Empty; - - this.Alert = string.Empty; - - var wallet = this.WalletManager.RecoverWallet(this.Password, this.WalletName, this.Mnemonic, this.DateTimeProvider.GetUtcNow(), passphrase: this.Passphrase); - - NavigationManager.NavigateTo("walletaccount/" + WalletName + "/account 0"); - } - private void CreateWallet() { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "No Password"; return; } - if (string.IsNullOrEmpty(this.Mnemonic)) { this.Alert = "No Mnemonic"; return; } - if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "No WalletName"; return; } + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.Mnemonic)) { this.Alert = "Ensure that you have generated a new Mnemonic"; return; } + if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "Please enter a wallet name"; return; } if (this.Passphrase == null) this.Passphrase = string.Empty; diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor new file mode 100644 index 000000000..9399271d7 --- /dev/null +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor @@ -0,0 +1,99 @@ +@page "/walletrecover" + +@using Blockcore.Features.Wallet.Interfaces +@using NBitcoin; +@using Blockcore.Features.Wallet.Api.Controllers + +@inject NavigationManager NavigationManager +@inject IWalletManager WalletManager +@inject Blockcore.Utilities.IDateTimeProvider DateTimeProvider +@inject IWalletSyncManager WalletSyncManager + + +
+ +

Recover a Wallet

+

Recover your wallet by entering your Mnemonic & your passphrase. Then give your wallet a name & password.

+@{ +
+
+ Mnemonic +
+ +
+

Reminder: The Mnemonic is your wallet and must be kept safe and secure.

+ +
+
+ Passphrase (optional): +
+ +
+

Reminder: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

+ +
+
+ Wallet name: +
+ +
+ +
+
+ Wallet Password: +
+ +
+ + + +
+
+
@Alert
+
+} + +@code { + + public string WalletName { get; set; } + public string AccountName { get; set; } + public string Mnemonic { get; set; } + private string Password { get; set; } + private string Passphrase { get; set; } + + string Alert { get; set; } + + private void NavigateToReceiveWallet(string walletName, string accountname) + { + NavigationManager.NavigateTo("walletreceive/" + walletName + "/" + accountname); + } + + private void NavigateToSendWallet(string walletName, string accountname) + { + NavigationManager.NavigateTo("walletsend/" + walletName + "/" + accountname); + } + + private void NavigateToWallets() + { + NavigationManager.NavigateTo("wallets"); + } + + private void RecoverWallet() + { + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.Mnemonic)) { this.Alert = "Ensure that you have entered your Mnemonic"; return; } + if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "Please enter a wallet name"; return; } + + if (this.Passphrase == null) + this.Passphrase = string.Empty; + + this.Alert = string.Empty; + + var wallet = this.WalletManager.RecoverWallet(this.Password, this.WalletName, this.Mnemonic, this.DateTimeProvider.GetUtcNow(), passphrase: this.Passphrase); + + NavigationManager.NavigateTo("walletaccount/" + WalletName + "/account 0"); + } + +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor index 44dafaf00..ede7bc851 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor @@ -21,17 +21,17 @@

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

- - - + + +


- - + + @@ -64,9 +64,12 @@ private void NavigateToWalletCreate() { - NavigationManager.NavigateTo("walletcrate"); + NavigationManager.NavigateTo("walletcreate"); + } + private void NavigateToWalletRecover() + { + NavigationManager.NavigateTo("walletrecover"); } - private void Resync() { this.WalletSyncManager.SyncFromHeight(1); From 642f84b824d08c1704067b9c7f6d05c5cc52295c Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 12 May 2020 09:56:39 +0100 Subject: [PATCH 02/44] Rename peer nodes to add nodes --- .../UI/Pages/{PeersNodes.razor => AddNodes.razor} | 6 +++--- .../Blockcore.Features.WebHost/UI/Pages/Peers.razor | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) rename src/Features/Blockcore.Features.WebHost/UI/Pages/{PeersNodes.razor => AddNodes.razor} (91%) diff --git a/src/Features/Blockcore.Features.WebHost/UI/Pages/PeersNodes.razor b/src/Features/Blockcore.Features.WebHost/UI/Pages/AddNodes.razor similarity index 91% rename from src/Features/Blockcore.Features.WebHost/UI/Pages/PeersNodes.razor rename to src/Features/Blockcore.Features.WebHost/UI/Pages/AddNodes.razor index 7ed6708f3..b2ddc3595 100644 --- a/src/Features/Blockcore.Features.WebHost/UI/Pages/PeersNodes.razor +++ b/src/Features/Blockcore.Features.WebHost/UI/Pages/AddNodes.razor @@ -1,12 +1,12 @@ -@page "/peers-nodes" +@page "/add-nodes" @using Blockcore.Utilities.Extensions @inject Blockcore.Connection.IConnectionManager ConnectionManager -

Connected peers

+

Add new nodes

-

Information about connected peers.

+

Add the IP address of known network peers.

@{
diff --git a/src/Features/Blockcore.Features.WebHost/UI/Pages/Peers.razor b/src/Features/Blockcore.Features.WebHost/UI/Pages/Peers.razor index e3b7b24b4..2fa770b77 100644 --- a/src/Features/Blockcore.Features.WebHost/UI/Pages/Peers.razor +++ b/src/Features/Blockcore.Features.WebHost/UI/Pages/Peers.razor @@ -9,7 +9,7 @@ @{
- +

Wallet / accountConfirmed blanaceWallet / AccountConfirmed balance Unconfirmed balance
@@ -37,8 +37,8 @@ @code { - private void NavigateToPeernodes() + private void NavigateToAddNodes() { - NavigationManager.NavigateTo("peers-nodes"); + NavigationManager.NavigateTo("add-nodes"); } } \ No newline at end of file From bb1a938332113e2898c0c91f81653af0085b0f96 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 12 May 2020 09:57:30 +0100 Subject: [PATCH 03/44] Improve error messages, fix some typos --- .../UI/NavItem.cs | 2 +- .../UI/Pages/ColdStake.razor | 60 ++++++++++--------- .../UI/Pages/ColdStakeSetup.razor | 6 +- .../UI/Pages/ColdStakeWithdraw.razor | 4 +- .../UI/Pages/Stake.razor | 8 +-- .../UI/Pages/WalletAccount.razor | 32 ++++++---- .../UI/Pages/WalletSend.razor | 38 ++++++++---- .../UI/Pages/Logs.razor | 6 +- 8 files changed, 90 insertions(+), 66 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs b/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs index d4f96f14b..e17f87f1d 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs +++ b/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs @@ -4,7 +4,7 @@ namespace Blockcore.Features.Wallet.UI { public class ColdStakingNavigationItem : INavigationItem { - public string Name => "ColdStaking"; + public string Name => "Cold Staking"; public string Navigation => "ColdStaking"; } diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index f815449cc..5a019777c 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -11,11 +11,33 @@ @if (!NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.CheckColdStakeVerify)) { -

Coldstaking is not activated

+

Cold staking is not activated

return; } -

Coldstaking Wallets

+

Cold staking Wallets

+ +

Enable cold staking on an existing wallet.

+ +
+
+
+ Wallet Name: +
+ +
+ +
+
+ Password: +
+ +
+ +
+ +
+

Information about the deployed wallets.

@@ -23,10 +45,10 @@
- - + + - + @@ -66,7 +88,7 @@ var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); - + @@ -103,26 +125,6 @@ }
Wallet / accountConfirmed blanaceWallet / AccountConfirmed balance Unconfirmed balanceActioneAction
@walletName /@hotStakingAccount.Name @walletName / @hotStakingAccount.Name @hotAccountBalance.AmountConfirmed @hotAccountBalance.AmountUnconfirmed @@ -94,7 +116,7 @@ @if (accountBalance.AmountConfirmed + accountBalance.AmountUnconfirmed > 0) { - + }
-
-
-
- Wallet Name: -
- -
- -
-
- Password: -
- -
- -
- -
-
- } @code @@ -146,8 +148,8 @@ private void CreateColdStakeAccount() { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "No password"; return; } - if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "No WalletName"; return; } + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "Please enter a wallet name"; return; } this.Alert = string.Empty; this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, true, this.Password); diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor index dccc6db8f..64f0c4425 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor @@ -156,9 +156,9 @@ private async Task Setup() { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "No password"; return; } - if (string.IsNullOrEmpty(this.ColdWalletAddress)) { this.Alert = "No ColdWalletAddress"; return; } - if (string.IsNullOrEmpty(this.HotWalletAddress)) { this.Alert = "No HotWalletAddress"; return; } + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.ColdWalletAddress)) { this.Alert = "Your cold wallet address is missing"; return; } + if (string.IsNullOrEmpty(this.HotWalletAddress)) { this.Alert = "Your hot wallet address is missing"; return; } this.Alert = string.Empty; diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor index 385724e17..bb7686ef6 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor @@ -112,8 +112,8 @@ private async Task Withdraw() { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "No password"; return; } - if (string.IsNullOrEmpty(this.Address)) { this.Alert = "No Address"; return; } + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.Address)) { this.Alert = "Please enter a withdrawal address"; return; } this.Alert = string.Empty; try diff --git a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor index b773e1c75..747d55824 100644 --- a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor +++ b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor @@ -35,8 +35,8 @@ - - + + @@ -139,8 +139,8 @@ private void StartStaking() { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "No password"; return; } - if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "No password"; return; } + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "Please enter a wallet name"; return; } var wallet = this.WalletManager.GetWallet(this.WalletName); diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index 7dc90f2cd..6d24ce085 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -10,27 +10,36 @@ @inject Network Network
-

Wallet Account

-

Information about @walletname / @accountname

- +

Wallet Account: @walletname / @accountname

@{ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single();
- -

Amount Confirmed: @accountBalance.AmountConfirmed

-

Amount Unconfirmed: @accountBalance.AmountUnconfirmed

-

Spendable Amount: @accountBalance.SpendableAmount

- - + -

+
Wallet/accountBlanaceWallet / AccountBalance
+ + + + + + + + + + + + + + +
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount
+

Wallet History

@@ -52,6 +61,7 @@ foreach (var transaction in history.TransactionsHistory) { + @transaction. @transaction.ToAddress @transaction.Amount @transaction.ConfirmedInBlock diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index c67b46660..657c77f55 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -19,9 +19,7 @@
-

Send Coins

- -

Send coins from account @walletname / @accountname

+

Send Coins: @walletname / @accountname

@{ @@ -29,9 +27,23 @@
-

Amount Confirmed: @accountBalance.AmountConfirmed

-

Amount Unconfirmed: @accountBalance.AmountUnconfirmed

-

Spendable Amount: @accountBalance.SpendableAmount

+ + + + + + + + + + + + + + + +
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount
+
@@ -151,13 +163,13 @@ private async Task Broadcast() { - if (string.IsNullOrEmpty(this.TransactionHex)) { this.Alert = "No trx"; return; } + if (string.IsNullOrEmpty(this.TransactionHex)) { this.Alert = "No transaction details, please click send coins first"; return; } this.Alert = string.Empty; if (!this.ConnectionManager.ConnectedPeers.Any()) { - this.Alert = "No peers connected"; + this.Alert = "No peers connected. You need connections before a transaction can be brodcast to the network."; return; } @@ -169,7 +181,7 @@ if (transactionBroadCastEntry.TransactionBroadcastState == TransactionBroadcastState.FailedBroadcast) { - this.Alert = "Error occurred: " + transactionBroadCastEntry.ErrorMessage; + this.Alert = "An error occurred: " + transactionBroadCastEntry.ErrorMessage; return; } @@ -178,10 +190,10 @@ private void SendCoins() { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "No password"; return; } - if (string.IsNullOrEmpty(this.Address)) { this.Alert = "No address"; return; } - if (this.Amount == 0) { this.Alert = "No amount"; return; } - if (this.Fee == 0) { this.Alert = "No fee"; return; } + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.Address)) { this.Alert = "Please enter a valid address"; return; } + if (this.Amount == 0) { this.Alert = "Please enter the number of coins you want to send"; return; } + if (this.Fee == 0) { this.Alert = "Please ensure you enter a fee"; return; } this.Alert = string.Empty; diff --git a/src/Features/Blockcore.Features.WebHost/UI/Pages/Logs.razor b/src/Features/Blockcore.Features.WebHost/UI/Pages/Logs.razor index 9dd077305..042863632 100644 --- a/src/Features/Blockcore.Features.WebHost/UI/Pages/Logs.razor +++ b/src/Features/Blockcore.Features.WebHost/UI/Pages/Logs.razor @@ -5,7 +5,7 @@

Node logs

@{ - +
+@(((Blockcore.FullNode)this.FullNode).LastLogOutput.TrimStart(' '))
+
} \ No newline at end of file From 724694befc17554a6c033753e01b4fbf373e4652 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 12 May 2020 17:58:12 +0100 Subject: [PATCH 04/44] Remove breadcrumbs & fix tx address bug --- .../UI/Pages/ColdStake.razor | 2 +- .../UI/Pages/WalletAccount.razor | 20 ++++++++----------- .../UI/Pages/WalletCreate.razor | 5 ----- .../UI/Pages/WalletReceive.razor | 5 ----- .../UI/Pages/WalletRecover.razor | 5 ----- .../UI/Pages/WalletSend.razor | 5 ----- .../UI/Pages/Wallets.razor | 7 ++----- 7 files changed, 11 insertions(+), 38 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index 5a019777c..85e069274 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -15,7 +15,7 @@ return; } -

Cold staking Wallets

+

Cold staking wallets

Enable cold staking on an existing wallet.

diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index 6d24ce085..a5b8ef2fc 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -9,11 +9,6 @@ @inject IWalletManager WalletManager @inject Network Network - -
-

Wallet Account: @walletname / @accountname

@{ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); @@ -49,10 +44,11 @@ - - - + + + + @@ -61,11 +57,11 @@ foreach (var transaction in history.TransactionsHistory) { - - - - + + + + } } diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor index 5240cc030..8a1888f68 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor @@ -9,11 +9,6 @@ @inject Blockcore.Utilities.IDateTimeProvider DateTimeProvider @inject IWalletSyncManager WalletSyncManager - -
-

Create a Wallet

Create your wallet by generating a Mnemonic & adding an optional phrase. Then give your wallet a name & password.

@{ diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor index 0a97e262b..d3d918f5c 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor @@ -7,11 +7,6 @@ @inject IWalletManager WalletManager @inject NavigationManager NavigationManager - -
-

Receive Coins

Generate receive address for @walletname / @accountname

diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor index 9399271d7..f38c354b4 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor @@ -9,11 +9,6 @@ @inject Blockcore.Utilities.IDateTimeProvider DateTimeProvider @inject IWalletSyncManager WalletSyncManager - -
-

Recover a Wallet

Recover your wallet by entering your Mnemonic & your passphrase. Then give your wallet a name & password.

@{ diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index 657c77f55..b14ab34b2 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -14,11 +14,6 @@ @inject IWalletTransactionHandler WalletTransactionHandler @inject IBroadcasterManager BroadcasterManager - -
-

Send Coins: @walletname / @accountname

@{ diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor index ede7bc851..16f9099d0 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor @@ -17,16 +17,13 @@

Information about the deployed wallets.

@{ -

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

-
-
-
+

To AddressAmountConfirmed In Block TypeBlockAmountTo AddressTxID
@transaction.@transaction.ToAddress@transaction.Amount@transaction.ConfirmedInBlock @transaction.Type@transaction.ConfirmedInBlock@transaction.Amount@transaction.ToAddress@transaction.Id
@@ -44,7 +41,7 @@ var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - + From b28d5ced0e981bcc80d02631eadacb3063e0169b Mon Sep 17 00:00:00 2001 From: Hunter Date: Wed, 13 May 2020 20:51:03 +0100 Subject: [PATCH 05/44] Even up the labels --- .../UI/Pages/ColdStake.razor | 4 +-- .../UI/Pages/ColdStakeSetup.razor | 36 ++++++++++++------- .../UI/Pages/ColdStakeWithdraw.razor | 12 +++---- .../UI/Pages/Stake.razor | 4 +-- .../UI/Pages/WalletCreate.razor | 29 ++++++++------- .../UI/Pages/WalletRecover.razor | 8 ++--- .../UI/Pages/WalletSend.razor | 14 ++++---- 7 files changed, 61 insertions(+), 46 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index 85e069274..75d33774b 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -22,14 +22,14 @@
- Wallet Name: + Wallet Name:
- Password: + Password:
diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor index 64f0c4425..610435b3f 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor @@ -20,19 +20,31 @@ @{ var accountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); -

Amount Confirmed: @accountBalance.AmountConfirmed

-

Amount Unconfirmed: @accountBalance.AmountUnconfirmed

-

Spendable Amount: @accountBalance.SpendableAmount

- +
@walletName / @account.Name@walletName / @account.Name @accountBalance.AmountConfirmed @accountBalance.AmountUnconfirmed
+ + + + + + + + + + + + + + +
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount

- ColdWalletAddress: + ColdWalletAddress:
- from wallet: @walletname + from wallet: @walletname
@@ -45,34 +57,34 @@
- HotWalletAddress: + HotWalletAddress:
- Amount: + Amount:
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
- Fee: + Fee:
- Optional (default to low) + Optional (default to low)
- Password: + Password:
diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor index bb7686ef6..d79c8d80c 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor @@ -30,14 +30,14 @@
- Password: + Password:
- Address: + Address:
@@ -45,21 +45,21 @@
- Amount: + Amount:
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
- Fee: + Fee:
- Optional (default to low) + Optional (default to low)
diff --git a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor index 747d55824..66e25c972 100644 --- a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor +++ b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor @@ -61,14 +61,14 @@ {
- Wallet Name: + Wallet Name:
- Password: + Password:
diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor index 8a1888f68..c89bf59d0 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor @@ -12,37 +12,40 @@

Create a Wallet

Create your wallet by generating a Mnemonic & adding an optional phrase. Then give your wallet a name & password.

@{ +
-
+ +
- Mnemonic + Mnemonic:
- +

Important: The Mnemonic is your wallet and must be kept safe and secure.

-
+
- Passphrase (optional): + Passphrase (optional):
- +
-

Important: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

+

Important: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

-
+ +
- Wallet name: + Wallet name:
- +
-
+
- Wallet Password: + Wallet Password:
- +
diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor index f38c354b4..7992a7148 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor @@ -14,7 +14,7 @@ @{
- Mnemonic + Mnemonic
@@ -22,7 +22,7 @@
- Passphrase (optional): + Passphrase (optional):
@@ -30,14 +30,14 @@
- Wallet name: + Wallet name:
- Wallet Password: + Wallet Password:
diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index b14ab34b2..2ce1d9d7b 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -42,34 +42,34 @@
- To Address: + To Address:
- Amount: + Amount:
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
- Fee: + Fee:
- Optional (default to low) + Optional (default to low)
- Wallet Password: + Wallet Password:
@@ -89,7 +89,7 @@
- Raw Transaction + Raw Transaction
From 9662386fdef21e66e1adca61b0e3ca485cbda938 Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 24 May 2020 13:43:41 +0100 Subject: [PATCH 06/44] Update favicon --- .../UI/wwwroot/favicon.ico | Bin 32038 -> 5430 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/favicon.ico b/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/favicon.ico index a3a799985c43bc7309d701b2cad129023377dc71..5c8d9bcf55722d54d10b98d059f8bafa82da6498 100644 GIT binary patch literal 5430 zcmeH~Pl!!X9LLX_G4sfu88MX7JgG4eO0ltcq9hVwYoRE!L2885s7V$y8)Qi&!^)p1 z3wh&TvyretLo=n=V2B!d=Jw+Lj@*3duZKH@tKKEd+TM~ zzm|~?gXY`){(+*7L+g4SoPbErKh$i@AhVR=Yh`$Xp3V`}&LJOhnGSq*gaPhb5lX=- zP(8{Sg(qU2$;XHPU4;8QoC5t0s%0|~+6$^9!=Re<6n4NgsFZ2lZ-xi(6PV?{_(A(N ztbsZxmlbRNB?kNkuCCkGIz0;uApzsDW|EJ=dvJA1wN=|y<7dNIO!e^v=o^>P3i7MQ z^}O2d&_;Olzum3YtDnL()t$>4*N}4TK_@>{T^Z}HUFjb zThLa`sJ1>kwb@nB_N!OrTL13*>+H1_bQaV8Gvzj{S?sEtQob#gy6g(`$Q$D;p{A$1;G0AY0^TsiNJqpyAE z2Bbk}-EvqI{gVhigY6LMTpi=VqUbMUyty&Pj1w9~KhAh@WB==qt}Sl;i#w-r;{Wyh zck-}qZLQ|}H=*ASZ#>UYO?_l@HMEthYU&`AI)4#T5z`r8{}1hfnsO@GY}(qv25U35 tmXB>YymYW}rvFfzNoSM&J{(PF>xmn|X6qA>gl6cl*`y6*7@s|E?Qb@-%@hCt literal 32038 zcmeHwX>eTEbtY7aYbrGrkNjgie?1jXjZ#zP%3n{}GObKv$BxI7Sl;Bwl5E+Qtj&t8 z*p|m4DO#HoJC-FyvNnp8NP<{Na0LMnTtO21(rBP}?EAiNjWgeO?z`{3ZoURUQlV2d zY1Pqv{m|X_oO91|?^z!6@@~od!@OH>&BN;>c@O+yUfy5w>LccTKJJ&`-k<%M^Zvi( z<$dKp=jCnNX5Qa+M_%6g|IEv~4R84q9|7E=|Ho(Wz3f-0wPjaRL;W*N^>q%^KGRr7 zxbjSORb_c&eO;oV_DZ7ua!sPH=0c+W;`vzJ#j~-x3uj};50#vqo*0w4!LUqs*UCh9 zvy2S%$#8$K4EOa&e@~aBS65_hc~Mpu=454VT2^KzWqEpBA=ME|O;1cn?8p<+{MKJf zbK#@1wzL44m$k(?85=Obido7=C|xWKe%66$z)NrzRwR>?hK?_bbwT z@Da?lBrBL}Zemo1@!9pYRau&!ld17h{f+UV0sY(R{ET$PBB|-=Nr@l-nY6w8HEAw* zRMIQU`24Jl_IFEPcS=_HdrOP5yf81z_?@M>83Vv65$QFr9nPg(wr`Ke8 zaY4ogdnMA*F7a4Q1_uXadTLUpCk;$ZPRRJ^sMOch;rlbvUGc1R9=u;dr9YANbQ<4Z z#P|Cp9BP$FXNPolgyr1XGt$^lFPF}rmBF5rj1Kh5%dforrP8W}_qJL$2qMBS-#%-|s#BPZBSETsn_EBYcr(W5dq( z@f%}C|iN7)YN`^)h7R?Cg}Do*w-!zwZb9=BMp%Wsh@nb22hA zA{`wa8Q;yz6S)zfo%sl08^GF`9csI9BlGnEy#0^Y3b);M+n<(}6jziM7nhe57a1rj zC@(2ISYBL^UtWChKzVWgf%4LW2Tqg_^7jMw`C$KvU+mcakFjV(BGAW9g%CzSyM;Df z143=mq0oxaK-H;o>F3~zJ<(3-j&?|QBn)WJfP#JR zRuA;`N?L83wQt78QIA$(Z)lGQY9r^SFal;LB^qi`8%8@y+mwcGsf~nv)bBy2S7z~9 z=;X@Gglk)^jpbNz?1;`!J3QUfAOp4U$Uxm5>92iT`mek#$>s`)M>;e4{#%HAAcb^8_Ax%ersk|}# z0bd;ZPu|2}18KtvmIo8`1@H~@2ejwo(5rFS`Z4&O{$$+ch2hC0=06Jh`@p+p8LZzY z&2M~8T6X^*X?yQ$3N5EzRv$(FtSxhW>>ABUyp!{484f8(%C1_y)3D%Qgfl_!sz`LTXOjR&L!zPA0qH_iNS!tY{!^2WfD%uT}P zI<~&?@&))5&hPPHVRl9);TPO>@UI2d!^ksb!$9T96V(F){puTsn(}qt_WXNw4VvHj zf;6A_XCvE`Z@}E-IOaG0rs>K>^=Sr&OgT_p;F@v0VCN0Y$r|Lw1?Wjt`AKK~RT*kJ z2>QPuVgLNcF+XKno;WBv$yj@d_WFJbl*#*V_Cwzo@%3n5%z4g21G*PVZ)wM5$A{klYozmGlB zT@u2+s}=f}25%IA!yNcXUr!!1)z(Nqbhojg0lv@7@0UlvUMT)*r;M$d0-t)Z?B1@qQk()o!4fqvfr_I0r7 zy1(NdkHEj#Yu{K>T#We#b#FD=c1XhS{hdTh9+8gy-vkcdkk*QS@y(xxEMb1w6z<^~ zYcETGfB#ibR#ql0EiD;PR$L&Vrh2uRv5t_$;NxC;>7_S5_OXxsi8udY3BUUdi55Sk zcyKM+PQ9YMA%D1kH1q48OFG(Gbl=FmV;yk8o>k%0$rJ8%-IYsHclnYuTskkaiCGkUlkMY~mx&K}XRlKIW;odWIeuKjtbc^8bBOTqK zjj(ot`_j?A6y_h%vxE9o*ntx#PGrnK7AljD_r58ylE*oy@{IY%+mA^!|2vW_`>`aC{#3`#3;D_$^S^cM zRcF+uTO2sICledvFgNMU@A%M)%8JbSLq{dD|2|2Sg8vvh_uV6*Q?F&rKaV{v_qz&y z`f;stIb?Cb2!Cg7CG91Bhu@D@RaIrq-+o+T2fwFu#|j>lD6ZS9-t^5cx>p|?flqUA z;Cgs#V)O#`Aw4$Kr)L5?|7f4izl!;n0jux}tEW$&&YBXz9o{+~HhoiYDJ`w5BVTl&ARya=M7zdy$FEe}iGBur8XE>rhLj&_yDk5D4n2GJZ07u7%zyAfNtOLn;)M?h*Py-Xtql5aJOtL4U8e|!t? z((sc6&OJXrPdVef^wZV&x=Z&~uA7^ix8rly^rEj?#d&~pQ{HN8Yq|fZ#*bXn-26P^ z5!)xRzYO9{u6vx5@q_{FE4#7BipS#{&J7*>y}lTyV94}dfE%Yk>@@pDe&F7J09(-0|wuI|$of-MRfK51#t@t2+U|*s=W; z!Y&t{dS%!4VEEi$efA!#<<7&04?kB}Soprd8*jYv;-Qj~h~4v>{XX~kjF+@Z7<t?^|i z#>_ag2i-CRAM8Ret^rZt*^K?`G|o>1o(mLkewxyA)38k93`<~4VFI?5VB!kBh%NNU zxb8K(^-MU1ImWQxG~nFB-Un;6n{lQz_FfsW9^H$Xcn{;+W^ZcG$0qLM#eNV=vGE@# z1~k&!h4@T|IiI<47@pS|i?Qcl=XZJL#$JKve;booMqDUYY{(xcdj6STDE=n?;fsS1 ze`h~Q{CT$K{+{t+#*I1=&&-UU8M&}AwAxD-rMa=e!{0gQXP@6azBq9(ji11uJF%@5 zCvV`#*?;ZguQ7o|nH%bm*s&jLej#@B35gy32ZAE0`Pz@#j6R&kN5w{O4~1rhDoU zEBdU)%Nl?8zi|DR((u|gg~r$aLYmGMyK%FO*qLvwxK5+cn*`;O`16c!&&XT{$j~5k zXb^fbh1GT-CI*Nj{-?r7HNg=e3E{6rxuluPXY z5Nm8ktc$o4-^SO0|Es_sp!A$8GVwOX+%)cH<;=u#R#nz;7QsHl;J@a{5NUAmAHq4D zIU5@jT!h?kUp|g~iN*!>jM6K!W5ar0v~fWrSHK@})@6Lh#h)C6F6@)&-+C3(zO! z8+kV|B7LctM3DpI*~EYo>vCj>_?x&H;>y0*vKwE0?vi$CLt zfSJB##P|M2dEUDBPKW=9cY-F;L;h3Fs4E2ERdN#NSL7ctAC z?-}_a{*L@GA7JHJudxtDVA{K5Yh*k(%#x4W7w+^ zcb-+ofbT5ieG+@QG2lx&7!MyE2JWDP@$k`M;0`*d+oQmJ2A^de!3c53HFcfW_Wtv< zKghQ;*FifmI}kE4dc@1y-u;@qs|V75Z^|Q0l0?teobTE8tGl@EB?k#q_wUjypJ*R zyEI=DJ^Z+d*&}B_xoWvs27LtH7972qqMxVFcX9}c&JbeNCXUZM0`nQIkf&C}&skSt z^9fw@b^Hb)!^hE2IJq~~GktG#ZWwWG<`@V&ckVR&r=JAO4YniJewVcG`HF;59}=bf zLyz0uxf6MhuSyH#-^!ZbHxYl^mmBVrx) zyrb8sQ*qBd_WXm9c~Of$&ZP$b^)<~0%nt#7y$1Jg$e}WCK>TeUB{P>|b1FAB?%K7>;XiOfd}JQ`|IP#Vf%kVy zXa4;XFZ+>n;F>uX&3|4zqWK2u3c<>q;tzjsb1;d{u;L$-hq3qe@82(ob<3qom#%`+ z;vzYAs7TIMl_O75BXu|r`Qhc4UT*vN$3Oo0kAC!{f2#HexDy|qUpgTF;k{o6|L>7l z=?`=*LXaow1o;oNNLXsGTrvC)$R&{m=94Tf+2iTT3Y_Or z-!;^0a{kyWtO4vksG_3cyc7HQ0~detf0+2+qxq(e1NS251N}w5iTSrM)`0p8rem!j zZ56hGD=pHI*B+dd)2B`%|9f0goozCSeXPw3 z+58k~sI02Yz#lOneJzYcG)EB0|F+ggC6D|B`6}d0khAK-gz7U3EGT|M_9$ZINqZjwf>P zJCZ=ogSoE`=yV5YXrcTQZx@Un(64*AlLiyxWnCJ9I<5Nc*eK6eV1Mk}ci0*NrJ=t| zCXuJG`#7GBbPceFtFEpl{(lTm`LX=B_!H+& z>$*Hf}}y zkt@nLXFG9%v**s{z&{H4e?aqp%&l#oU8lxUxk2o%K+?aAe6jLojA& z_|J0<-%u^<;NT*%4)n2-OdqfctSl6iCHE?W_Q2zpJken#_xUJlidzs249H=b#g z?}L4-Tnp6)t_5X?_$v)vz`s9@^BME2X@w<>sKZ3=B{%*B$T5Nj%6!-Hr;I!Scj`lH z&2dHFlOISwWJ&S2vf~@I4i~(0*T%OFiuX|eD*nd2utS4$1_JM?zmp>a#CsVy6Er^z zeNNZZDE?R3pM?>~e?H_N`C`hy%m4jb;6L#8=a7l>3eJS2LGgEUxsau-Yh9l~o7=Yh z2mYg3`m5*3Ik|lKQf~euzZlCWzaN&=vHuHtOwK!2@W6)hqq$Zm|7`Nmu%9^F6UH?+ z@2ii+=iJ;ZzhiUKu$QB()nKk3FooI>Jr_IjzY6=qxYy;&mvi7BlQ?t4kRjIhb|2q? zd^K~{-^cxjVSj?!Xs=Da5IHmFzRj!Kzh~b!?`P7c&T9s77VLYB?8_?F zauM^)p;qFG!9PHLfIsnt43UnmV?Wn?Ki7aXSosgq;f?MYUuSIYwOn(5vWhb{f%$pn z4ySN-z}_%7|B);A@PA5k*7kkdr4xZ@s{e9j+9w;*RFm;XPDQwx%~;8iBzSKTIGKO z{53ZZU*OLr@S5=k;?CM^i#zkxs3Sj%z0U`L%q`qM+tP zX$aL;*^g$7UyM2Go+_4A+f)IQcy^G$h2E zb?nT$XlgTEFJI8GN6NQf%-eVn9mPilRqUbT$pN-|;FEjq@Ao&TxpZg=mEgBHB zU@grU;&sfmqlO=6|G3sU;7t8rbK$?X0y_v9$^{X`m4jZ_BR|B|@?ZCLSPPEzz`w1n zP5nA;4(kQFKm%$enjkkBxM%Y}2si&d|62L)U(dCzCGn56HN+i#6|nV-TGIo0;W;`( zW-y=1KF4dp$$mC_|6}pbb>IHoKQeZajXQB>jVR?u`R>%l1o54?6NnS*arpVopdEF; zeC5J3*M0p`*8lif;!irrcjC?(uExejsi~>4wKYwstGY^N@KY}TujLx`S=Cu+T=!dx zKWlPm->I**E{A*q-Z^FFT5$G%7Ij0_*Mo4-y6~RmyTzUB&lfae(WZfO>um}mnsDXPEbau-!13!!xd!qh*{C)6&bz0j1I{>y$D-S)b*)JMCPk!=~KL&6Ngin0p6MCOxF2L_R9t8N!$2Wpced<#`y!F;w zKTi5V_kX&X09wAIJ#anfg9Dhn0s7(C6Nj3S-mVn(i|C6ZAVq0$hE)874co};g z^hR7pe4lU$P;*ggYc4o&UTQC%liCXooIfkI3TNaBV%t~FRr}yHu7kjQ2J*3;e%;iW zvDVCh8=G80KAeyhCuY2LjrC!Od1rvF7h}zszxGV)&!)6ChP5WAjv-zQAMNJIG!JHS zwl?pLxC-V5II#(hQ`l)ZAp&M0xd4%cxmco*MIk?{BD=BK`1vpc}D39|XlV z{c&0oGdDa~TL2FT4lh=~1NL5O-P~0?V2#ie`v^CnANfGUM!b4F=JkCwd7Q`c8Na2q zJGQQk^?6w}Vg9-{|2047((lAV84uN%sK!N2?V(!_1{{v6rdgZl56f0zDMQ+q)jKzzu^ztsVken;=DjAh6G`Cw`Q4G+BjS+n*=KI~^K{W=%t zbD-rN)O4|*Q~@<#@1Vx$E!0W9`B~IZeFn87sHMXD>$M%|Bh93rdGf1lKoX3K651t&nhsl= zXxG|%@8}Bbrlp_u#t*DZX<}_0Yb{A9*1Pd_)LtqNwy6xT4pZrOY{s?N4)pPwT(i#y zT%`lRi8U#Ken4fw>H+N`{f#FF?ZxFlLZg7z7#cr4X>id z{9kUD`d2=w_Zlb{^c`5IOxWCZ1k<0T1D1Z31IU0Q2edsZ1K0xv$pQVYq2KEp&#v#Z z?{m@Lin;*Str(C2sfF^L>{R3cjY`~#)m>Wm$Y|1fzeS0-$(Q^z@} zEO*vlb-^XK9>w&Ef^=Zzo-1AFSP#9zb~X5_+){$(eB4K z8gtW+nl{q+CTh+>v(gWrsP^DB*ge(~Q$AGxJ-eYc1isti%$%nM<_&Ev?%|??PK`$p z{f-PM{Ym8k<$$)(F9)tqzFJ?h&Dk@D?Dt{4CHKJWLs8$zy6+(R)pr@0ur)xY{=uXFFzH_> z-F^tN1y(2hG8V)GpDg%wW0Px_ep~nIjD~*HCSxDi0y`H!`V*~RHs^uQsb1*bK1qGpmd zB1m`Cjw0`nLBF2|umz+a#2X$c?Lj;M?Lj;MUp*d>7j~ayNAyj@SLpeH`)BgRH}byy zyQSat!;U{@O(<<2fp&oQkIy$z`_CQ-)O@RN;QD9T4y|wIJ^%U#(BF%=`i49}j!D-) zkOwPSJaG03SMkE~BzW}b_v>LA&y)EEYO6sbdnTX*$>UF|JhZ&^MSb4}Tgbne_4n+C zwI8U4i~PI>7a3{kVa8|))*%C0|K+bIbmV~a`|G#+`TU#g zXW;bWIcWsQi9c4X*RUDpIfyoPY)2bI-r9)xulm1CJDkQd6u+f)_N=w1ElgEBjprPF z3o?Ly0RVeY_{3~fPVckRMxe2lM8hj!B8F)JO z!`AP6>u>5Y&3o9t0QxBpNE=lJx#NyIbp1gD zzUYBIPYHIv9ngk-Zt~<)62^1Zs1LLYMh@_tP^I7EX-9)Ed0^@y{k65Gp0KRcTmMWw zU|+)qx{#q0SL+4q?Q`i0>COIIF8a0Cf&C`hbMj?LmG9K&iW-?PJt*u)38tTXAP>@R zZL6uH^!RYNq$p>PKz7f-zvg>OKXcZ8h!%Vo@{VUZp|+iUD_xb(N~G|6c#oQK^nHZU zKg#F6<)+`rf~k*Xjjye+syV{bwU2glMMMs-^ss4`bYaVroXzn`YQUd__UlZL_mLs z(vO}k!~(mi|L+(5&;>r<;|OHnbXBE78LruP;{yBxZ6y7K3)nMo-{6PCI7gQi6+rF_ zkPod!Z8n}q46ykrlQS|hVB(}(2Kf7BCZ>Vc;V>ccbk2~NGaf6wGQH@W9&?Zt3v(h*P4xDrN>ex7+jH*+Qg z%^jH$&+*!v{sQ!xkWN4+>|b}qGvEd6ANzgqoVy5Qfws}ef2QqF{iiR5{pT}PS&yjo z>lron#va-p=v;m>WB+XVz|o;UJFdjo5_!RRD|6W{4}A2a#bZv)gS_`b|KsSH)Sd_JIr%<%n06TX&t{&!H#{)?4W9hlJ`R1>FyugOh3=D_{einr zu(Wf`qTkvED+gEULO0I*Hs%f;&=`=X4;N8Ovf28x$A*11`dmfy2=$+PNqX>XcG`h% zJY&A6@&)*WT^rC(Caj}2+|X|6cICm5h0OK0cGB_!wEKFZJU)OQ+TZ1q2bTx9hxnq& z$9ee|f9|0M^)#E&Pr4)f?o&DMM4w>Ksb{hF(0|wh+5_{vPow{V%TFzU2za&gjttNi zIyR9qA56dX52Qbv2aY^g`U7R43-p`#sO1A=KS2aKgfR+Yu^bQ*i-qu z%0mP;Ap)B~zZgO9lG^`325gOf?iUHF{~7jyGC)3L(eL(SQ70VzR~wLN18tnx(Cz2~ zctBl1kI)wAe+cxWHw*NW-d;=pd+>+wd$a@GBju*wFvabSaPtHiT!o#QFC+wBVwYo3s=y;z1jM+M=Fj!FZM>UzpL-eZzOT( zhmZmEfWa=%KE#V3-ZK5#v!Hzd{zc^{ctF~- z>DT-U`}5!fk$aj24`#uGdB7r`>oX5tU|d*b|N3V1lXmv%MGrvE(dXG)^-J*LA>$LE z7kut4`zE)v{@Op|(|@i#c>tM!12FQh?}PfA0`Bp%=%*RiXVzLDXnXtE@4B)5uR}a> zbNU}q+712pIrM`k^odG8dKtG$zwHmQI^c}tfjx5?egx3!e%JRm_64e+>`Ra1IRfLb z1KQ`SxmH{cZfyVS5m(&`{V}Y4j6J{b17`h6KWqZ&hfc(oR zxM%w!$F(mKy05kY&lco3%zvLCxBW+t*rxO+i=qGMvobx0-<7`VUu)ka`){=ew+Ovt zg%52_{&UbkUA8aJPWsk)gYWV4`dnxI%s?7^fGpq{ZQuu=VH{-t7w~K%_E<8`zS;V- zKTho*>;UQQul^1GT^HCt@I-q?)&4!QDgBndn?3sNKYKCQFU4LGKJ$n@Je$&w9@E$X z^p@iJ(v&`1(tq~1zc>0Vow-KR&vm!GUzT?Eqgnc)leZ9p)-Z*C!zqb=-$XG0 z^!8RfuQs5s>Q~qcz92(a_Q+KH?C*vCTr~UdTiR`JGuNH8v(J|FTiSEcPrBpmHRtmd zI2Jng0J=bXK);YY^rM?jzn?~X-Pe`GbAy{D)Y6D&1GY-EBcy%Bq?bKh?A>DD9DD!p z?{q02wno2sraGUkZv5dx+J8)&K$)No43Zr(*S`FEdL!4C)}WE}vJd%{S6-3VUw>Wp z?Aasv`T0^%P$2vE?L+Qhj~qB~K%eW)xH(=b_jU}TLD&BP*Pc9hz@Z=e0nkpLkWl}> z_5J^i(9Z7$(XG9~I3sY)`OGZ#_L06+Dy4E>UstcP-rU@xJ$&rxvo!n1Ao`P~KLU-8 z{zDgN4-&A6N!kPSYbQ&7sLufi`YtE2uN$S?e&5n>Y4(q#|KP!cc1j)T^QrUXMPFaP z_SoYO8S8G}Z$?AL4`;pE?7J5K8yWqy23>cCT2{=-)+A$X^-I9=e!@J@A&-;Ufc)`H}c(VI&;0x zrrGv()5mjP%jXzS{^|29?bLNXS0bC%p!YXI!;O457rjCEEzMkGf~B3$T}dXBO23tP z+Ci>;5UoM?C@bU@f9G1^X3=ly&ZeFH<@|RnOG--A&)fd)AUgjw?%izq{p(KJ`EP0v z2mU)P!+3t@X14DA=E2RR-|p${GZ9ETX=d+kJRZL$nSa0daI@&oUUxnZg0xd_xu>Vz lzF#z5%kSKX?YLH3ll^(hI(_`L*t#Iva2Ede*Z;>H_ Date: Sun, 24 May 2020 13:47:44 +0100 Subject: [PATCH 07/44] Update staking UI --- .../UI/Pages/Stake.razor | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor index 66e25c972..0ab8e4030 100644 --- a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor +++ b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor @@ -11,9 +11,11 @@ @inject IPosMinting PosMinting @inject Network Network -

Staking

- -

Information about staking.

+
+

Staking

+
+
+
@{ if (this.StakingEnabled) @@ -29,14 +31,14 @@ Staking disabled
} - -
- - - + +
+
+ - - + + + @@ -47,15 +49,19 @@ { var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - - + + + } } }
Wallet / AccountBalanceWalletConfirmed balanceUnconfirmed balance
@walletName / @account.Name
@walletName @accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed
+
+ + if (!this.StakingEnabled) { @@ -70,17 +76,17 @@
Password:
- +
- +
} else {
- +
} From 2fd15c3691208521eb05132f9e896a572633cf62 Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 24 May 2020 13:49:00 +0100 Subject: [PATCH 08/44] Merge index & peers, update UI --- .../UI/Pages/AddNodes.razor | 45 ---------- .../UI/Pages/Index.razor | 86 ++++++++++++++++--- .../UI/Pages/Logs.razor | 6 +- .../UI/Pages/Peers.razor | 44 ---------- .../UI/Shared/NavMenu.razor | 6 -- 5 files changed, 79 insertions(+), 108 deletions(-) delete mode 100644 src/Features/Blockcore.Features.NodeHost/UI/Pages/AddNodes.razor delete mode 100644 src/Features/Blockcore.Features.NodeHost/UI/Pages/Peers.razor diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/AddNodes.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/AddNodes.razor deleted file mode 100644 index b2ddc3595..000000000 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/AddNodes.razor +++ /dev/null @@ -1,45 +0,0 @@ -@page "/add-nodes" - -@using Blockcore.Utilities.Extensions - -@inject Blockcore.Connection.IConnectionManager ConnectionManager - -

Add new nodes

- -

Add the IP address of known network peers.

- -@{ -
-
- Node ip: -
- -
- add -
-
- -
- -
- -
-
@Alert
-
-} - -@code -{ - private string NodeIp { get; set; } - - string Alert { get; set; } - - private void Addnode() - { - var endpoint = this.NodeIp.ToIPEndPoint(this.ConnectionManager.Network.DefaultPort); - - this.ConnectionManager.AddNodeAddress(endpoint); - - this.Alert = $"node {endpoint} added"; - } -} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index 0adaee9c4..6296a0e29 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -1,5 +1,7 @@ @page "/" +@using Blockcore.Utilities.Extensions + @inject IFullNode FullNode @inject NBitcoin.Network Network @inject NBitcoin.ChainIndexer ChainIndexer @@ -7,26 +9,86 @@ @inject Blockcore.Interfaces.IInitialBlockDownloadState InitialBlockDownloadState @inject NavigationManager NavigationManager -

@this.Network.Name node.

+
+

@this.Network.CoinTicker.ToUpper() Node

+
+
+ +
+ +
+ + +
+
-@{ - if (this.InitialBlockDownloadState.IsInitialBlockDownload()) - { -

In IBD

- } +
-

Connected peers: @this.ConnectionManager.ConnectedPeers.Count()

-

Current tip at height: @this.ChainIndexer.Tip.Height

-

Current tip Hash: @this.ChainIndexer.Tip.HashBlock

+
+
@Alert
+
-
+@{ + + + + + + + + + + + + + + + + +
Connected peers:@this.ConnectionManager.ConnectedPeers.Count()
Current tip at height:@this.ChainIndexer.Tip.Height
Current tip Hash:@this.ChainIndexer.Tip.HashBlock
- - +if (this.InitialBlockDownloadState.IsInitialBlockDownload()) +{ +

In IBD

} + +
+ + + + + + + + + + + @foreach (var peer in this.ConnectionManager.ConnectedPeers) + { + + + + + + + } + +
IP AddressInboundAgentVersion
@peer.RemoteSocketEndpoint.ToString()@peer.Inbound@peer.PeerVersion?.UserAgent@peer.PeerVersion?.Version
+
+} @code { + private string NodeIp { get; set; } + string Alert { get; set; } + private void Addnode() + { + var endpoint = this.NodeIp.ToIPEndPoint(this.ConnectionManager.Network.DefaultPort); + + this.ConnectionManager.AddNodeAddress(endpoint); + + this.Alert = $"node {endpoint} added"; + } private void Shutdown() { this.FullNode?.NodeLifetime.StopApplication(); diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Logs.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Logs.razor index 042863632..d0b000de8 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Logs.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Logs.razor @@ -2,7 +2,11 @@ @inject IFullNode FullNode -

Node logs

+
+

Node Logs

+
+
+
@{
diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Peers.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Peers.razor
deleted file mode 100644
index 2fa770b77..000000000
--- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Peers.razor
+++ /dev/null
@@ -1,44 +0,0 @@
-@page "/peers"
-
-@inject Blockcore.Connection.IConnectionManager ConnectionManager
-@inject NavigationManager NavigationManager
-
-

Connected peers

- -

Information about connected peers.

- -@{ -
- -
-
- - - - - - - - - - - @foreach (var peer in this.ConnectionManager.ConnectedPeers) - { - - - - - - - } - -
IpInboundAgentVersion
@peer.RemoteSocketEndpoint.ToString()@peer.Inbound@peer.PeerVersion?.UserAgent@peer.PeerVersion?.Version
-} - -@code -{ - private void NavigateToAddNodes() - { - NavigationManager.NavigateTo("add-nodes"); - } -} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor index 0a9bba482..36679e314 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor @@ -18,12 +18,6 @@ - - @{ var items = fullnode.NodeService>(); foreach (var item in items) From bd0cbcfca33e9e8e958f33f6fa3f488aed540d7e Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 24 May 2020 13:51:35 +0100 Subject: [PATCH 09/44] Update Wallet UI --- .../UI/Pages/WalletAccount.razor | 70 ++++++++----------- .../UI/Pages/WalletReceive.razor | 49 +++++++++---- .../UI/Pages/WalletSend.razor | 46 +++++------- .../UI/Pages/Wallets.razor | 34 +++++---- 4 files changed, 104 insertions(+), 95 deletions(-) diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index a5b8ef2fc..0130fb196 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -9,46 +9,32 @@ @inject IWalletManager WalletManager @inject Network Network -

Wallet Account: @walletname / @accountname

@{ - var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); +var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); -
- - -
-
- - - - - - - - - - - - - - - -
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount
-
+
+

Wallet Account: @walletname

+
+ + +
+
-

Wallet History

+
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
- // For now just show last 100 trx of history. - var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); +// For now just show last 100 trx of history. +var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); - - +
+
+ - - - - - + + + @@ -56,17 +42,16 @@ { foreach (var transaction in history.TransactionsHistory) { - - - - - - + @*@onclick="() => { NavigateToViewTx(transaction.Id); }" > *@ + + + } }
TypeBlockAmountTo AddressTxID

TYPE

AMOUNT

BLOCK

@transaction.Type@transaction.ConfirmedInBlock@transaction.Amount@transaction.ToAddress@transaction.Id

@transaction.Type

@transaction.Amount

@transaction.ConfirmedInBlock

+
} @code { @@ -90,4 +75,9 @@ { NavigationManager.NavigateTo("wallets"); } + + private void NavigateToViewTx(uint256 txId) + { + NavigationManager.NavigateTo("coldStakeviewtx"); + } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor index d3d918f5c..2999a911e 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor @@ -7,17 +7,47 @@ @inject IWalletManager WalletManager @inject NavigationManager NavigationManager -

Receive Coins

- -

Generate receive address for @walletname / @accountname

+
+

Receive to: @walletname

+
+
+
@{ var result = this.WalletManager.GetUnusedAddress(new WalletAccountReference(walletname, accountname)); -
    -
  • Address: @result.Address
  • -
  • Segwit Address: @result.Bech32Address
  • -
+
+ + + + + + + + + + + +
Address:@result.Address
Segwit Address:@result.Bech32Address
+
+ + @* TODO: Add Copy Paste Functionality +
+
+ Address: +
+ + +
+ +
+
+ Segwit Address: +
+ + +
*@ + } @code { @@ -26,9 +56,4 @@ public string walletname { get; set; } [Parameter] public string accountname { get; set; } - - private void NavigateToWalletAccount(string walletName, string accountname) - { - NavigationManager.NavigateTo("walletaccount/" + walletName + "/" + accountname); - } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index 549157b0a..6f0527633 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -14,64 +14,54 @@ @inject IWalletTransactionHandler WalletTransactionHandler @inject IBroadcasterManager BroadcasterManager -

Send Coins: @walletname / @accountname

+ +
+

Send coins from: @walletname

+
+
+
@{ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); -
+
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
- - - - - - - - - - - - - - - -
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount
- -
- To Address: + To Address:
- Amount: + Amount:
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
- Fee: + Fee:
- Optional (default to low) + Optional (default to low)
- Wallet Password: + Password:
- +
@@ -214,4 +204,4 @@ this.SentTransactionHash = transactionResult.GetHash(); this.TransactionHex = transactionResult.ToHex(this.Network.Consensus.ConsensusFactory); } -} \ No newline at end of file +}ins from: te \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor index 16f9099d0..865caa845 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor @@ -12,22 +12,25 @@ @inject Network Network @inject IPooledTransaction PooledTransaction -

Wallets

- -

Information about the deployed wallets.

- @{ -

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

+
+

Wallet Details

+
+ + + + +
+
+ +

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

+
- - - - -

- - +
+
+ - + @@ -40,8 +43,8 @@ { var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - - + + @@ -50,6 +53,7 @@ }
Wallet / AccountWallet Confirmed balance Unconfirmed balance
@walletName / @account.Name
@walletName @accountBalance.AmountConfirmed @accountBalance.AmountUnconfirmed
+
} @code From 4e721a742b151b03ad76a3f3ad5434ae664a8fca Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 24 May 2020 13:52:26 +0100 Subject: [PATCH 10/44] Update Coldstake UI, Add CS History & CD Delegate --- .../UI/Pages/ColdStake.razor | 157 +++++---------- .../UI/Pages/ColdStakeDelegate.razor | 181 ++++++++++++++++++ .../UI/Pages/ColdStakeEnableWallet.razor | 78 ++++++++ .../UI/Pages/ColdStakeSetup.razor | 56 +++--- .../UI/Pages/ColdStakeView.razor | 86 +++++++++ .../UI/Pages/ColdStakeWithdraw.razor | 39 ++-- 6 files changed, 437 insertions(+), 160 deletions(-) create mode 100644 src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor create mode 100644 src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor create mode 100644 src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index 75d33774b..199ac9337 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -12,133 +12,68 @@ @if (!NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.CheckColdStakeVerify)) {

Cold staking is not activated

+
+ +
return; } -

Cold staking wallets

- -

Enable cold staking on an existing wallet.

- -
-
-
- Wallet Name: -
- +
+

Cold Staking

+
+
+
-
-
- Password: -
- -
- -
- -
-
- -

Information about the deployed wallets.

- -@{ - - +@{ +
+
+ - - - - + + + + + - @{ - foreach (var walletName in this.WalletManager.GetWalletsNames()) - { + @foreach (var walletName in this.WalletManager.GetWalletsNames()) { + + + + @foreach (var account in this.WalletManager.GetAccounts(walletName)) { + + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + + + var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); - if (coldStakingAccount != null) - { + + if (coldStakingAccount != null) { var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); - - - - - - - - } - else - { - - - - - - + } var hotStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), false); - if (hotStakingAccount != null) - { + + if (hotStakingAccount != null) { var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); - - - - - - - - } - else - { - - - - - - - } - - foreach (var account in this.WalletManager.GetAccounts(walletName)) - { - var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - - - - - - - + } } - } + + }
Wallet / AccountConfirmed balanceUnconfirmed balanceActionWalletAccount balanceCold balanceHot balance
@walletName@accountBalance.AmountConfirmed
@walletName / @coldStakingAccount.Name@coldAccountBalance.AmountConfirmed@coldAccountBalance.AmountUnconfirmed - @if (coldAccountBalance.AmountConfirmed + coldAccountBalance.AmountUnconfirmed > 0) - { - - } -
@walletName---
@coldAccountBalance.AmountConfirmed
@walletName / @hotStakingAccount.Name@hotAccountBalance.AmountConfirmed@hotAccountBalance.AmountUnconfirmed -
@walletName---
@walletName / @account.Name@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed - @if (accountBalance.AmountConfirmed + accountBalance.AmountUnconfirmed > 0) - { - - } -
@hotAccountBalance.AmountConfirmed
-} - +
+ } @code { ColdStakingManager ColdStakingManager; string Alert { get; set; } - private string WalletName { get; set; } - - private string Password { get; set; } - - public bool IsColdWalletAccount { get; set; } - protected override Task OnInitializedAsync() { ColdStakingManager = this.WalletManager as ColdStakingManager; @@ -146,16 +81,10 @@ return Task.CompletedTask; } - private void CreateColdStakeAccount() + private void NavigateToEnableWallet() { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } - if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "Please enter a wallet name"; return; } - this.Alert = string.Empty; - - this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, true, this.Password); - this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, false, this.Password); + NavigationManager.NavigateTo("coldstaking-enablewallet"); } - private void NavigateToWithdraw(string walletName) { NavigationManager.NavigateTo("coldstaking-withdraw/" + walletName); @@ -165,4 +94,12 @@ { NavigationManager.NavigateTo("coldstaking-setup/" + walletName); } + private void NavigateToDelegate(string walletName) + { + NavigationManager.NavigateTo("coldstaking-delegate/" + walletName); + } + private void NavigateToColdStakeView(string walletName) + { + NavigationManager.NavigateTo("coldstakeview/" + walletName + "/coldStakingColdAddresses"); + } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor new file mode 100644 index 000000000..957c7fd25 --- /dev/null +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor @@ -0,0 +1,181 @@ +@page "/coldstaking-delegate/{walletname}" + +@using Blockcore.Features.ColdStaking +@using Blockcore.Features.Wallet.Interfaces +@using NBitcoin; +@using Blockcore.Interfaces +@using Blockcore.Base.Deployments + +@inject IWalletManager WalletManager +@inject NavigationManager NavigationManager +@inject Network Network +@inject IWalletTransactionHandler WalletTransactionHandler +@inject IBroadcasterManager BroadcasterManager +@inject NodeDeployments NodeDeployments + +
+

Delegate Staking From: @walletname

+
+
+
+ +@{ + var accountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); + +
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
+ +
+
+ Delegated Staking Address: +
+ +
+ +
+
+ Amount: +
+ +
+ @this.Network.CoinTicker.ToUpper() +
+
+ +
+
+ Fee: +
+ +
+ Optional (default to low) +
+
+ +
+
+ Password: +
+ +
+ +
+ +
+ +
+ +
+ +
+
@Alert
+
+} + +@code +{ + [Parameter] + public string walletname { get; set; } + + ColdStakingManager ColdStakingManager; + + string Alert { get; set; } + + private string HotWallet { get; set; } + + private string HotWalletAddress { get; set; } + + private string ColdWalletAddress { get; set; } + + private string Password { get; set; } + + private decimal Amount { get; set; } + + private decimal Fee { get; set; } + + public bool SegwitChangeAddress { get; set; } + + public bool PayToScript { get; set; } + + protected override Task OnInitializedAsync() + { + ColdStakingManager = this.WalletManager as ColdStakingManager; + + this.Fee = new Money(this.Network.MinTxFee).ToDecimal(MoneyUnit.BTC); + + var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(this.walletname, true); + + this.SegwitChangeAddress = this.NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.Witness); + + this.ColdWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; + + if (this.ColdWalletAddress == null) + { + this.Alert = "The cold staking account does not exist."; + return Task.CompletedTask; + } + + return Task.CompletedTask; + } + + private void GetHotWalletAddress(string hotWalletName) + { + var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(hotWalletName, false); + + this.HotWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; + + if (this.HotWalletAddress == null) + { + this.Alert = $"The cold staking account does not exist on wallet {hotWalletName}."; + return; + } + } + + private void ChangePayToScript() + { + this.PayToScript = !this.PayToScript; + } + + private async Task Setup() + { + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.ColdWalletAddress)) { this.Alert = "Your cold wallet address is missing"; return; } + if (string.IsNullOrEmpty(this.HotWalletAddress)) { this.Alert = "Your hot wallet address is missing"; return; } + + this.Alert = string.Empty; + + try + { + Transaction transaction = this.ColdStakingManager.GetColdStakingSetupTransaction( + this.WalletTransactionHandler, + this.ColdWalletAddress, + this.HotWalletAddress, + this.walletname, + "account 0", + this.Password, + new Money(this.Amount, MoneyUnit.BTC), + new Money(this.Fee, MoneyUnit.BTC), + this.SegwitChangeAddress, + this.PayToScript); + + await this.BroadcasterManager.BroadcastTransactionAsync(transaction); + + var res = this.BroadcasterManager.GetTransaction(transaction.GetHash()); + + if (res.TransactionBroadcastState == Connection.Broadcasting.TransactionBroadcastState.FailedBroadcast) + { + this.Alert = res.ErrorMessage; + return; + } + } + catch (Exception ex) + { + Alert = ex.Message; + return; + } + + NavigationManager.NavigateTo("coldstaking"); + } +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor new file mode 100644 index 000000000..680d10bb1 --- /dev/null +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor @@ -0,0 +1,78 @@ +@page "/coldstaking-enablewallet" + +@using Blockcore.Features.ColdStaking +@using Blockcore.Features.Wallet.Interfaces +@using Blockcore.Base.Deployments +@using NBitcoin; + +@inject IWalletManager WalletManager +@inject NavigationManager NavigationManager +@inject NodeDeployments NodeDeployments + +@if (!NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.CheckColdStakeVerify)) +{ +

Cold staking is not activated

+ return; +} + +

Enable cold staking on an existing wallet

+ +
+
+ Wallet Name: +
+ +
+ + +
+
+ Password: +
+ +
+ +
+ +
+ +@code +{ + ColdStakingManager ColdStakingManager; + + string Alert { get; set; } + + private string WalletName { get; set; } + + private string Password { get; set; } + + public bool IsColdWalletAccount { get; set; } + + protected override Task OnInitializedAsync() + { + ColdStakingManager = this.WalletManager as ColdStakingManager; + + return Task.CompletedTask; + } + + private void CreateColdStakeAccount() + { + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter your password"; return; } + if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "Please enter your wallet name"; return; } + this.Alert = string.Empty; + + this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, true, this.Password); + this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, false, this.Password); + } + +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor index 610435b3f..ea3b31470 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor @@ -13,30 +13,19 @@ @inject IBroadcasterManager BroadcasterManager @inject NodeDeployments NodeDeployments -

Coldstaking setup wallet: @walletname

- -

Setup cold staking.

+
+

Coldstaking setup for: @walletname

+
+
+
@{ var accountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); - - - - - - - - - - - - - - - -
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount
-
+
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
@@ -44,22 +33,25 @@
- from wallet: @walletname + from: @walletname
-
- @foreach (var walletNameItem in this.WalletManager.GetWalletsNames().Where(w => w != walletname)) - { - - } -
-
HotWalletAddress:
+ +
+
+ @foreach (var walletNameItem in this.WalletManager.GetWalletsNames().Where(w => w != walletname)) + { + + } +
+
+
@@ -68,7 +60,7 @@
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
@@ -78,7 +70,7 @@
- Optional (default to low) + Optional (default to low)
@@ -86,7 +78,7 @@
Password:
- +
@@ -94,7 +86,7 @@
- +
diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor new file mode 100644 index 000000000..338bc7b25 --- /dev/null +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor @@ -0,0 +1,86 @@ +@page "/coldstakeview/{walletName}/{accountname}" + +@using Blockcore.Features.Wallet.Interfaces +@using NBitcoin; +@using Blockcore.Features.Wallet.Api.Controllers +@using Blockcore.Features.Wallet.Api.Models + +@inject NavigationManager NavigationManager +@inject IWalletManager WalletManager +@inject Network Network + +@{ + var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); + +
+

Cold Staking Dashboard for @walletname

+
+ + + +
+
+ +
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
+ // For now just show last 100 trx of history. + var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); + +
+ + + + + + + + + + @foreach (var history in model.AccountsHistoryModel) + { + foreach (var transaction in history.TransactionsHistory) + { + + + + + + } + } + +

TYPE

AMOUNT

BLOCK

@transaction.Type

@transaction.Amount

@transaction.ConfirmedInBlock

+
+} + +@code { + + [Parameter] + public string walletname { get; set; } + [Parameter] + public string accountname { get; set; } + + private void NavigateToEnableWallet() + { + NavigationManager.NavigateTo("coldstaking-enablewallet"); + } + private void NavigateToWithdraw(string walletName) + { + NavigationManager.NavigateTo("coldstaking-withdraw/" + walletName); + } + + private void NavigateToSetup(string walletName) + { + NavigationManager.NavigateTo("coldstaking-setup/" + walletName); + } + private void NavigateToDelegate(string walletName) + { + NavigationManager.NavigateTo("coldstaking-delegate/" + walletName); + } + + private void NavigateToViewTx(uint256 txId) + { + NavigationManager.NavigateTo("coldStakeviewtx"); + } +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor index d79c8d80c..bbd0de63f 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor @@ -13,9 +13,11 @@ @inject IBroadcasterManager BroadcasterManager @inject NodeDeployments NodeDeployments -

Coldstaking withdraw wallet: @walletname

- -

Withdraw form a coldstaking cold wallet.

+
+

Cold Staking Withdrawal To: @walletname

+
+
+
@{ var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletname), true); @@ -23,24 +25,18 @@ { var coldAccountBalance = ColdStakingManager.GetBalances(walletname, coldStakingAccount.Name).Single(); -

Amount Confirmed: @coldAccountBalance.AmountConfirmed

-

Amount Unconfirmed: @coldAccountBalance.AmountUnconfirmed

-

Spendable Amount: @coldAccountBalance.SpendableAmount

- } -
-
-
- Password: +
+

@coldAccountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@coldAccountBalance.AmountUnconfirmed (unconfirmed)

- -
+ }
Address:
- - + +
@@ -49,7 +45,7 @@
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
@@ -59,12 +55,19 @@
- Optional (default to low) + Optional (default to low) +
+
+ +
+
+ Password:
+
- +
From 645b149d3aa8c89367ba4844f4a2f2e0a3e4e77c Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 24 May 2020 13:43:41 +0100 Subject: [PATCH 11/44] Update favicon --- .../UI/wwwroot/favicon.ico | Bin 32038 -> 5430 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/favicon.ico b/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/favicon.ico index a3a799985c43bc7309d701b2cad129023377dc71..5c8d9bcf55722d54d10b98d059f8bafa82da6498 100644 GIT binary patch literal 5430 zcmeH~Pl!!X9LLX_G4sfu88MX7JgG4eO0ltcq9hVwYoRE!L2885s7V$y8)Qi&!^)p1 z3wh&TvyretLo=n=V2B!d=Jw+Lj@*3duZKH@tKKEd+TM~ zzm|~?gXY`){(+*7L+g4SoPbErKh$i@AhVR=Yh`$Xp3V`}&LJOhnGSq*gaPhb5lX=- zP(8{Sg(qU2$;XHPU4;8QoC5t0s%0|~+6$^9!=Re<6n4NgsFZ2lZ-xi(6PV?{_(A(N ztbsZxmlbRNB?kNkuCCkGIz0;uApzsDW|EJ=dvJA1wN=|y<7dNIO!e^v=o^>P3i7MQ z^}O2d&_;Olzum3YtDnL()t$>4*N}4TK_@>{T^Z}HUFjb zThLa`sJ1>kwb@nB_N!OrTL13*>+H1_bQaV8Gvzj{S?sEtQob#gy6g(`$Q$D;p{A$1;G0AY0^TsiNJqpyAE z2Bbk}-EvqI{gVhigY6LMTpi=VqUbMUyty&Pj1w9~KhAh@WB==qt}Sl;i#w-r;{Wyh zck-}qZLQ|}H=*ASZ#>UYO?_l@HMEthYU&`AI)4#T5z`r8{}1hfnsO@GY}(qv25U35 tmXB>YymYW}rvFfzNoSM&J{(PF>xmn|X6qA>gl6cl*`y6*7@s|E?Qb@-%@hCt literal 32038 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 Date: Sun, 24 May 2020 13:47:44 +0100 Subject: [PATCH 12/44] Update staking UI --- .../UI/Pages/Stake.razor | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor index 66e25c972..0ab8e4030 100644 --- a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor +++ b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor @@ -11,9 +11,11 @@ @inject IPosMinting PosMinting @inject Network Network -

Staking

- -

Information about staking.

+
+

Staking

+
+
+
@{ if (this.StakingEnabled) @@ -29,14 +31,14 @@ Staking disabled
} - -
- - - + +
+
+ - - + + + @@ -47,15 +49,19 @@ { var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - - + + + } } }
Wallet / AccountBalanceWalletConfirmed balanceUnconfirmed balance
@walletName / @account.Name
@walletName @accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed
+ + + if (!this.StakingEnabled) { @@ -70,17 +76,17 @@
Password:
- +
- +
} else {
- +
} From 79ad189f745e6f405acb8e04b9bfc0719a303492 Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 24 May 2020 13:49:00 +0100 Subject: [PATCH 13/44] Merge index & peers, update UI --- .../UI/Pages/AddNodes.razor | 45 ---------- .../UI/Pages/Index.razor | 86 ++++++++++++++++--- .../UI/Pages/Logs.razor | 6 +- .../UI/Pages/Peers.razor | 44 ---------- .../UI/Shared/NavMenu.razor | 6 -- 5 files changed, 79 insertions(+), 108 deletions(-) delete mode 100644 src/Features/Blockcore.Features.NodeHost/UI/Pages/AddNodes.razor delete mode 100644 src/Features/Blockcore.Features.NodeHost/UI/Pages/Peers.razor diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/AddNodes.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/AddNodes.razor deleted file mode 100644 index b2ddc3595..000000000 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/AddNodes.razor +++ /dev/null @@ -1,45 +0,0 @@ -@page "/add-nodes" - -@using Blockcore.Utilities.Extensions - -@inject Blockcore.Connection.IConnectionManager ConnectionManager - -

Add new nodes

- -

Add the IP address of known network peers.

- -@{ -
-
- Node ip: -
- -
- add -
-
- -
- -
- -
-
@Alert
-
-} - -@code -{ - private string NodeIp { get; set; } - - string Alert { get; set; } - - private void Addnode() - { - var endpoint = this.NodeIp.ToIPEndPoint(this.ConnectionManager.Network.DefaultPort); - - this.ConnectionManager.AddNodeAddress(endpoint); - - this.Alert = $"node {endpoint} added"; - } -} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index 0adaee9c4..6296a0e29 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -1,5 +1,7 @@ @page "/" +@using Blockcore.Utilities.Extensions + @inject IFullNode FullNode @inject NBitcoin.Network Network @inject NBitcoin.ChainIndexer ChainIndexer @@ -7,26 +9,86 @@ @inject Blockcore.Interfaces.IInitialBlockDownloadState InitialBlockDownloadState @inject NavigationManager NavigationManager -

@this.Network.Name node.

+
+

@this.Network.CoinTicker.ToUpper() Node

+
+
+ +
+ +
+ + +
+
-@{ - if (this.InitialBlockDownloadState.IsInitialBlockDownload()) - { -

In IBD

- } +
-

Connected peers: @this.ConnectionManager.ConnectedPeers.Count()

-

Current tip at height: @this.ChainIndexer.Tip.Height

-

Current tip Hash: @this.ChainIndexer.Tip.HashBlock

+
+
@Alert
+
-
+@{ + + + + + + + + + + + + + + + + +
Connected peers:@this.ConnectionManager.ConnectedPeers.Count()
Current tip at height:@this.ChainIndexer.Tip.Height
Current tip Hash:@this.ChainIndexer.Tip.HashBlock
- - +if (this.InitialBlockDownloadState.IsInitialBlockDownload()) +{ +

In IBD

} + +
+ + + + + + + + + + + @foreach (var peer in this.ConnectionManager.ConnectedPeers) + { + + + + + + + } + +
IP AddressInboundAgentVersion
@peer.RemoteSocketEndpoint.ToString()@peer.Inbound@peer.PeerVersion?.UserAgent@peer.PeerVersion?.Version
+
+} @code { + private string NodeIp { get; set; } + string Alert { get; set; } + private void Addnode() + { + var endpoint = this.NodeIp.ToIPEndPoint(this.ConnectionManager.Network.DefaultPort); + + this.ConnectionManager.AddNodeAddress(endpoint); + + this.Alert = $"node {endpoint} added"; + } private void Shutdown() { this.FullNode?.NodeLifetime.StopApplication(); diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Logs.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Logs.razor index 042863632..d0b000de8 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Logs.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Logs.razor @@ -2,7 +2,11 @@ @inject IFullNode FullNode -

Node logs

+
+

Node Logs

+
+
+
@{
diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Peers.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Peers.razor
deleted file mode 100644
index 2fa770b77..000000000
--- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Peers.razor
+++ /dev/null
@@ -1,44 +0,0 @@
-@page "/peers"
-
-@inject Blockcore.Connection.IConnectionManager ConnectionManager
-@inject NavigationManager NavigationManager
-
-

Connected peers

- -

Information about connected peers.

- -@{ -
- -
-
- - - - - - - - - - - @foreach (var peer in this.ConnectionManager.ConnectedPeers) - { - - - - - - - } - -
IpInboundAgentVersion
@peer.RemoteSocketEndpoint.ToString()@peer.Inbound@peer.PeerVersion?.UserAgent@peer.PeerVersion?.Version
-} - -@code -{ - private void NavigateToAddNodes() - { - NavigationManager.NavigateTo("add-nodes"); - } -} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor index 0a9bba482..36679e314 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor @@ -18,12 +18,6 @@ - - @{ var items = fullnode.NodeService>(); foreach (var item in items) From 2d8dc00f5efbd229eac7aa0eae587da62c1142f9 Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 24 May 2020 13:51:35 +0100 Subject: [PATCH 14/44] Update Wallet UI --- .../UI/Pages/WalletAccount.razor | 70 ++++++++----------- .../UI/Pages/WalletReceive.razor | 49 +++++++++---- .../UI/Pages/WalletSend.razor | 46 +++++------- .../UI/Pages/Wallets.razor | 34 +++++---- 4 files changed, 104 insertions(+), 95 deletions(-) diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index a5b8ef2fc..0130fb196 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -9,46 +9,32 @@ @inject IWalletManager WalletManager @inject Network Network -

Wallet Account: @walletname / @accountname

@{ - var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); +var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); -
- - -
-
- - - - - - - - - - - - - - - -
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount
-
+
+

Wallet Account: @walletname

+
+ + +
+
-

Wallet History

+
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
- // For now just show last 100 trx of history. - var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); +// For now just show last 100 trx of history. +var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); - - +
+
+ - - - - - + + + @@ -56,17 +42,16 @@ { foreach (var transaction in history.TransactionsHistory) { - - - - - - + @*@onclick="() => { NavigateToViewTx(transaction.Id); }" > *@ + + + } }
TypeBlockAmountTo AddressTxID

TYPE

AMOUNT

BLOCK

@transaction.Type@transaction.ConfirmedInBlock@transaction.Amount@transaction.ToAddress@transaction.Id

@transaction.Type

@transaction.Amount

@transaction.ConfirmedInBlock

+ } @code { @@ -90,4 +75,9 @@ { NavigationManager.NavigateTo("wallets"); } + + private void NavigateToViewTx(uint256 txId) + { + NavigationManager.NavigateTo("coldStakeviewtx"); + } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor index d3d918f5c..2999a911e 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor @@ -7,17 +7,47 @@ @inject IWalletManager WalletManager @inject NavigationManager NavigationManager -

Receive Coins

- -

Generate receive address for @walletname / @accountname

+
+

Receive to: @walletname

+
+
+
@{ var result = this.WalletManager.GetUnusedAddress(new WalletAccountReference(walletname, accountname)); -
    -
  • Address: @result.Address
  • -
  • Segwit Address: @result.Bech32Address
  • -
+
+ + + + + + + + + + + +
Address:@result.Address
Segwit Address:@result.Bech32Address
+
+ + @* TODO: Add Copy Paste Functionality +
+
+ Address: +
+ + +
+ +
+
+ Segwit Address: +
+ + +
*@ + } @code { @@ -26,9 +56,4 @@ public string walletname { get; set; } [Parameter] public string accountname { get; set; } - - private void NavigateToWalletAccount(string walletName, string accountname) - { - NavigationManager.NavigateTo("walletaccount/" + walletName + "/" + accountname); - } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index 549157b0a..6f0527633 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -14,64 +14,54 @@ @inject IWalletTransactionHandler WalletTransactionHandler @inject IBroadcasterManager BroadcasterManager -

Send Coins: @walletname / @accountname

+ +
+

Send coins from: @walletname

+
+
+
@{ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); -
+
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
- - - - - - - - - - - - - - - -
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount
- -
- To Address: + To Address:
- Amount: + Amount:
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
- Fee: + Fee:
- Optional (default to low) + Optional (default to low)
- Wallet Password: + Password:
- +
@@ -214,4 +204,4 @@ this.SentTransactionHash = transactionResult.GetHash(); this.TransactionHex = transactionResult.ToHex(this.Network.Consensus.ConsensusFactory); } -} \ No newline at end of file +}ins from: te \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor index 16f9099d0..865caa845 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor @@ -12,22 +12,25 @@ @inject Network Network @inject IPooledTransaction PooledTransaction -

Wallets

- -

Information about the deployed wallets.

- @{ -

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

+
+

Wallet Details

+
+ + + + +
+
+ +

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

+
- - - - -

- - +
+
+ - + @@ -40,8 +43,8 @@ { var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - - + + @@ -50,6 +53,7 @@ }
Wallet / AccountWallet Confirmed balance Unconfirmed balance
@walletName / @account.Name
@walletName @accountBalance.AmountConfirmed @accountBalance.AmountUnconfirmed
+
} @code From 458f88c44d496c387b35e843c661905ef8dedb3f Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 24 May 2020 13:52:26 +0100 Subject: [PATCH 15/44] Update Coldstake UI, Add CS History & CD Delegate --- .../UI/Pages/ColdStake.razor | 157 +++++---------- .../UI/Pages/ColdStakeDelegate.razor | 181 ++++++++++++++++++ .../UI/Pages/ColdStakeEnableWallet.razor | 78 ++++++++ .../UI/Pages/ColdStakeSetup.razor | 56 +++--- .../UI/Pages/ColdStakeView.razor | 86 +++++++++ .../UI/Pages/ColdStakeWithdraw.razor | 39 ++-- 6 files changed, 437 insertions(+), 160 deletions(-) create mode 100644 src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor create mode 100644 src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor create mode 100644 src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index 75d33774b..199ac9337 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -12,133 +12,68 @@ @if (!NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.CheckColdStakeVerify)) {

Cold staking is not activated

+
+ +
return; } -

Cold staking wallets

- -

Enable cold staking on an existing wallet.

- -
-
-
- Wallet Name: -
- +
+

Cold Staking

+
+
+
-
-
- Password: -
- -
- -
- -
-
- -

Information about the deployed wallets.

- -@{ - - +@{ +
+
+ - - - - + + + + + - @{ - foreach (var walletName in this.WalletManager.GetWalletsNames()) - { + @foreach (var walletName in this.WalletManager.GetWalletsNames()) { + + + + @foreach (var account in this.WalletManager.GetAccounts(walletName)) { + + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + + + var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); - if (coldStakingAccount != null) - { + + if (coldStakingAccount != null) { var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); - - - - - - - - } - else - { - - - - - - + } var hotStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), false); - if (hotStakingAccount != null) - { + + if (hotStakingAccount != null) { var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); - - - - - - - - } - else - { - - - - - - - } - - foreach (var account in this.WalletManager.GetAccounts(walletName)) - { - var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - - - - - - - + } } - } + + }
Wallet / AccountConfirmed balanceUnconfirmed balanceActionWalletAccount balanceCold balanceHot balance
@walletName@accountBalance.AmountConfirmed
@walletName / @coldStakingAccount.Name@coldAccountBalance.AmountConfirmed@coldAccountBalance.AmountUnconfirmed - @if (coldAccountBalance.AmountConfirmed + coldAccountBalance.AmountUnconfirmed > 0) - { - - } -
@walletName---
@coldAccountBalance.AmountConfirmed
@walletName / @hotStakingAccount.Name@hotAccountBalance.AmountConfirmed@hotAccountBalance.AmountUnconfirmed -
@walletName---
@walletName / @account.Name@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed - @if (accountBalance.AmountConfirmed + accountBalance.AmountUnconfirmed > 0) - { - - } -
@hotAccountBalance.AmountConfirmed
-} - +
+ } @code { ColdStakingManager ColdStakingManager; string Alert { get; set; } - private string WalletName { get; set; } - - private string Password { get; set; } - - public bool IsColdWalletAccount { get; set; } - protected override Task OnInitializedAsync() { ColdStakingManager = this.WalletManager as ColdStakingManager; @@ -146,16 +81,10 @@ return Task.CompletedTask; } - private void CreateColdStakeAccount() + private void NavigateToEnableWallet() { - if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } - if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "Please enter a wallet name"; return; } - this.Alert = string.Empty; - - this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, true, this.Password); - this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, false, this.Password); + NavigationManager.NavigateTo("coldstaking-enablewallet"); } - private void NavigateToWithdraw(string walletName) { NavigationManager.NavigateTo("coldstaking-withdraw/" + walletName); @@ -165,4 +94,12 @@ { NavigationManager.NavigateTo("coldstaking-setup/" + walletName); } + private void NavigateToDelegate(string walletName) + { + NavigationManager.NavigateTo("coldstaking-delegate/" + walletName); + } + private void NavigateToColdStakeView(string walletName) + { + NavigationManager.NavigateTo("coldstakeview/" + walletName + "/coldStakingColdAddresses"); + } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor new file mode 100644 index 000000000..957c7fd25 --- /dev/null +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor @@ -0,0 +1,181 @@ +@page "/coldstaking-delegate/{walletname}" + +@using Blockcore.Features.ColdStaking +@using Blockcore.Features.Wallet.Interfaces +@using NBitcoin; +@using Blockcore.Interfaces +@using Blockcore.Base.Deployments + +@inject IWalletManager WalletManager +@inject NavigationManager NavigationManager +@inject Network Network +@inject IWalletTransactionHandler WalletTransactionHandler +@inject IBroadcasterManager BroadcasterManager +@inject NodeDeployments NodeDeployments + +
+

Delegate Staking From: @walletname

+
+
+
+ +@{ + var accountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); + +
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
+ +
+
+ Delegated Staking Address: +
+ +
+ +
+
+ Amount: +
+ +
+ @this.Network.CoinTicker.ToUpper() +
+
+ +
+
+ Fee: +
+ +
+ Optional (default to low) +
+
+ +
+
+ Password: +
+ +
+ +
+ +
+ +
+ +
+ +
+
@Alert
+
+} + +@code +{ + [Parameter] + public string walletname { get; set; } + + ColdStakingManager ColdStakingManager; + + string Alert { get; set; } + + private string HotWallet { get; set; } + + private string HotWalletAddress { get; set; } + + private string ColdWalletAddress { get; set; } + + private string Password { get; set; } + + private decimal Amount { get; set; } + + private decimal Fee { get; set; } + + public bool SegwitChangeAddress { get; set; } + + public bool PayToScript { get; set; } + + protected override Task OnInitializedAsync() + { + ColdStakingManager = this.WalletManager as ColdStakingManager; + + this.Fee = new Money(this.Network.MinTxFee).ToDecimal(MoneyUnit.BTC); + + var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(this.walletname, true); + + this.SegwitChangeAddress = this.NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.Witness); + + this.ColdWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; + + if (this.ColdWalletAddress == null) + { + this.Alert = "The cold staking account does not exist."; + return Task.CompletedTask; + } + + return Task.CompletedTask; + } + + private void GetHotWalletAddress(string hotWalletName) + { + var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(hotWalletName, false); + + this.HotWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; + + if (this.HotWalletAddress == null) + { + this.Alert = $"The cold staking account does not exist on wallet {hotWalletName}."; + return; + } + } + + private void ChangePayToScript() + { + this.PayToScript = !this.PayToScript; + } + + private async Task Setup() + { + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } + if (string.IsNullOrEmpty(this.ColdWalletAddress)) { this.Alert = "Your cold wallet address is missing"; return; } + if (string.IsNullOrEmpty(this.HotWalletAddress)) { this.Alert = "Your hot wallet address is missing"; return; } + + this.Alert = string.Empty; + + try + { + Transaction transaction = this.ColdStakingManager.GetColdStakingSetupTransaction( + this.WalletTransactionHandler, + this.ColdWalletAddress, + this.HotWalletAddress, + this.walletname, + "account 0", + this.Password, + new Money(this.Amount, MoneyUnit.BTC), + new Money(this.Fee, MoneyUnit.BTC), + this.SegwitChangeAddress, + this.PayToScript); + + await this.BroadcasterManager.BroadcastTransactionAsync(transaction); + + var res = this.BroadcasterManager.GetTransaction(transaction.GetHash()); + + if (res.TransactionBroadcastState == Connection.Broadcasting.TransactionBroadcastState.FailedBroadcast) + { + this.Alert = res.ErrorMessage; + return; + } + } + catch (Exception ex) + { + Alert = ex.Message; + return; + } + + NavigationManager.NavigateTo("coldstaking"); + } +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor new file mode 100644 index 000000000..680d10bb1 --- /dev/null +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor @@ -0,0 +1,78 @@ +@page "/coldstaking-enablewallet" + +@using Blockcore.Features.ColdStaking +@using Blockcore.Features.Wallet.Interfaces +@using Blockcore.Base.Deployments +@using NBitcoin; + +@inject IWalletManager WalletManager +@inject NavigationManager NavigationManager +@inject NodeDeployments NodeDeployments + +@if (!NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.CheckColdStakeVerify)) +{ +

Cold staking is not activated

+ return; +} + +

Enable cold staking on an existing wallet

+ +
+
+ Wallet Name: +
+ +
+ + +
+
+ Password: +
+ +
+ +
+ +
+ +@code +{ + ColdStakingManager ColdStakingManager; + + string Alert { get; set; } + + private string WalletName { get; set; } + + private string Password { get; set; } + + public bool IsColdWalletAccount { get; set; } + + protected override Task OnInitializedAsync() + { + ColdStakingManager = this.WalletManager as ColdStakingManager; + + return Task.CompletedTask; + } + + private void CreateColdStakeAccount() + { + if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter your password"; return; } + if (string.IsNullOrEmpty(this.WalletName)) { this.Alert = "Please enter your wallet name"; return; } + this.Alert = string.Empty; + + this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, true, this.Password); + this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, false, this.Password); + } + +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor index 610435b3f..ea3b31470 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor @@ -13,30 +13,19 @@ @inject IBroadcasterManager BroadcasterManager @inject NodeDeployments NodeDeployments -

Coldstaking setup wallet: @walletname

- -

Setup cold staking.

+
+

Coldstaking setup for: @walletname

+
+
+
@{ var accountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); - - - - - - - - - - - - - - - -
Amount ConfirmedAmount UnconfirmedSpendable Amount
@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@accountBalance.SpendableAmount
-
+
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
@@ -44,22 +33,25 @@
- from wallet: @walletname + from: @walletname
-
- @foreach (var walletNameItem in this.WalletManager.GetWalletsNames().Where(w => w != walletname)) - { - - } -
-
HotWalletAddress:
+ +
+
+ @foreach (var walletNameItem in this.WalletManager.GetWalletsNames().Where(w => w != walletname)) + { + + } +
+
+
@@ -68,7 +60,7 @@
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
@@ -78,7 +70,7 @@
- Optional (default to low) + Optional (default to low)
@@ -86,7 +78,7 @@
Password:
- +
@@ -94,7 +86,7 @@
- +
diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor new file mode 100644 index 000000000..338bc7b25 --- /dev/null +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor @@ -0,0 +1,86 @@ +@page "/coldstakeview/{walletName}/{accountname}" + +@using Blockcore.Features.Wallet.Interfaces +@using NBitcoin; +@using Blockcore.Features.Wallet.Api.Controllers +@using Blockcore.Features.Wallet.Api.Models + +@inject NavigationManager NavigationManager +@inject IWalletManager WalletManager +@inject Network Network + +@{ + var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); + +
+

Cold Staking Dashboard for @walletname

+
+ + + +
+
+ +
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@accountBalance.AmountUnconfirmed (unconfirmed)

+
+ // For now just show last 100 trx of history. + var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); + +
+ + + + + + + + + + @foreach (var history in model.AccountsHistoryModel) + { + foreach (var transaction in history.TransactionsHistory) + { + + + + + + } + } + +

TYPE

AMOUNT

BLOCK

@transaction.Type

@transaction.Amount

@transaction.ConfirmedInBlock

+
+} + +@code { + + [Parameter] + public string walletname { get; set; } + [Parameter] + public string accountname { get; set; } + + private void NavigateToEnableWallet() + { + NavigationManager.NavigateTo("coldstaking-enablewallet"); + } + private void NavigateToWithdraw(string walletName) + { + NavigationManager.NavigateTo("coldstaking-withdraw/" + walletName); + } + + private void NavigateToSetup(string walletName) + { + NavigationManager.NavigateTo("coldstaking-setup/" + walletName); + } + private void NavigateToDelegate(string walletName) + { + NavigationManager.NavigateTo("coldstaking-delegate/" + walletName); + } + + private void NavigateToViewTx(uint256 txId) + { + NavigationManager.NavigateTo("coldStakeviewtx"); + } +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor index d79c8d80c..bbd0de63f 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor @@ -13,9 +13,11 @@ @inject IBroadcasterManager BroadcasterManager @inject NodeDeployments NodeDeployments -

Coldstaking withdraw wallet: @walletname

- -

Withdraw form a coldstaking cold wallet.

+
+

Cold Staking Withdrawal To: @walletname

+
+
+
@{ var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletname), true); @@ -23,24 +25,18 @@ { var coldAccountBalance = ColdStakingManager.GetBalances(walletname, coldStakingAccount.Name).Single(); -

Amount Confirmed: @coldAccountBalance.AmountConfirmed

-

Amount Unconfirmed: @coldAccountBalance.AmountUnconfirmed

-

Spendable Amount: @coldAccountBalance.SpendableAmount

- } -
-
-
- Password: +
+

@coldAccountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@coldAccountBalance.AmountUnconfirmed (unconfirmed)

- -
+ }
Address:
- - + +
@@ -49,7 +45,7 @@
- @this.Network.CoinTicker.ToUpper() + @this.Network.CoinTicker.ToUpper()
@@ -59,12 +55,19 @@
- Optional (default to low) + Optional (default to low) +
+ + +
+
+ Password:
+
- +
From 29752fe8b2a82c07ea2ff628818e2b8cb8366c2a Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 25 May 2020 11:51:45 +0100 Subject: [PATCH 16/44] Add timestamp to tx history + button spaces --- .../UI/Pages/ColdStakeView.razor | 8 +++++--- .../UI/Pages/WalletAccount.razor | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor index 338bc7b25..ed2db90af 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor @@ -15,8 +15,8 @@

Cold Staking Dashboard for @walletname

- - + +
@@ -33,6 +33,7 @@

TYPE

+

TIMESTAMP

AMOUNT

BLOCK

@@ -42,8 +43,9 @@ { foreach (var transaction in history.TransactionsHistory) { - + @* @onclick="() => { NavigateToViewTx(transaction.Id); }" *@

@transaction.Type

+

@transaction.Timestamp

@transaction.Amount

@transaction.ConfirmedInBlock

diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index 0130fb196..79d844218 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -15,7 +15,7 @@ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Sin

Wallet Account: @walletname

- +
@@ -33,6 +33,7 @@ var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new Walle

TYPE

+

DATE

AMOUNT

BLOCK

@@ -44,6 +45,7 @@ var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new Walle { @*@onclick="() => { NavigateToViewTx(transaction.Id); }" > *@

@transaction.Type

+

@transaction.Timestamp

@transaction.Amount

@transaction.ConfirmedInBlock

From a4465e2cd0176721069a51d41909ccc20166512b Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 25 May 2020 11:51:58 +0100 Subject: [PATCH 17/44] Add button spacing --- .../UI/Pages/Index.razor | 4 ++-- .../UI/Pages/WalletCreate.razor | 13 +++++++++---- .../UI/Pages/WalletRecover.razor | 15 ++++++++++----- .../UI/Pages/WalletSend.razor | 2 +- .../UI/Pages/Wallets.razor | 8 ++++---- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index 6296a0e29..a8cc59afc 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -15,9 +15,9 @@
- +
- +
diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor index c89bf59d0..cd1d51757 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor @@ -9,7 +9,12 @@ @inject Blockcore.Utilities.IDateTimeProvider DateTimeProvider @inject IWalletSyncManager WalletSyncManager -

Create a Wallet

+
+

Create a Wallet

+
+
+
+

Create your wallet by generating a Mnemonic & adding an optional phrase. Then give your wallet a name & password.

@{ @@ -29,7 +34,7 @@
Passphrase (optional):
- +

Important: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

@@ -38,14 +43,14 @@
Wallet name:
- +
Wallet Password:
- +
diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor index 7992a7148..82fda0174 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor @@ -9,14 +9,19 @@ @inject Blockcore.Utilities.IDateTimeProvider DateTimeProvider @inject IWalletSyncManager WalletSyncManager -

Recover a Wallet

+
+

Recover a Wallet

+
+
+
+

Recover your wallet by entering your Mnemonic & your passphrase. Then give your wallet a name & password.

@{
Mnemonic
- +

Reminder: The Mnemonic is your wallet and must be kept safe and secure.

@@ -24,7 +29,7 @@
Passphrase (optional):
- +

Reminder: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

@@ -32,14 +37,14 @@
Wallet name:
- +
Wallet Password:
- +
diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index 6f0527633..f5fe46f32 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -204,4 +204,4 @@ this.SentTransactionHash = transactionResult.GetHash(); this.TransactionHex = transactionResult.ToHex(this.Network.Consensus.ConsensusFactory); } -}ins from: te \ No newline at end of file +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor index 865caa845..171ac259c 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor @@ -16,10 +16,10 @@

Wallet Details

- - - - + + + +
From ed6ecc6c22ea82d84a50e3c679ae719c02585d32 Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 25 May 2020 15:01:20 +0100 Subject: [PATCH 18/44] Fixed timestamp format --- .../UI/Pages/ColdStake.razor | 9 ++------- .../UI/Pages/ColdStakeView.razor | 6 +++--- .../UI/Pages/WalletAccount.razor | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index 199ac9337..b4f3499e3 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -12,9 +12,6 @@ @if (!NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.CheckColdStakeVerify)) {

Cold staking is not activated

-
- -
return; } @@ -39,13 +36,11 @@ @foreach (var walletName in this.WalletManager.GetWalletsNames()) { - - @walletName - + + @walletName @foreach (var account in this.WalletManager.GetAccounts(walletName)) { var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - @accountBalance.AmountConfirmed var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor index ed2db90af..0f4b638bd 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor @@ -15,7 +15,7 @@

Cold Staking Dashboard for @walletname

- +
@@ -33,7 +33,7 @@

TYPE

-

TIMESTAMP

+

DATE/TIME

AMOUNT

BLOCK

@@ -45,7 +45,7 @@ { @* @onclick="() => { NavigateToViewTx(transaction.Id); }" *@

@transaction.Type

-

@transaction.Timestamp

+

@String.Format("{0:f}", transaction.Timestamp)

@transaction.Amount

@transaction.ConfirmedInBlock

diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index 79d844218..7ff5973b9 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -33,7 +33,7 @@ var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new Walle

TYPE

-

DATE

+

DATE/TIME

AMOUNT

BLOCK

@@ -45,7 +45,7 @@ var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new Walle { @*@onclick="() => { NavigateToViewTx(transaction.Id); }" > *@

@transaction.Type

-

@transaction.Timestamp

+

@String.Format("{0:f}", transaction.Timestamp)

@transaction.Amount

@transaction.ConfirmedInBlock

From b427f9b941e1483dda7200c6ee7e6ead57a6af7b Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 26 May 2020 12:22:17 +0100 Subject: [PATCH 19/44] Hide wallets not enable & show enable button --- .../UI/Pages/ColdStake.razor | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index b4f3499e3..e62e46648 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -18,7 +18,12 @@

Cold Staking

- + @foreach (var walletName in this.WalletManager.GetWalletsNames()) { + var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + if (coldStakingWalletEnabled != null) {} else { + + } + }
@@ -36,28 +41,32 @@ @foreach (var walletName in this.WalletManager.GetWalletsNames()) { - - @walletName - @foreach (var account in this.WalletManager.GetAccounts(walletName)) { + + var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + if (coldStakingWalletEnabled != null) { + + @walletName + @foreach (var account in this.WalletManager.GetAccounts(walletName)) { - var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - @accountBalance.AmountConfirmed + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + @accountBalance.AmountConfirmed - var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); - - if (coldStakingAccount != null) { - var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); - @coldAccountBalance.AmountConfirmed - } + var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + + if (coldStakingAccount != null) { + var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); + @coldAccountBalance.AmountConfirmed + } - var hotStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), false); - - if (hotStakingAccount != null) { - var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); - @hotAccountBalance.AmountConfirmed - } + var hotStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), false); + + if (hotStakingAccount != null) { + var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); + @hotAccountBalance.AmountConfirmed + } } + } } From 689e8da935eb5f3281878785e3defc1fb4eb058d Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 26 May 2020 12:23:22 +0100 Subject: [PATCH 20/44] Add check for empty nodeip & add error --- .../UI/Pages/Index.razor | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index a8cc59afc..53582a373 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -16,9 +16,9 @@
-
- - +
+ + @@ -30,6 +30,7 @@ @{ +
@@ -46,6 +47,7 @@
+
if (this.InitialBlockDownloadState.IsInitialBlockDownload()) { @@ -57,10 +59,10 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload()) - - - - + + + + @@ -83,6 +85,9 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload()) string Alert { get; set; } private void Addnode() { + if (string.IsNullOrEmpty(this.NodeIp)) { this.Alert = "Please enter an IP address"; return; } + this.Alert = string.Empty; + var endpoint = this.NodeIp.ToIPEndPoint(this.ConnectionManager.Network.DefaultPort); this.ConnectionManager.AddNodeAddress(endpoint); From 2f5cf798593609a086e4a7ce951d908025fdb932 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 26 May 2020 12:23:56 +0100 Subject: [PATCH 21/44] Fix double spaced table --- .../UI/Pages/ColdStakeView.razor | 18 +++++++++--------- .../UI/Pages/WalletAccount.razor | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor index 0f4b638bd..1b4885939 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor @@ -28,14 +28,14 @@ // For now just show last 100 trx of history. var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); -
+
IP AddressInboundAgentVersionIP AddressInboundAgentVersion
- - - - + + + + @@ -44,10 +44,10 @@ foreach (var transaction in history.TransactionsHistory) { @* @onclick="() => { NavigateToViewTx(transaction.Id); }" *@ - - - - + + + + } } diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index 7ff5973b9..22dbab11c 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -28,14 +28,14 @@ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Sin // For now just show last 100 trx of history. var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); -
+

TYPE

DATE/TIME

AMOUNT

BLOCK

TYPEDATE/TIMEAMOUNTBLOCK

@transaction.Type

@String.Format("{0:f}", transaction.Timestamp)

@transaction.Amount

@transaction.ConfirmedInBlock

@transaction.Type@String.Format("{0:f}", transaction.Timestamp)@transaction.Amount@transaction.ConfirmedInBlock
- - - - + + + + @@ -44,10 +44,10 @@ var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new Walle foreach (var transaction in history.TransactionsHistory) { @*@onclick="() => { NavigateToViewTx(transaction.Id); }" > *@ - - - - + + + + } } From 0094690a9d0db1d25b548eda3d886a440695942e Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 26 May 2020 12:24:44 +0100 Subject: [PATCH 22/44] Only show account not enabled --- .../UI/Pages/ColdStakeEnableWallet.razor | 45 +++++++++---------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor index 680d10bb1..c0ab449ea 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor @@ -17,24 +17,28 @@

Enable cold staking on an existing wallet

-
+ +
- Wallet Name: + Wallet Name:
- @{ - foreach (var walletName in this.WalletManager.GetWalletsNames()) - { - foreach (var account in this.WalletManager.GetAccounts(walletName)) - { - + foreach (var walletName in this.WalletManager.GetWalletsNames()) { + var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + if (coldStakingWalletEnabled != null) { + } else { + foreach (var account in this.WalletManager.GetAccounts(walletName)) + { + + } } } }
-
Password: @@ -43,28 +47,15 @@
- +
@code { ColdStakingManager ColdStakingManager; - string Alert { get; set; } - private string WalletName { get; set; } - private string Password { get; set; } - - public bool IsColdWalletAccount { get; set; } - - protected override Task OnInitializedAsync() - { - ColdStakingManager = this.WalletManager as ColdStakingManager; - - return Task.CompletedTask; - } - private void CreateColdStakeAccount() { if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter your password"; return; } @@ -73,6 +64,12 @@ this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, true, this.Password); this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, false, this.Password); - } + NavigationManager.NavigateTo("coldstakeview/" + WalletName + "/coldStakingColdAddresses"); + } + protected override Task OnInitializedAsync() + { + ColdStakingManager = this.WalletManager as ColdStakingManager; + return Task.CompletedTask; + } } \ No newline at end of file From d355bd5152fcea15280d75e2024c7c3212a3f7e8 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 26 May 2020 12:27:11 +0100 Subject: [PATCH 23/44] fix display issue on table --- .../UI/Pages/WalletAccount.razor | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index 22dbab11c..54d34be81 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -32,10 +32,10 @@ var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new Walle

TYPE

DATE/TIME

AMOUNT

BLOCK

>TYPE>DATE/TIME>AMOUNT>BLOCK

@transaction.Type

@String.Format("{0:f}", transaction.Timestamp)

@transaction.Amount

@transaction.ConfirmedInBlock

>@transaction.Type>@String.Format("{0:f}", transaction.Timestamp)>@transaction.Amount>@transaction.ConfirmedInBlock
- - - - + + + + @@ -44,10 +44,10 @@ var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new Walle foreach (var transaction in history.TransactionsHistory) { @*@onclick="() => { NavigateToViewTx(transaction.Id); }" > *@ - - - - + + + + } } From d9475eb2fef1670582a4b119e2363d676bcbfb04 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 26 May 2020 17:59:01 +0100 Subject: [PATCH 24/44] enable copy to clipboard for receiving addresses --- .../UI/Pages/Index.razor | 2 +- .../UI/Pages/_Host.cshtml | 11 ++++++++ .../UI/CopyToClipboard.razor | 18 ++++++++++++ .../UI/Pages/WalletReceive.razor | 28 ++++--------------- 4 files changed, 35 insertions(+), 24 deletions(-) create mode 100644 src/Features/Blockcore.Features.Wallet/UI/CopyToClipboard.razor diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index 53582a373..c46c8df0f 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -12,7 +12,7 @@

@this.Network.CoinTicker.ToUpper() Node

-
+
diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/_Host.cshtml b/src/Features/Blockcore.Features.NodeHost/UI/Pages/_Host.cshtml index 4cf67e21e..c9bf8cf67 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/_Host.cshtml +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/_Host.cshtml @@ -32,5 +32,16 @@
+ \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/CopyToClipboard.razor b/src/Features/Blockcore.Features.Wallet/UI/CopyToClipboard.razor new file mode 100644 index 000000000..81b8f827b --- /dev/null +++ b/src/Features/Blockcore.Features.Wallet/UI/CopyToClipboard.razor @@ -0,0 +1,18 @@ +@using Microsoft.JSInterop +@inject IJSRuntime JSRuntime + +
+ +
+ +
+
+ +@code { + [Parameter] public string Text { get; set; } + + private async Task CopyTextToClipboard() + { + await JSRuntime.InvokeVoidAsync("clipboardCopy.copyText", Text); + } +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor index 2999a911e..fc6529e5a 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor @@ -17,37 +17,19 @@ var result = this.WalletManager.GetUnusedAddress(new WalletAccountReference(walletname, accountname));
-
>TYPE>DATE/TIME>AMOUNT>BLOCKTYPEDATE/TIMEAMOUNTBLOCK
>@transaction.Type>@String.Format("{0:f}", transaction.Timestamp)>@transaction.Amount>@transaction.ConfirmedInBlock@transaction.Type@String.Format("{0:f}", transaction.Timestamp)@transaction.Amount@transaction.ConfirmedInBlock
+
- - + + - - + +
Address:@result.AddressAddress:
Segwit Address:@result.Bech32AddressSegwit Address:
- - @* TODO: Add Copy Paste Functionality -
-
- Address: -
- - -
- -
-
- Segwit Address: -
- - -
*@ - } @code { From aa69ef3e316662ba573a95c65d8b4f778cd495b4 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 26 May 2020 20:31:25 +0100 Subject: [PATCH 25/44] Only CS enabled accounts available as hot wallet --- .../UI/Pages/ColdStakeDelegate.razor | 20 +------------- .../UI/Pages/ColdStakeSetup.razor | 26 ++++++++++++++++--- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor index 957c7fd25..7856e8e27 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor @@ -101,38 +101,20 @@ protected override Task OnInitializedAsync() { + //TODO Check Coldstake Address ColdStakingManager = this.WalletManager as ColdStakingManager; - this.Fee = new Money(this.Network.MinTxFee).ToDecimal(MoneyUnit.BTC); - var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(this.walletname, true); - this.SegwitChangeAddress = this.NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.Witness); - this.ColdWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; - if (this.ColdWalletAddress == null) { this.Alert = "The cold staking account does not exist."; return Task.CompletedTask; } - return Task.CompletedTask; } - private void GetHotWalletAddress(string hotWalletName) - { - var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(hotWalletName, false); - - this.HotWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; - - if (this.HotWalletAddress == null) - { - this.Alert = $"The cold staking account does not exist on wallet {hotWalletName}."; - return; - } - } - private void ChangePayToScript() { this.PayToScript = !this.PayToScript; diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor index ea3b31470..1262ad762 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor @@ -27,9 +27,11 @@

@accountBalance.AmountUnconfirmed (unconfirmed)

+ + //TODO: remove coldstake address
- ColdWalletAddress: + Cold Address:
@@ -39,18 +41,34 @@
- HotWalletAddress: + Hot Address:
+ @{ + foreach (var walletName in this.WalletManager.GetWalletsNames().Where(w => w != walletname)) { + var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + if (coldStakingWalletEnabled != null) { + + } + } + } +
+
+ + @* +
*@
From 44353026b4622f42f5a642b470157c0cf1c53a79 Mon Sep 17 00:00:00 2001 From: Hunter Date: Tue, 26 May 2020 23:56:15 +0100 Subject: [PATCH 26/44] fix enable cold stake page by removing dropdown --- .../UI/Pages/ColdStakeEnableWallet.razor | 10 +++++----- .../Blockcore.Features.Miner/UI/Pages/Stake.razor | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor index c0ab449ea..0279c9ff9 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor @@ -17,13 +17,12 @@

Enable cold staking on an existing wallet

-
Wallet Name:
- @{ foreach (var walletName in this.WalletManager.GetWalletsNames()) { var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); @@ -36,14 +35,15 @@ } } } - -
+ *@ + +
Password:
- +
diff --git a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor index 0ab8e4030..e096a7443 100644 --- a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor +++ b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor @@ -69,7 +69,7 @@
Wallet Name:
- +
From dba6bb8d0f3c15b59ad4f096418c3e20bffe5c1b Mon Sep 17 00:00:00 2001 From: dangershony Date: Wed, 27 May 2020 00:04:09 +0100 Subject: [PATCH 27/44] Add alrert to coldstaking enable page --- .../UI/Pages/ColdStakeEnableWallet.razor | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor index 0279c9ff9..b17c9128a 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor @@ -17,12 +17,12 @@

Enable cold staking on an existing wallet

-
-
- Wallet Name: -
+
+
+ Wallet Name: +
- @* @{ foreach (var walletName in this.WalletManager.GetWalletsNames()) { var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); @@ -36,19 +36,23 @@ } } *@ - -
+ +
-
-
- Password: -
- +
+
+ Password:
+ +
-
- -
+
+ +
+ +
+
@Alert
+
@code { @@ -56,6 +60,7 @@ string Alert { get; set; } private string WalletName { get; set; } private string Password { get; set; } + private void CreateColdStakeAccount() { if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter your password"; return; } @@ -66,7 +71,8 @@ this.ColdStakingManager.GetOrCreateColdStakingAccount(this.WalletName, false, this.Password); NavigationManager.NavigateTo("coldstakeview/" + WalletName + "/coldStakingColdAddresses"); - } + } + protected override Task OnInitializedAsync() { ColdStakingManager = this.WalletManager as ColdStakingManager; From 614877169881c2bea27402d37691952aa2c5cca9 Mon Sep 17 00:00:00 2001 From: dangershony Date: Thu, 28 May 2020 02:45:29 +0100 Subject: [PATCH 28/44] Attempt to disable fee checks to test xds --- .../WalletTransactionHandler.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs b/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs index 48fdd4cd2..7d19de861 100644 --- a/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs +++ b/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs @@ -229,6 +229,9 @@ protected virtual void InitializeTransactionBuilder(TransactionBuildContext cont if (context.Time.HasValue) context.TransactionBuilder.SetTimeStamp(context.Time.Value); + + // TODO: testing do not check-in + context.TransactionBuilder.StandardTransactionPolicy.CheckFee = false; } /// @@ -426,11 +429,11 @@ protected void AddFee(TransactionBuildContext context) /// The context associated with the current transaction being built. protected void AddOpReturnOutput(TransactionBuildContext context) { - if (string.IsNullOrEmpty(context.OpReturnData) && context.OpReturnRawData == null) + if (string.IsNullOrEmpty(context.OpReturnData) && context.OpReturnRawData == null) return; - + byte[] bytes = context.OpReturnRawData ?? Encoding.UTF8.GetBytes(context.OpReturnData); - + // TODO: Get the template from the network standard scripts instead Script opReturnScript = TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes); context.TransactionBuilder.Send(opReturnScript, context.OpReturnAmount ?? Money.Zero); @@ -570,4 +573,4 @@ public TransactionBuildContext(Network network) /// public bool UseSegwitChangeAddress { get; set; } } -} +} \ No newline at end of file From 8765ebe00dacaf08b44708b8663e6b2c9e2456b5 Mon Sep 17 00:00:00 2001 From: Hunter Date: Thu, 28 May 2020 09:01:58 +0100 Subject: [PATCH 29/44] Improve IBD message --- .gitignore | 3 +++ src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9907b03d7..cd87e7456 100644 --- a/.gitignore +++ b/.gitignore @@ -265,3 +265,6 @@ src/.idea/.idea.Stratis.Bitcoin.FullNode/.idea/ *.iml /src/.idea /src/Blockcore.Benchmark/BenchmarkDotNet.Artifacts/results +.vscode/launch.json +.vscode/tasks.json +.gitignore diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index c46c8df0f..a078ca57f 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -51,7 +51,7 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload()) { -

In IBD

+

Currently processing the initial block download & syncing your full node with the chain

} From 55fc5dfdbe058376c011d3a959ceb749f9e9edf1 Mon Sep 17 00:00:00 2001 From: thecrypt0hunter <36605607+thecrypt0hunter@users.noreply.github.com> Date: Thu, 28 May 2020 10:47:22 +0100 Subject: [PATCH 30/44] Update src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor Co-authored-by: Dan Gershony --- src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index a078ca57f..37952ce5d 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -51,7 +51,7 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload()) { -

Currently processing the initial block download & syncing your full node with the chain

+

Currently processing IBD (the initial block download) & syncing your node with the network

} @@ -103,4 +103,4 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload()) { NavigationManager.NavigateTo("logs"); } -} \ No newline at end of file +} From be8dac387c1c49444f125cd7a4964b6e548e5b12 Mon Sep 17 00:00:00 2001 From: Hunter Date: Thu, 28 May 2020 17:59:32 +0100 Subject: [PATCH 31/44] Fix issue with IBD message --- .../Blockcore.Features.NodeHost/UI/Pages/Index.razor | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index 37952ce5d..d8151343a 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -30,6 +30,11 @@ @{ +if (this.InitialBlockDownloadState.IsInitialBlockDownload()) +{ +

Currently processing IBD, the initial block download & syncing your node with the network

+} +
@@ -49,11 +54,6 @@
-if (this.InitialBlockDownloadState.IsInitialBlockDownload()) -{ -

Currently processing IBD (the initial block download) & syncing your node with the network

-} -
From 569350892e9dedb5069c8c40a3feb84def0b1d21 Mon Sep 17 00:00:00 2001 From: Hunter Date: Thu, 28 May 2020 18:00:14 +0100 Subject: [PATCH 32/44] Stop dupe buttons appearing to enable cold staking --- .../Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index e62e46648..6e14f3cb1 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -22,6 +22,7 @@ var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); if (coldStakingWalletEnabled != null) {} else { + break; } } From 23695ab0d023a672b8d582eb678213fbe348d3be Mon Sep 17 00:00:00 2001 From: Hunter Date: Thu, 28 May 2020 18:01:01 +0100 Subject: [PATCH 33/44] Enable drop down on cold stake enable wallet page --- .../UI/Pages/ColdStakeEnableWallet.razor | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor index b17c9128a..11e9f6465 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor @@ -22,7 +22,7 @@ Wallet Name: - @* @{ foreach (var walletName in this.WalletManager.GetWalletsNames()) { var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); @@ -35,8 +35,8 @@ } } } - *@ - + + @* *@
From 31323b305ce992a1779305557083741b5d511375 Mon Sep 17 00:00:00 2001 From: Hunter Date: Thu, 28 May 2020 18:11:55 +0100 Subject: [PATCH 34/44] fix for a single unenabled wallet --- .../UI/Pages/ColdStakeEnableWallet.razor | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor index 11e9f6465..8790ca624 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor @@ -22,7 +22,8 @@ Wallet Name:
- + @{ foreach (var walletName in this.WalletManager.GetWalletsNames()) { var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); @@ -30,13 +31,13 @@ } else { foreach (var account in this.WalletManager.GetAccounts(walletName)) { - + } } } } - @* *@ + @* *@
From 850005395a95557f45c7d02b7a44d295308cf411 Mon Sep 17 00:00:00 2001 From: dangershony Date: Thu, 28 May 2020 22:31:59 +0100 Subject: [PATCH 35/44] Revert fee check --- .../Blockcore.Features.Wallet/WalletTransactionHandler.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs b/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs index 7d19de861..b95168ac3 100644 --- a/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs +++ b/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs @@ -229,9 +229,6 @@ protected virtual void InitializeTransactionBuilder(TransactionBuildContext cont if (context.Time.HasValue) context.TransactionBuilder.SetTimeStamp(context.Time.Value); - - // TODO: testing do not check-in - context.TransactionBuilder.StandardTransactionPolicy.CheckFee = false; } /// From 98b47d1aafb85d3d282e10f7ffeff8f1ed0b0614 Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 31 May 2020 12:04:07 +0100 Subject: [PATCH 36/44] Add total node balance --- .../UI/Pages/ColdStake.razor | 75 +++++++++++++++++-- .../UI/Pages/ColdStakeView.razor | 20 +++-- .../UI/Pages/Stake.razor | 65 ++++++++++++++-- .../UI/Pages/Index.razor | 2 +- .../UI/Pages/Wallets.razor | 37 ++++++++- 5 files changed, 178 insertions(+), 21 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index 6e14f3cb1..c1d3ed4ab 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -8,6 +8,7 @@ @inject IWalletManager WalletManager @inject NavigationManager NavigationManager @inject NodeDeployments NodeDeployments +@inject Network Network @if (!NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.CheckColdStakeVerify)) { @@ -29,6 +30,19 @@
@{ + +
+
+

@totalBalance().coldBalance @this.Network.CoinTicker.ToUpper()

+

@totalUnconfirmedBalance().coldBalance (unconfirmed)

+
+ +
+

@totalBalance().balance @this.Network.CoinTicker.ToUpper()

+

@totalUnconfirmedBalance().balance (unconfirmed)

+
+
+
@@ -50,20 +64,33 @@ @foreach (var account in this.WalletManager.GetAccounts(walletName)) { var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - + + @if (@accountBalance.AmountUnconfirmed >0) { + + } else { + + } var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); if (coldStakingAccount != null) { var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); - + @if (@coldAccountBalance.AmountUnconfirmed >0) { + + } else { + + } } var hotStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), false); if (hotStakingAccount != null) { var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); - + @if (@hotAccountBalance.AmountUnconfirmed >0) { + + } else { + + } } } @@ -76,16 +103,54 @@ @code { ColdStakingManager ColdStakingManager; - string Alert { get; set; } - protected override Task OnInitializedAsync() { ColdStakingManager = this.WalletManager as ColdStakingManager; return Task.CompletedTask; } + private (dynamic balance, dynamic coldBalance) totalBalance() + { + dynamic balance = 0; + dynamic coldBalance = 0; + foreach (var walletName in this.WalletManager.GetWalletsNames()) + { + foreach (var account in this.WalletManager.GetAccounts(walletName)) + { + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + balance = balance + accountBalance.AmountConfirmed; + + var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + if (coldStakingAccount != null) { + var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); + coldBalance = coldBalance + coldAccountBalance.AmountConfirmed; + } + } + } + return (balance,coldBalance); + } + + private (dynamic balance, dynamic coldBalance) totalUnconfirmedBalance() + { + dynamic balance = 0; + dynamic coldBalance = 0; + foreach (var walletName in this.WalletManager.GetWalletsNames()) + { + foreach (var account in this.WalletManager.GetAccounts(walletName)) + { + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + balance = balance + accountBalance.AmountUnconfirmed; + var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + if (coldStakingAccount != null) { + var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); + coldBalance = coldBalance + coldAccountBalance.AmountUnconfirmed; + } + } + } + return (balance,coldBalance); + } private void NavigateToEnableWallet() { NavigationManager.NavigateTo("coldstaking-enablewallet"); diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor index 1b4885939..e780898d3 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor @@ -10,7 +10,6 @@ @inject Network Network @{ - var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single();

Cold Staking Dashboard for @walletname

@@ -21,12 +20,23 @@
-
-

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); +var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); + +
+
+

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

@accountBalance.AmountUnconfirmed (unconfirmed)

+
+ +
+

@mainAccountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

+

@mainAccountBalance.AmountUnconfirmed (unconfirmed)

+
- // For now just show last 100 trx of history. - var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); + +// For now just show last 100 trx of history. +var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 });
@accountBalance.AmountConfirmed@accountBalance.AmountConfirmed (@accountBalance.AmountUnconfirmed )@accountBalance.AmountConfirmed@coldAccountBalance.AmountConfirmed@coldAccountBalance.AmountConfirmed (@coldAccountBalance.AmountUnconfirmed )@coldAccountBalance.AmountConfirmed@hotAccountBalance.AmountConfirmed@hotAccountBalance.AmountConfirmed (@hotAccountBalance.AmountUnconfirmed )@hotAccountBalance.AmountConfirmed
diff --git a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor index e096a7443..4c5595a62 100644 --- a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor +++ b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor @@ -17,6 +17,13 @@ +
+
+

@totalBalance() @this.Network.CoinTicker.ToUpper()

+

@totalUnconfirmedBalance() (unconfirmed)

+
+
+ @{ if (this.StakingEnabled) { @@ -31,14 +38,14 @@ Staking disabled } - +
- - + + @* *@ @@ -47,12 +54,26 @@ { foreach (var account in this.WalletManager.GetAccounts(walletName)) { - var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + var mainAccountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - - + @if (@mainAccountBalance.AmountUnconfirmed >0) { + + } else { + + } + + @* var hotStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), false); + + if (hotStakingAccount != null) { + var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); + @if (@hotAccountBalance.AmountUnconfirmed >0) { + + } else { + + } + } *@ } } @@ -61,8 +82,6 @@
WalletConfirmed balanceUnconfirmed balanceMain balance (unconfirmed)Hot balance (unconfirmed)
@walletName@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed@mainAccountBalance.AmountConfirmed (@mainAccountBalance.AmountUnconfirmed )@mainAccountBalance.AmountConfirmed@hotAccountBalance.AmountConfirmed (@hotAccountBalance.AmountUnconfirmed )@hotAccountBalance.AmountConfirmed
- - if (!this.StakingEnabled) {
@@ -97,6 +116,7 @@ @code { + string Alert { get; set; } private string WalletName { get; set; } @@ -143,6 +163,35 @@ this.LoadStats(); } + private dynamic totalBalance() + { + dynamic balance = 0; + foreach (var walletName in this.WalletManager.GetWalletsNames()) + { + foreach (var account in this.WalletManager.GetAccounts(walletName)) + { + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + balance = balance + accountBalance.AmountConfirmed; + } + } + return balance; + } + + private dynamic totalUnconfirmedBalance() + { + dynamic balance = 0; + foreach (var walletName in this.WalletManager.GetWalletsNames()) + { + foreach (var account in this.WalletManager.GetAccounts(walletName)) + { + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + balance = balance + accountBalance.AmountUnconfirmed; + } + } + return balance; + } + + private void StartStaking() { if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index d8151343a..6031985bc 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -32,7 +32,7 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload()) { -

Currently processing IBD, the initial block download & syncing your node with the network

+

Currently processing the IBD (initial block download) & syncing your node with the network

}
diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor index 171ac259c..c29288f4b 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor @@ -23,8 +23,12 @@
-

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

-
+
+
+

@totalBalance() @this.Network.CoinTicker.ToUpper()

+

@totalUnconfirmedBalance() (unconfirmed)

+
+
@@ -54,6 +58,7 @@
+

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

} @code @@ -103,4 +108,32 @@ } } } + private dynamic totalBalance() + { + dynamic balance = 0; + foreach (var walletName in this.WalletManager.GetWalletsNames()) + { + foreach (var account in this.WalletManager.GetAccounts(walletName)) + { + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + balance = balance + accountBalance.AmountConfirmed; + } + } + return balance; + } + + private dynamic totalUnconfirmedBalance() + { + dynamic balance = 0; + foreach (var walletName in this.WalletManager.GetWalletsNames()) + { + foreach (var account in this.WalletManager.GetAccounts(walletName)) + { + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + balance = balance + accountBalance.AmountUnconfirmed; + } + } + return balance; + } + } \ No newline at end of file From ee58de11b65e6fffdecc7087ae8b79b7760a19ed Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 31 May 2020 12:45:00 +0100 Subject: [PATCH 37/44] add dynamic menu icon --- src/Blockcore/Interfaces/UI/INavigationItem.cs | 2 +- src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs | 2 +- src/Features/Blockcore.Features.Miner/UI/NavItem.cs | 2 +- .../Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor | 3 ++- src/Features/Blockcore.Features.Wallet/UI/NavItem.cs | 1 + 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Blockcore/Interfaces/UI/INavigationItem.cs b/src/Blockcore/Interfaces/UI/INavigationItem.cs index 01324a906..0eff28913 100644 --- a/src/Blockcore/Interfaces/UI/INavigationItem.cs +++ b/src/Blockcore/Interfaces/UI/INavigationItem.cs @@ -7,7 +7,7 @@ namespace Blockcore.Interfaces.UI public interface INavigationItem { public string Name { get; } - public string Navigation { get; } + public string Icon { get; } } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs b/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs index e17f87f1d..84e60e425 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs +++ b/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs @@ -5,7 +5,7 @@ namespace Blockcore.Features.Wallet.UI public class ColdStakingNavigationItem : INavigationItem { public string Name => "Cold Staking"; - public string Navigation => "ColdStaking"; + public string Icon => "oi-cloud"; } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Miner/UI/NavItem.cs b/src/Features/Blockcore.Features.Miner/UI/NavItem.cs index c0feec04f..f5c3fcbba 100644 --- a/src/Features/Blockcore.Features.Miner/UI/NavItem.cs +++ b/src/Features/Blockcore.Features.Miner/UI/NavItem.cs @@ -5,7 +5,7 @@ namespace Blockcore.Features.Wallet.UI public class StakeNavigationItem : INavigationItem { public string Name => "Staking"; - public string Navigation => "Stake"; + public string Icon => "oi-bolt"; } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor index 36679e314..923ff757a 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor @@ -24,7 +24,8 @@ { } diff --git a/src/Features/Blockcore.Features.Wallet/UI/NavItem.cs b/src/Features/Blockcore.Features.Wallet/UI/NavItem.cs index cae969269..836afd5fa 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/NavItem.cs +++ b/src/Features/Blockcore.Features.Wallet/UI/NavItem.cs @@ -7,5 +7,6 @@ public class WalletNavigationItem : INavigationItem public string Name => "Wallets"; public string Navigation => "Wallets"; + public string Icon => "oi-folder"; } } \ No newline at end of file From ac2eea611f8ef4e45b30a08fc2920bcf2c016899 Mon Sep 17 00:00:00 2001 From: Hunter Date: Sun, 31 May 2020 21:24:24 +0100 Subject: [PATCH 38/44] Rework UI as dark mode --- .../UI/Pages/ColdStake.razor | 165 ++++++++----- .../UI/Pages/ColdStakeDelegate.razor | 124 ++++++---- .../UI/Pages/ColdStakeEnableWallet.razor | 73 +++--- .../UI/Pages/ColdStakeSetup.razor | 183 +++++++------- .../UI/Pages/ColdStakeView.razor | 102 +++++--- .../UI/Pages/ColdStakeWithdraw.razor | 126 ++++++---- .../UI/Pages/Stake.razor | 26 +- .../UI/Pages/Index.razor | 95 ++++--- .../UI/Pages/_Host.cshtml | 4 +- .../UI/Shared/MainLayout.razor | 29 ++- .../UI/Shared/NavMenu.razor | 1 - .../wwwroot/css/bootstrap/darkstrap.min.css | 12 + .../UI/wwwroot/css/site.css | 6 +- .../UI/Pages/WalletAccount.razor | 80 +++--- .../UI/Pages/WalletBroadcastTx.razor | 109 ++++++++ .../UI/Pages/WalletCreate.razor | 79 +++--- .../UI/Pages/WalletReceive.razor | 36 +-- .../UI/Pages/WalletRecover.razor | 76 +++--- .../UI/Pages/WalletSend.razor | 232 +++++++++++------- .../UI/Pages/Wallets.razor | 88 ++++--- 20 files changed, 1022 insertions(+), 624 deletions(-) create mode 100644 src/Features/Blockcore.Features.NodeHost/UI/wwwroot/css/bootstrap/darkstrap.min.css create mode 100644 src/Features/Blockcore.Features.Wallet/UI/Pages/WalletBroadcastTx.razor diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor index c1d3ed4ab..032d7c4d2 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStake.razor @@ -28,78 +28,107 @@ }
- -@{ - -
-
-

@totalBalance().coldBalance @this.Network.CoinTicker.ToUpper()

-

@totalUnconfirmedBalance().coldBalance (unconfirmed)

-
- -
-

@totalBalance().balance @this.Network.CoinTicker.ToUpper()

-

@totalUnconfirmedBalance().balance (unconfirmed)

-
+@{ +
+
+
+
+
Main Balance
+
+
+
+

@totalBalance().balance

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@totalUnconfirmedBalance().balance (unconfirmed)
+
+
+
+
+
+
+
Cold Balance
+
+
+
+

@totalBalance().coldBalance

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@totalUnconfirmedBalance().coldBalance (unconfirmed)
+
+
+
-
- - - - - - - - - - - - @foreach (var walletName in this.WalletManager.GetWalletsNames()) { - - var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); - if (coldStakingWalletEnabled != null) { - - - @foreach (var account in this.WalletManager.GetAccounts(walletName)) { - - var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); - - @if (@accountBalance.AmountUnconfirmed >0) { - - } else { - - } - - var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); - - if (coldStakingAccount != null) { - var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); - @if (@coldAccountBalance.AmountUnconfirmed >0) { - - } else { - - } - } - - var hotStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), false); - - if (hotStakingAccount != null) { - var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); - @if (@hotAccountBalance.AmountUnconfirmed >0) { - - } else { - +
+
+
+
+

Balances

+
+
WalletAccount balanceCold balanceHot balance
@walletName@accountBalance.AmountConfirmed (@accountBalance.AmountUnconfirmed )@accountBalance.AmountConfirmed@coldAccountBalance.AmountConfirmed (@coldAccountBalance.AmountUnconfirmed )@coldAccountBalance.AmountConfirmed@hotAccountBalance.AmountConfirmed (@hotAccountBalance.AmountUnconfirmed )@hotAccountBalance.AmountConfirmed
+ + + + + + + + + + @foreach (var walletName in this.WalletManager.GetWalletsNames()) { + + var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + if (coldStakingWalletEnabled != null) { + + + @foreach (var account in this.WalletManager.GetAccounts(walletName)) { + + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + + @if (@accountBalance.AmountUnconfirmed >0) { + + } else { + + } + + var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + + if (coldStakingAccount != null) { + var coldAccountBalance = ColdStakingManager.GetBalances(walletName, coldStakingAccount.Name).Single(); + @if (@coldAccountBalance.AmountUnconfirmed >0) { + + } else { + + } + } + + var hotStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), false); + + if (hotStakingAccount != null) { + var hotAccountBalance = ColdStakingManager.GetBalances(walletName, hotStakingAccount.Name).Single(); + @if (@hotAccountBalance.AmountUnconfirmed >0) { + + } else { + + } + } + } + } - } - } - - } - } - -
WalletAccount balanceCold balanceHot balance
@walletName@accountBalance.AmountConfirmed (@accountBalance.AmountUnconfirmed )@accountBalance.AmountConfirmed@coldAccountBalance.AmountConfirmed (@coldAccountBalance.AmountUnconfirmed )@coldAccountBalance.AmountConfirmed@hotAccountBalance.AmountConfirmed (@hotAccountBalance.AmountUnconfirmed )@hotAccountBalance.AmountConfirmed
+ } + + +
+
+ - } + +} @code { ColdStakingManager ColdStakingManager; diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor index 7856e8e27..9b520143c 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor @@ -20,58 +20,92 @@ @{ - var accountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); - -
-

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

-

@accountBalance.AmountUnconfirmed (unconfirmed)

-
- -
-
- Delegated Staking Address: +var accountBalance = this.WalletManager.GetBalances(walletname, "coldStakingColdAddresses").Single(); +var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); + +
+
+
+
+
Main Balance
+
+
+
+

@mainAccountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@mainAccountBalance.AmountUnconfirmed (unconfirmed)
+
-
- -
-
- Amount: -
- -
- @this.Network.CoinTicker.ToUpper() -
-
- -
-
- Fee: -
- -
- Optional (default to low) +
+
+
+
Cold Balance
+
+
+
+

@accountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@accountBalance.AmountUnconfirmed (unconfirmed)
+
+
-
-
- Password: +
+
+
+
+
+
+ Delegated Staking Address: +
+ +
+ +
+
+ Amount: +
+ +
+ @this.Network.CoinTicker.ToUpper() +
+
+ +
+
+ Fee: +
+ +
+ Optional (default to low) +
+
+ +
+
+ Password: +
+ +
+
+ + +
+
+
@Alert
+
+
- -
- -
- -
- -
- -
- -
-
@Alert
+
} @code diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor index 8790ca624..7e451c254 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeEnableWallet.razor @@ -17,44 +17,49 @@

Enable cold staking on an existing wallet

-
-
- Wallet Name: -
- - - @* *@ -
+
+
+
+
+
+
+ Wallet Name: +
-
-
- Password: -
- -
+ +
+
+
+ Password: +
+ +
-
- -
+
+ +
-
-
@Alert
+
+
@Alert
+
+
+
+
- @code { ColdStakingManager ColdStakingManager; diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor index 1262ad762..085fb69c3 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor @@ -20,96 +20,115 @@
@{ - var accountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); - -
-

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

-

@accountBalance.AmountUnconfirmed (unconfirmed)

-
- - - //TODO: remove coldstake address -
-
- Cold Address: -
- -
- from: @walletname -
-
- -
-
- Hot Address: -
- - -
-
- @{ - foreach (var walletName in this.WalletManager.GetWalletsNames().Where(w => w != walletname)) { - var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); - if (coldStakingWalletEnabled != null) { - - } - } - } +var accountBalance = this.WalletManager.GetBalances(walletname, "coldStakingColdAddresses").Single(); +var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); + +
+
+
+
+
Main Balance
+
+
+
+

@mainAccountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@mainAccountBalance.AmountUnconfirmed (unconfirmed)
- - @* *@ -
- -
-
- Amount: -
- -
- @this.Network.CoinTicker.ToUpper() -
-
- -
-
- Fee: -
- -
- Optional (default to low) +
+
+
+
Cold Balance
+
+
+
+

@accountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@accountBalance.AmountUnconfirmed (unconfirmed)
+
+
-
-
- Password: +//TODO: remove coldstake address +
+
+
+
+
+
+ Cold Address: +
+ +
+ from: @walletname +
+
+ +
+
+ Hot Address: +
+ + +
+
+ @{ + foreach (var walletName in this.WalletManager.GetWalletsNames().Where(w => w != walletname)) { + var coldStakingWalletEnabled = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletName), true); + if (coldStakingWalletEnabled != null) { + + } + } + } +
+
+
+
+ Amount: +
+ +
+ @this.Network.CoinTicker.ToUpper() +
+
+ +
+
+ Fee: +
+ +
+ Optional (default to low) +
+
+ +
+
+ Password: +
+ +
+
+ + +
+
+
@Alert
+
+
+
- -
- -
- -
- -
- -
- -
-
@Alert
+
} @code diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor index e780898d3..cf851207f 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor @@ -23,46 +23,78 @@ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); -
-
-

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

-

@accountBalance.AmountUnconfirmed (unconfirmed)

-
- -
-

@mainAccountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

-

@mainAccountBalance.AmountUnconfirmed (unconfirmed)

-
+
+
+
+
+
Main Balance
+
+
+
+

@mainAccountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@mainAccountBalance.AmountUnconfirmed (unconfirmed)
+
+
+
+
+
+
+
Cold Balance
+
+
+
+

@accountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@accountBalance.AmountUnconfirmed (unconfirmed)
+
+
+
// For now just show last 100 trx of history. var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); -
- - - - - - - - - - - @foreach (var history in model.AccountsHistoryModel) - { - foreach (var transaction in history.TransactionsHistory) - { - @* @onclick="() => { NavigateToViewTx(transaction.Id); }" *@ - - - - - - } - } - -
TYPEDATE/TIMEAMOUNTBLOCK
@transaction.Type@String.Format("{0:f}", transaction.Timestamp)@transaction.Amount@transaction.ConfirmedInBlock
+
+
+
+
+

Balances

+
+ + + + + + + + + + + @foreach (var history in model.AccountsHistoryModel) + { + foreach (var transaction in history.TransactionsHistory) + { + @* @onclick="() => { NavigateToViewTx(transaction.Id); }" *@ + + + + + + } + } + +
TYPEDATE/TIMEAMOUNTBLOCK
@transaction.Type@String.Format("{0:f}", transaction.Timestamp)@transaction.Amount@transaction.ConfirmedInBlock
+
+
+
+
} diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor index bbd0de63f..4a52d6649 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor @@ -20,60 +20,92 @@
@{ - var coldStakingAccount = ColdStakingManager.GetColdStakingAccount(this.WalletManager.GetWallet(walletname), true); - if (coldStakingAccount != null) - { - var coldAccountBalance = ColdStakingManager.GetBalances(walletname, coldStakingAccount.Name).Single(); - -
-

@coldAccountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

-

@coldAccountBalance.AmountUnconfirmed (unconfirmed)

-
- } - -
-
- Address: -
- - -
- -
-
- Amount: -
- -
- @this.Network.CoinTicker.ToUpper() +var accountBalance = this.WalletManager.GetBalances(walletname, "coldStakingColdAddresses").Single(); +var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0").Single(); + +
+
+
+
+
Main Balance
+
+
+
+

@mainAccountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@mainAccountBalance.AmountUnconfirmed (unconfirmed)
+
- -
-
- Fee: -
- -
- Optional (default to low) +
+
+
+
Cold Balance
+
+
+
+

@accountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@accountBalance.AmountUnconfirmed (unconfirmed)
+
+
-
-
- Password: +
+
+
+
+
+
+ Address: +
+ + +
+ +
+
+ Amount: +
+ +
+ @this.Network.CoinTicker.ToUpper() +
+
+ +
+
+ Fee: +
+ +
+ Optional (default to low) +
+
+ +
+
+ Password: +
+ +
+
+ +
+
+
@Alert
+
+
- -
- -
-
- -
-
@Alert
-
- +
} @code diff --git a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor index 4c5595a62..a0a6b25a3 100644 --- a/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor +++ b/src/Features/Blockcore.Features.Miner/UI/Pages/Stake.razor @@ -16,14 +16,24 @@
- -
-
-

@totalBalance() @this.Network.CoinTicker.ToUpper()

-

@totalUnconfirmedBalance() (unconfirmed)

-
+
+
+
+
+
Main Balance
+
+
+
+

@totalBalance()

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@totalUnconfirmedBalance() (unconfirmed)
+
+
+
- @{ if (this.StakingEnabled) { @@ -40,7 +50,7 @@ }
- +
diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index 6031985bc..a984e0220 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -35,48 +35,63 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload())

Currently processing the IBD (initial block download) & syncing your node with the network

} -
-
Wallet
- - - - - - - - - - - - - - -
Connected peers:@this.ConnectionManager.ConnectedPeers.Count()
Current tip at height:@this.ChainIndexer.Tip.Height
Current tip Hash:@this.ChainIndexer.Tip.HashBlock
+
+
+
+
+
+ + + + + + + + + + + + + + + +
Connected peers:@this.ConnectionManager.ConnectedPeers.Count()
Current tip at height:@this.ChainIndexer.Tip.Height
Current tip Hash:@this.ChainIndexer.Tip.HashBlock
+
+
+
+
- -
- - - - - - - - - - - @foreach (var peer in this.ConnectionManager.ConnectedPeers) - { - - - - - - - } - -
IP AddressInboundAgentVersion
@peer.RemoteSocketEndpoint.ToString()@peer.Inbound@peer.PeerVersion?.UserAgent@peer.PeerVersion?.Version
+
+
+
+
+
+ + + + + + + + + + + @foreach (var peer in this.ConnectionManager.ConnectedPeers) + { + + + + + + + } + +
IP AddressInboundAgentVersion
@peer.RemoteSocketEndpoint.ToString()@peer.Inbound@peer.PeerVersion?.UserAgent@peer.PeerVersion?.Version
+
+
+
+
} @code diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/_Host.cshtml b/src/Features/Blockcore.Features.NodeHost/UI/Pages/_Host.cshtml index c9bf8cf67..e46ad2d3b 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/_Host.cshtml +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/_Host.cshtml @@ -12,8 +12,8 @@ Dashboard - - + + diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Shared/MainLayout.razor b/src/Features/Blockcore.Features.NodeHost/UI/Shared/MainLayout.razor index 200e89693..c06e01133 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Shared/MainLayout.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Shared/MainLayout.razor @@ -1,17 +1,20 @@ @inherits LayoutComponentBase - - -
-
- Open API - Web Socket - Blockcore + -
- @Body -
-
\ No newline at end of file +
+ @* +
*@ + +
+ @Body +
+
\ No newline at end of file diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor index 923ff757a..c7cef8a45 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor @@ -24,7 +24,6 @@ { diff --git a/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/css/bootstrap/darkstrap.min.css b/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/css/bootstrap/darkstrap.min.css new file mode 100644 index 000000000..43d80a04d --- /dev/null +++ b/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/css/bootstrap/darkstrap.min.css @@ -0,0 +1,12 @@ +/*! + * Bootswatch v4.5.0 + * Homepage: https://bootswatch.com + * Copyright 2012-2020 Thomas Park + * Licensed under MIT + * Based on Bootstrap +*//*! + * Bootstrap v4.5.0 (https://getbootstrap.com/) + * Copyright 2011-2020 The Bootstrap Authors + * Copyright 2011-2020 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */@import url("https://fonts.googleapis.com/css?family=Lato:400,700,400italic&display=swap");:root{--blue: #375a7f;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #E74C3C;--orange: #fd7e14;--yellow: #F39C12;--green: #00bc8c;--teal: #20c997;--cyan: #3498DB;--white: #fff;--gray: #888;--gray-dark: #303030;--primary: #375a7f;--secondary: #444;--success: #00bc8c;--info: #3498DB;--warning: #F39C12;--danger: #E74C3C;--light: #adb5bd;--dark: #303030;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{-webkit-box-sizing:border-box;box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:"Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size:0.9375rem;font-weight:400;line-height:1.5;color:#fff;text-align:left;background-color:#222}[tabindex="-1"]:focus:not(:focus-visible){outline:0 !important}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:0.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#00bc8c;text-decoration:none;background-color:transparent}a:hover{color:#007053;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:0.75rem;padding-bottom:0.75rem;color:#888;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:0.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role="button"]{cursor:pointer}select{word-wrap:normal}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button:not(:disabled),[type="button"]:not(:disabled),[type="reset"]:not(:disabled),[type="submit"]:not(:disabled){cursor:pointer}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{padding:0;border-style:none}input[type="radio"],input[type="checkbox"]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{outline-offset:-2px;-webkit-appearance:none}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none !important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:0.5rem;font-weight:500;line-height:1.2}h1,.h1{font-size:3rem}h2,.h2{font-size:2.5rem}h3,.h3{font-size:2rem}h4,.h4{font-size:1.40625rem}h5,.h5{font-size:1.171875rem}h6,.h6{font-size:0.9375rem}.lead{font-size:1.171875rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,0.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:0.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:0.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.171875rem}.blockquote-footer{display:block;font-size:80%;color:#888}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:0.25rem;background-color:#222;border:1px solid #dee2e6;border-radius:0.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:0.5rem;line-height:1}.figure-caption{font-size:90%;color:#888}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:0.2rem 0.4rem;font-size:87.5%;color:#fff;background-color:#222;border-radius:0.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:inherit}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container{max-width:540px}}@media (min-width: 768px){.container{max-width:720px}}@media (min-width: 992px){.container{max-width:960px}}@media (min-width: 1200px){.container{max-width:1140px}}.container-fluid,.container-sm,.container-md,.container-lg,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container,.container-sm{max-width:540px}}@media (min-width: 768px){.container,.container-sm,.container-md{max-width:720px}}@media (min-width: 992px){.container,.container-sm,.container-md,.container-lg{max-width:960px}}@media (min-width: 1200px){.container,.container-sm,.container-md,.container-lg,.container-xl{max-width:1140px}}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*="col-"]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}@media (min-width: 576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-sm-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-sm-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-sm-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-sm-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-sm-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-sm-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-sm-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-sm-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}}@media (min-width: 768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-md-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-md-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-md-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-md-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-md-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-md-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-md-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-md-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}}@media (min-width: 992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-lg-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-lg-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-lg-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-lg-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-lg-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-lg-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-lg-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-lg-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}}@media (min-width: 1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-xl-1>*{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-webkit-box-flex:0;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-xl-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-xl-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-xl-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-xl-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-xl-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-xl-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-xl-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}}.table{width:100%;margin-bottom:1rem;color:#fff}.table th,.table td{padding:0.75rem;vertical-align:top;border-top:1px solid #444}.table thead th{vertical-align:bottom;border-bottom:2px solid #444}.table tbody+tbody{border-top:2px solid #444}.table-sm th,.table-sm td{padding:0.3rem}.table-bordered{border:1px solid #444}.table-bordered th,.table-bordered td{border:1px solid #444}.table-bordered thead th,.table-bordered thead td{border-bottom-width:2px}.table-borderless th,.table-borderless td,.table-borderless thead th,.table-borderless tbody+tbody{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:#303030}.table-hover tbody tr:hover{color:#fff;background-color:rgba(0,0,0,0.075)}.table-primary,.table-primary>th,.table-primary>td{background-color:#c7d1db}.table-primary th,.table-primary td,.table-primary thead th,.table-primary tbody+tbody{border-color:#97a9bc}.table-hover .table-primary:hover{background-color:#b7c4d1}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b7c4d1}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#cbcbcb}.table-secondary th,.table-secondary td,.table-secondary thead th,.table-secondary tbody+tbody{border-color:#9e9e9e}.table-hover .table-secondary:hover{background-color:#bebebe}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#bebebe}.table-success,.table-success>th,.table-success>td{background-color:#b8ecdf}.table-success th,.table-success td,.table-success thead th,.table-success tbody+tbody{border-color:#7adcc3}.table-hover .table-success:hover{background-color:#a4e7d6}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#a4e7d6}.table-info,.table-info>th,.table-info>td{background-color:#c6e2f5}.table-info th,.table-info td,.table-info thead th,.table-info tbody+tbody{border-color:#95c9ec}.table-hover .table-info:hover{background-color:#b0d7f1}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#b0d7f1}.table-warning,.table-warning>th,.table-warning>td{background-color:#fce3bd}.table-warning th,.table-warning td,.table-warning thead th,.table-warning tbody+tbody{border-color:#f9cc84}.table-hover .table-warning:hover{background-color:#fbd9a5}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#fbd9a5}.table-danger,.table-danger>th,.table-danger>td{background-color:#f8cdc8}.table-danger th,.table-danger td,.table-danger thead th,.table-danger tbody+tbody{border-color:#f3a29a}.table-hover .table-danger:hover{background-color:#f5b8b1}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f5b8b1}.table-light,.table-light>th,.table-light>td{background-color:#e8eaed}.table-light th,.table-light td,.table-light thead th,.table-light tbody+tbody{border-color:#d4d9dd}.table-hover .table-light:hover{background-color:#dadde2}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#dadde2}.table-dark,.table-dark>th,.table-dark>td{background-color:#c5c5c5}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#939393}.table-hover .table-dark:hover{background-color:#b8b8b8}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b8b8b8}.table-active,.table-active>th,.table-active>td{background-color:rgba(0,0,0,0.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,0.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,0.075)}.table .thead-dark th{color:#fff;background-color:#303030;border-color:#434343}.table .thead-light th{color:#444;background-color:#ebebeb;border-color:#444}.table-dark{color:#fff;background-color:#303030}.table-dark th,.table-dark td,.table-dark thead th{border-color:#434343}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,0.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,0.075)}@media (max-width: 575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width: 767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width: 991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width: 1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + 0.75rem + 2px);padding:0.375rem 0.75rem;font-size:0.9375rem;font-weight:400;line-height:1.5;color:#444;background-color:#fff;background-clip:padding-box;border:1px solid #222;border-radius:0.25rem;-webkit-transition:border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control{-webkit-transition:none;transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #444}.form-control:focus{color:#444;background-color:#fff;border-color:#739ac2;outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25)}.form-control::-webkit-input-placeholder{color:#888;opacity:1}.form-control::-ms-input-placeholder{color:#888;opacity:1}.form-control::placeholder{color:#888;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#ebebeb;opacity:1}input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:focus::-ms-value{color:#444;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.171875rem;line-height:1.5}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.8203125rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:0.375rem 0;margin-bottom:0;font-size:0.9375rem;line-height:1.5;color:#fff;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + 0.5rem + 2px);padding:0.25rem 0.5rem;font-size:0.8203125rem;line-height:1.5;border-radius:0.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:0.5rem 1rem;font-size:1.171875rem;line-height:1.5;border-radius:0.3rem}select.form-control[size],select.form-control[multiple]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:0.25rem}.form-row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*="col-"]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:0.3rem;margin-left:-1.25rem}.form-check-input[disabled] ~ .form-check-label,.form-check-input:disabled ~ .form-check-label{color:#888}.form-check-label{margin-bottom:0}.form-check-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:0.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:0.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:0.25rem;font-size:80%;color:#00bc8c}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:0.25rem 0.5rem;margin-top:.1rem;font-size:0.8203125rem;line-height:1.5;color:#fff;background-color:rgba(0,188,140,0.9);border-radius:0.25rem}.was-validated :valid ~ .valid-feedback,.was-validated :valid ~ .valid-tooltip,.is-valid ~ .valid-feedback,.is-valid ~ .valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#00bc8c;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2300bc8c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#00bc8c;-webkit-box-shadow:0 0 0 0.2rem rgba(0,188,140,0.25);box-shadow:0 0 0 0.2rem rgba(0,188,140,0.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#00bc8c;padding-right:calc(0.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23303030' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2300bc8c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#00bc8c;-webkit-box-shadow:0 0 0 0.2rem rgba(0,188,140,0.25);box-shadow:0 0 0 0.2rem rgba(0,188,140,0.25)}.was-validated .form-check-input:valid ~ .form-check-label,.form-check-input.is-valid ~ .form-check-label{color:#00bc8c}.was-validated .form-check-input:valid ~ .valid-feedback,.was-validated .form-check-input:valid ~ .valid-tooltip,.form-check-input.is-valid ~ .valid-feedback,.form-check-input.is-valid ~ .valid-tooltip{display:block}.was-validated .custom-control-input:valid ~ .custom-control-label,.custom-control-input.is-valid ~ .custom-control-label{color:#00bc8c}.was-validated .custom-control-input:valid ~ .custom-control-label::before,.custom-control-input.is-valid ~ .custom-control-label::before{border-color:#00bc8c}.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before,.custom-control-input.is-valid:checked ~ .custom-control-label::before{border-color:#00efb2;background-color:#00efb2}.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before,.custom-control-input.is-valid:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 0.2rem rgba(0,188,140,0.25);box-shadow:0 0 0 0.2rem rgba(0,188,140,0.25)}.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before,.custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before{border-color:#00bc8c}.was-validated .custom-file-input:valid ~ .custom-file-label,.custom-file-input.is-valid ~ .custom-file-label{border-color:#00bc8c}.was-validated .custom-file-input:valid:focus ~ .custom-file-label,.custom-file-input.is-valid:focus ~ .custom-file-label{border-color:#00bc8c;-webkit-box-shadow:0 0 0 0.2rem rgba(0,188,140,0.25);box-shadow:0 0 0 0.2rem rgba(0,188,140,0.25)}.invalid-feedback{display:none;width:100%;margin-top:0.25rem;font-size:80%;color:#E74C3C}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:0.25rem 0.5rem;margin-top:.1rem;font-size:0.8203125rem;line-height:1.5;color:#fff;background-color:rgba(231,76,60,0.9);border-radius:0.25rem}.was-validated :invalid ~ .invalid-feedback,.was-validated :invalid ~ .invalid-tooltip,.is-invalid ~ .invalid-feedback,.is-invalid ~ .invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#E74C3C;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23E74C3C' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23E74C3C' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#E74C3C;-webkit-box-shadow:0 0 0 0.2rem rgba(231,76,60,0.25);box-shadow:0 0 0 0.2rem rgba(231,76,60,0.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#E74C3C;padding-right:calc(0.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23303030' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23E74C3C' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23E74C3C' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#E74C3C;-webkit-box-shadow:0 0 0 0.2rem rgba(231,76,60,0.25);box-shadow:0 0 0 0.2rem rgba(231,76,60,0.25)}.was-validated .form-check-input:invalid ~ .form-check-label,.form-check-input.is-invalid ~ .form-check-label{color:#E74C3C}.was-validated .form-check-input:invalid ~ .invalid-feedback,.was-validated .form-check-input:invalid ~ .invalid-tooltip,.form-check-input.is-invalid ~ .invalid-feedback,.form-check-input.is-invalid ~ .invalid-tooltip{display:block}.was-validated .custom-control-input:invalid ~ .custom-control-label,.custom-control-input.is-invalid ~ .custom-control-label{color:#E74C3C}.was-validated .custom-control-input:invalid ~ .custom-control-label::before,.custom-control-input.is-invalid ~ .custom-control-label::before{border-color:#E74C3C}.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before,.custom-control-input.is-invalid:checked ~ .custom-control-label::before{border-color:#ed7669;background-color:#ed7669}.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before,.custom-control-input.is-invalid:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 0.2rem rgba(231,76,60,0.25);box-shadow:0 0 0 0.2rem rgba(231,76,60,0.25)}.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before,.custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before{border-color:#E74C3C}.was-validated .custom-file-input:invalid ~ .custom-file-label,.custom-file-input.is-invalid ~ .custom-file-label{border-color:#E74C3C}.was-validated .custom-file-input:invalid:focus ~ .custom-file-label,.custom-file-input.is-invalid:focus ~ .custom-file-label{border-color:#E74C3C;-webkit-box-shadow:0 0 0 0.2rem rgba(231,76,60,0.25);box-shadow:0 0 0 0.2rem rgba(231,76,60,0.25)}.form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width: 576px){.form-inline label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:0.25rem;margin-left:0}.form-inline .custom-control{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#fff;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:0.375rem 0.75rem;font-size:0.9375rem;line-height:1.5;border-radius:0.25rem;-webkit-transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.btn{-webkit-transition:none;transition:none}}.btn:hover{color:#fff;text-decoration:none}.btn:focus,.btn.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25)}.btn.disabled,.btn:disabled{opacity:0.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#375a7f;border-color:#375a7f}.btn-primary:hover{color:#fff;background-color:#2b4764;border-color:#28415b}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#2b4764;border-color:#28415b;-webkit-box-shadow:0 0 0 0.2rem rgba(85,115,146,0.5);box-shadow:0 0 0 0.2rem rgba(85,115,146,0.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#375a7f;border-color:#375a7f}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#28415b;border-color:#243a53}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(85,115,146,0.5);box-shadow:0 0 0 0.2rem rgba(85,115,146,0.5)}.btn-secondary{color:#fff;background-color:#444;border-color:#444}.btn-secondary:hover{color:#fff;background-color:#313131;border-color:#2b2a2a}.btn-secondary:focus,.btn-secondary.focus{color:#fff;background-color:#313131;border-color:#2b2a2a;-webkit-box-shadow:0 0 0 0.2rem rgba(96,96,96,0.5);box-shadow:0 0 0 0.2rem rgba(96,96,96,0.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#444;border-color:#444}.btn-secondary:not(:disabled):not(.disabled):active,.btn-secondary:not(:disabled):not(.disabled).active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#2b2a2a;border-color:#242424}.btn-secondary:not(:disabled):not(.disabled):active:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(96,96,96,0.5);box-shadow:0 0 0 0.2rem rgba(96,96,96,0.5)}.btn-success{color:#fff;background-color:#00bc8c;border-color:#00bc8c}.btn-success:hover{color:#fff;background-color:#009670;border-color:#008966}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#009670;border-color:#008966;-webkit-box-shadow:0 0 0 0.2rem rgba(38,198,157,0.5);box-shadow:0 0 0 0.2rem rgba(38,198,157,0.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#00bc8c;border-color:#00bc8c}.btn-success:not(:disabled):not(.disabled):active,.btn-success:not(:disabled):not(.disabled).active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#008966;border-color:#007c5d}.btn-success:not(:disabled):not(.disabled):active:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.show>.btn-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(38,198,157,0.5);box-shadow:0 0 0 0.2rem rgba(38,198,157,0.5)}.btn-info{color:#fff;background-color:#3498DB;border-color:#3498DB}.btn-info:hover{color:#fff;background-color:#2384c6;border-color:#217dbb}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#2384c6;border-color:#217dbb;-webkit-box-shadow:0 0 0 0.2rem rgba(82,167,224,0.5);box-shadow:0 0 0 0.2rem rgba(82,167,224,0.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#3498DB;border-color:#3498DB}.btn-info:not(:disabled):not(.disabled):active,.btn-info:not(:disabled):not(.disabled).active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#217dbb;border-color:#1f76b0}.btn-info:not(:disabled):not(.disabled):active:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.show>.btn-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(82,167,224,0.5);box-shadow:0 0 0 0.2rem rgba(82,167,224,0.5)}.btn-warning{color:#fff;background-color:#F39C12;border-color:#F39C12}.btn-warning:hover{color:#fff;background-color:#d4860b;border-color:#c87f0a}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#d4860b;border-color:#c87f0a;-webkit-box-shadow:0 0 0 0.2rem rgba(245,171,54,0.5);box-shadow:0 0 0 0.2rem rgba(245,171,54,0.5)}.btn-warning.disabled,.btn-warning:disabled{color:#fff;background-color:#F39C12;border-color:#F39C12}.btn-warning:not(:disabled):not(.disabled):active,.btn-warning:not(:disabled):not(.disabled).active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#c87f0a;border-color:#bc770a}.btn-warning:not(:disabled):not(.disabled):active:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(245,171,54,0.5);box-shadow:0 0 0 0.2rem rgba(245,171,54,0.5)}.btn-danger{color:#fff;background-color:#E74C3C;border-color:#E74C3C}.btn-danger:hover{color:#fff;background-color:#e12e1c;border-color:#d62c1a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#e12e1c;border-color:#d62c1a;-webkit-box-shadow:0 0 0 0.2rem rgba(235,103,89,0.5);box-shadow:0 0 0 0.2rem rgba(235,103,89,0.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#E74C3C;border-color:#E74C3C}.btn-danger:not(:disabled):not(.disabled):active,.btn-danger:not(:disabled):not(.disabled).active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#d62c1a;border-color:#ca2a19}.btn-danger:not(:disabled):not(.disabled):active:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(235,103,89,0.5);box-shadow:0 0 0 0.2rem rgba(235,103,89,0.5)}.btn-light{color:#222;background-color:#adb5bd;border-color:#adb5bd}.btn-light:hover{color:#fff;background-color:#98a2ac;border-color:#919ca6}.btn-light:focus,.btn-light.focus{color:#fff;background-color:#98a2ac;border-color:#919ca6;-webkit-box-shadow:0 0 0 0.2rem rgba(152,159,166,0.5);box-shadow:0 0 0 0.2rem rgba(152,159,166,0.5)}.btn-light.disabled,.btn-light:disabled{color:#222;background-color:#adb5bd;border-color:#adb5bd}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle{color:#fff;background-color:#919ca6;border-color:#8a95a1}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(152,159,166,0.5);box-shadow:0 0 0 0.2rem rgba(152,159,166,0.5)}.btn-dark{color:#fff;background-color:#303030;border-color:#303030}.btn-dark:hover{color:#fff;background-color:#1d1d1d;border-color:#171616}.btn-dark:focus,.btn-dark.focus{color:#fff;background-color:#1d1d1d;border-color:#171616;-webkit-box-shadow:0 0 0 0.2rem rgba(79,79,79,0.5);box-shadow:0 0 0 0.2rem rgba(79,79,79,0.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#303030;border-color:#303030}.btn-dark:not(:disabled):not(.disabled):active,.btn-dark:not(:disabled):not(.disabled).active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#171616;border-color:#101010}.btn-dark:not(:disabled):not(.disabled):active:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(79,79,79,0.5);box-shadow:0 0 0 0.2rem rgba(79,79,79,0.5)}.btn-outline-primary{color:#375a7f;border-color:#375a7f}.btn-outline-primary:hover{color:#fff;background-color:#375a7f;border-color:#375a7f}.btn-outline-primary:focus,.btn-outline-primary.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.5);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#375a7f;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled):active,.btn-outline-primary:not(:disabled):not(.disabled).active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#375a7f;border-color:#375a7f}.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.5);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.5)}.btn-outline-secondary{color:#444;border-color:#444}.btn-outline-secondary:hover{color:#fff;background-color:#444;border-color:#444}.btn-outline-secondary:focus,.btn-outline-secondary.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(68,68,68,0.5);box-shadow:0 0 0 0.2rem rgba(68,68,68,0.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#444;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled):active,.btn-outline-secondary:not(:disabled):not(.disabled).active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#444;border-color:#444}.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(68,68,68,0.5);box-shadow:0 0 0 0.2rem rgba(68,68,68,0.5)}.btn-outline-success{color:#00bc8c;border-color:#00bc8c}.btn-outline-success:hover{color:#fff;background-color:#00bc8c;border-color:#00bc8c}.btn-outline-success:focus,.btn-outline-success.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(0,188,140,0.5);box-shadow:0 0 0 0.2rem rgba(0,188,140,0.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#00bc8c;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled):active,.btn-outline-success:not(:disabled):not(.disabled).active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#00bc8c;border-color:#00bc8c}.btn-outline-success:not(:disabled):not(.disabled):active:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(0,188,140,0.5);box-shadow:0 0 0 0.2rem rgba(0,188,140,0.5)}.btn-outline-info{color:#3498DB;border-color:#3498DB}.btn-outline-info:hover{color:#fff;background-color:#3498DB;border-color:#3498DB}.btn-outline-info:focus,.btn-outline-info.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(52,152,219,0.5);box-shadow:0 0 0 0.2rem rgba(52,152,219,0.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#3498DB;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled):active,.btn-outline-info:not(:disabled):not(.disabled).active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#3498DB;border-color:#3498DB}.btn-outline-info:not(:disabled):not(.disabled):active:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(52,152,219,0.5);box-shadow:0 0 0 0.2rem rgba(52,152,219,0.5)}.btn-outline-warning{color:#F39C12;border-color:#F39C12}.btn-outline-warning:hover{color:#fff;background-color:#F39C12;border-color:#F39C12}.btn-outline-warning:focus,.btn-outline-warning.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(243,156,18,0.5);box-shadow:0 0 0 0.2rem rgba(243,156,18,0.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#F39C12;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled):active,.btn-outline-warning:not(:disabled):not(.disabled).active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#F39C12;border-color:#F39C12}.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(243,156,18,0.5);box-shadow:0 0 0 0.2rem rgba(243,156,18,0.5)}.btn-outline-danger{color:#E74C3C;border-color:#E74C3C}.btn-outline-danger:hover{color:#fff;background-color:#E74C3C;border-color:#E74C3C}.btn-outline-danger:focus,.btn-outline-danger.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(231,76,60,0.5);box-shadow:0 0 0 0.2rem rgba(231,76,60,0.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#E74C3C;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled):active,.btn-outline-danger:not(:disabled):not(.disabled).active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#E74C3C;border-color:#E74C3C}.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(231,76,60,0.5);box-shadow:0 0 0 0.2rem rgba(231,76,60,0.5)}.btn-outline-light{color:#adb5bd;border-color:#adb5bd}.btn-outline-light:hover{color:#222;background-color:#adb5bd;border-color:#adb5bd}.btn-outline-light:focus,.btn-outline-light.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(173,181,189,0.5);box-shadow:0 0 0 0.2rem rgba(173,181,189,0.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#adb5bd;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled):active,.btn-outline-light:not(:disabled):not(.disabled).active,.show>.btn-outline-light.dropdown-toggle{color:#222;background-color:#adb5bd;border-color:#adb5bd}.btn-outline-light:not(:disabled):not(.disabled):active:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(173,181,189,0.5);box-shadow:0 0 0 0.2rem rgba(173,181,189,0.5)}.btn-outline-dark{color:#303030;border-color:#303030}.btn-outline-dark:hover{color:#fff;background-color:#303030;border-color:#303030}.btn-outline-dark:focus,.btn-outline-dark.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(48,48,48,0.5);box-shadow:0 0 0 0.2rem rgba(48,48,48,0.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#303030;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled):active,.btn-outline-dark:not(:disabled):not(.disabled).active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#303030;border-color:#303030}.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(48,48,48,0.5);box-shadow:0 0 0 0.2rem rgba(48,48,48,0.5)}.btn-link{font-weight:400;color:#00bc8c;text-decoration:none}.btn-link:hover{color:#007053;text-decoration:underline}.btn-link:focus,.btn-link.focus{text-decoration:underline}.btn-link:disabled,.btn-link.disabled{color:#888;pointer-events:none}.btn-lg,.btn-group-lg>.btn{padding:0.5rem 1rem;font-size:1.171875rem;line-height:1.5;border-radius:0.3rem}.btn-sm,.btn-group-sm>.btn{padding:0.25rem 0.5rem;font-size:0.8203125rem;line-height:1.5;border-radius:0.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:0.5rem}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{-webkit-transition:opacity 0.15s linear;transition:opacity 0.15s linear}@media (prefers-reduced-motion: reduce){.fade{-webkit-transition:none;transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height 0.35s ease;transition:height 0.35s ease}@media (prefers-reduced-motion: reduce){.collapsing{-webkit-transition:none;transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid;border-right:0.3em solid transparent;border-bottom:0;border-left:0.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:0.5rem 0;margin:0.125rem 0 0;font-size:0.9375rem;color:#fff;text-align:left;list-style:none;background-color:#222;background-clip:padding-box;border:1px solid #444;border-radius:0.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width: 576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width: 768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width: 992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width: 1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:0.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0;border-right:0.3em solid transparent;border-bottom:0.3em solid;border-left:0.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:0.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid transparent;border-right:0;border-bottom:0.3em solid transparent;border-left:0.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:0.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:0.255em;vertical-align:0.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid transparent;border-right:0.3em solid;border-bottom:0.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^="top"],.dropdown-menu[x-placement^="right"],.dropdown-menu[x-placement^="bottom"],.dropdown-menu[x-placement^="left"]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:0.5rem 0;overflow:hidden;border-top:1px solid #444}.dropdown-item{display:block;width:100%;padding:0.25rem 1.5rem;clear:both;font-weight:400;color:#fff;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-item:focus{color:#fff;text-decoration:none;background-color:#375a7f}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#375a7f}.dropdown-item.disabled,.dropdown-item:disabled{color:#888;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:0.5rem 1.5rem;margin-bottom:0;font-size:0.8203125rem;color:#888;white-space:nowrap}.dropdown-item-text{display:block;padding:0.25rem 1.5rem;color:#fff}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover{z-index:1}.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child){margin-left:-1px}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:0.5625rem;padding-left:0.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:0.375rem;padding-left:0.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:0.75rem;padding-left:0.75rem}.btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type="radio"],.btn-group-toggle>.btn input[type="checkbox"],.btn-group-toggle>.btn-group>.btn input[type="radio"],.btn-group-toggle>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-control-plaintext,.input-group>.custom-select,.input-group>.custom-file{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.form-control+.form-control,.input-group>.form-control+.custom-select,.input-group>.form-control+.custom-file,.input-group>.form-control-plaintext+.form-control,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.custom-file,.input-group>.custom-select+.form-control,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.custom-file,.input-group>.custom-file+.form-control,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.custom-file{margin-left:-1px}.input-group>.form-control:focus,.input-group>.custom-select:focus,.input-group>.custom-file .custom-file-input:focus ~ .custom-file-label{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.form-control:not(:last-child),.input-group>.custom-select:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.form-control:not(:first-child),.input-group>.custom-select:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-prepend,.input-group-append{display:-webkit-box;display:-ms-flexbox;display:flex}.input-group-prepend .btn,.input-group-append .btn{position:relative;z-index:2}.input-group-prepend .btn:focus,.input-group-append .btn:focus{z-index:3}.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.input-group-text,.input-group-append .input-group-text+.btn{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0.375rem 0.75rem;margin-bottom:0;font-size:0.9375rem;font-weight:400;line-height:1.5;color:#adb5bd;text-align:center;white-space:nowrap;background-color:#444;border:1px solid #222;border-radius:0.25rem}.input-group-text input[type="radio"],.input-group-text input[type="checkbox"]{margin-top:0}.input-group-lg>.form-control:not(textarea),.input-group-lg>.custom-select{height:calc(1.5em + 1rem + 2px)}.input-group-lg>.form-control,.input-group-lg>.custom-select,.input-group-lg>.input-group-prepend>.input-group-text,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-append>.btn{padding:0.5rem 1rem;font-size:1.171875rem;line-height:1.5;border-radius:0.3rem}.input-group-sm>.form-control:not(textarea),.input-group-sm>.custom-select{height:calc(1.5em + 0.5rem + 2px)}.input-group-sm>.form-control,.input-group-sm>.custom-select,.input-group-sm>.input-group-prepend>.input-group-text,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-append>.btn{padding:0.25rem 0.5rem;font-size:0.8203125rem;line-height:1.5;border-radius:0.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text,.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.40625rem;padding-left:1.5rem}.custom-control-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.203125rem;opacity:0}.custom-control-input:checked ~ .custom-control-label::before{color:#fff;border-color:#375a7f;background-color:#375a7f}.custom-control-input:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25)}.custom-control-input:focus:not(:checked) ~ .custom-control-label::before{border-color:#739ac2}.custom-control-input:not(:disabled):active ~ .custom-control-label::before{color:#fff;background-color:#97b3d2;border-color:#97b3d2}.custom-control-input[disabled] ~ .custom-control-label,.custom-control-input:disabled ~ .custom-control-label{color:#888}.custom-control-input[disabled] ~ .custom-control-label::before,.custom-control-input:disabled ~ .custom-control-label::before{background-color:#ebebeb}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:0.203125rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:0.203125rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50% / 50% 50%}.custom-checkbox .custom-control-label::before{border-radius:0.25rem}.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before{border-color:#375a7f;background-color:#375a7f}.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before{background-color:rgba(55,90,127,0.5)}.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before{background-color:rgba(55,90,127,0.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked ~ .custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before{background-color:rgba(55,90,127,0.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:0.5rem}.custom-switch .custom-control-label::after{top:calc(0.203125rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:0.5rem;-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.custom-switch .custom-control-label::after{-webkit-transition:none;transition:none}}.custom-switch .custom-control-input:checked ~ .custom-control-label::after{background-color:#fff;-webkit-transform:translateX(0.75rem);transform:translateX(0.75rem)}.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before{background-color:rgba(55,90,127,0.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + 0.75rem + 2px);padding:0.375rem 1.75rem 0.375rem 0.75rem;font-size:0.9375rem;font-weight:400;line-height:1.5;color:#444;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23303030' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px;border:1px solid #222;border-radius:0.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#739ac2;outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25)}.custom-select:focus::-ms-value{color:#444;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:0.75rem;background-image:none}.custom-select:disabled{color:#888;background-color:#ebebeb}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #444}.custom-select-sm{height:calc(1.5em + 0.5rem + 2px);padding-top:0.25rem;padding-bottom:0.25rem;padding-left:0.5rem;font-size:0.8203125rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:0.5rem;padding-bottom:0.5rem;padding-left:1rem;font-size:1.171875rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + 0.75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + 0.75rem + 2px);margin:0;opacity:0}.custom-file-input:focus ~ .custom-file-label{border-color:#739ac2;-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25)}.custom-file-input[disabled] ~ .custom-file-label,.custom-file-input:disabled ~ .custom-file-label{background-color:#ebebeb}.custom-file-input:lang(en) ~ .custom-file-label::after{content:"Browse"}.custom-file-input ~ .custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + 0.75rem + 2px);padding:0.375rem 0.75rem;font-weight:400;line-height:1.5;color:#adb5bd;background-color:#fff;border:1px solid #222;border-radius:0.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + 0.75rem);padding:0.375rem 0.75rem;line-height:1.5;color:#adb5bd;content:"Browse";background-color:#444;border-left:inherit;border-radius:0 0.25rem 0.25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:none}.custom-range:focus::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 1px #222,0 0 0 0.2rem rgba(55,90,127,0.25);box-shadow:0 0 0 1px #222,0 0 0 0.2rem rgba(55,90,127,0.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #222,0 0 0 0.2rem rgba(55,90,127,0.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #222,0 0 0 0.2rem rgba(55,90,127,0.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-0.25rem;background-color:#375a7f;border:0;border-radius:1rem;-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#97b3d2}.custom-range::-webkit-slider-runnable-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#375a7f;border:0;border-radius:1rem;-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-moz-range-thumb{-webkit-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#97b3d2}.custom-range::-moz-range-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:0.2rem;margin-left:0.2rem;background-color:#375a7f;border:0;border-radius:1rem;-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-ms-thumb{-webkit-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#97b3d2}.custom-range::-ms-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:0.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.custom-control-label::before,.custom-file-label,.custom-select{-webkit-transition:none;transition:none}}.nav{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:0.5rem 2rem}.nav-link:hover,.nav-link:focus{text-decoration:none}.nav-link.disabled{color:#adb5bd;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #444}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:0.25rem;border-top-right-radius:0.25rem}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#444 #444 transparent}.nav-tabs .nav-link.disabled{color:#adb5bd;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#fff;background-color:#222;border-color:#444 #444 transparent}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:0.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#375a7f}.nav-fill .nav-item{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-sm,.navbar .container-md,.navbar .container-lg,.navbar .container-xl{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:0.32421875rem;padding-bottom:0.32421875rem;margin-right:1rem;font-size:1.171875rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:0.5rem;padding-bottom:0.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:0.25rem 0.75rem;font-size:1.171875rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:0.25rem}.navbar-toggler:hover,.navbar-toggler:focus{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width: 575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 576px){.navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width: 767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 768px){.navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width: 991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 992px){.navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width: 1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 1200px){.navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:#222}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:#222}.navbar-light .navbar-nav .nav-link{color:rgba(34,34,34,0.7)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:#222}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,0.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.active{color:#222}.navbar-light .navbar-toggler{color:rgba(34,34,34,0.7);border-color:rgba(34,34,34,0.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2834, 34, 34, 0.7%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(34,34,34,0.7)}.navbar-light .navbar-text a{color:#222}.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:#222}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,0.6)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:#fff}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,0.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,0.6);border-color:rgba(255,255,255,0.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.6%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,0.6)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.card{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#303030;background-clip:border-box;border:1px solid rgba(0,0,0,0.125);border-radius:0.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(0.25rem - 1px);border-bottom-left-radius:calc(0.25rem - 1px)}.card-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:0.75rem}.card-subtitle{margin-top:-0.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:0.75rem 1.25rem;margin-bottom:0;background-color:#444;border-bottom:1px solid rgba(0,0,0,0.125)}.card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:0.75rem 1.25rem;background-color:#444;border-top:1px solid rgba(0,0,0,0.125)}.card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.card-header-tabs{margin-right:-0.625rem;margin-bottom:-0.75rem;margin-left:-0.625rem;border-bottom:0}.card-header-pills{margin-right:-0.625rem;margin-left:-0.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-top,.card-img-bottom{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(0.25rem - 1px);border-bottom-left-radius:calc(0.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width: 576px){.card-deck{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width: 576px){.card-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:0.75rem}@media (min-width: 576px){.card-columns{-webkit-column-count:3;column-count:3;-webkit-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#444;border-radius:0.25rem}.breadcrumb-item{display:-webkit-box;display:-ms-flexbox;display:flex}.breadcrumb-item+.breadcrumb-item{padding-left:0.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:0.5rem;color:#888;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#888}.pagination{display:-webkit-box;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:0.25rem}.page-link{position:relative;display:block;padding:0.5rem 0.75rem;margin-left:0;line-height:1.25;color:#fff;background-color:#00bc8c;border:0 solid transparent}.page-link:hover{z-index:2;color:#fff;text-decoration:none;background-color:#00efb2;border-color:transparent}.page-link:focus{z-index:3;outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:0.25rem;border-bottom-left-radius:0.25rem}.page-item:last-child .page-link{border-top-right-radius:0.25rem;border-bottom-right-radius:0.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#00efb2;border-color:transparent}.page-item.disabled .page-link{color:#fff;pointer-events:none;cursor:auto;background-color:#007053;border-color:transparent}.pagination-lg .page-link{padding:0.75rem 1.5rem;font-size:1.171875rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:0.3rem;border-bottom-left-radius:0.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:0.3rem;border-bottom-right-radius:0.3rem}.pagination-sm .page-link{padding:0.25rem 0.5rem;font-size:0.8203125rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:0.2rem;border-bottom-left-radius:0.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:0.2rem;border-bottom-right-radius:0.2rem}.badge{display:inline-block;padding:0.25em 0.4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:0.25rem;-webkit-transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.badge{-webkit-transition:none;transition:none}}a.badge:hover,a.badge:focus{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:0.6em;padding-left:0.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#375a7f}a.badge-primary:hover,a.badge-primary:focus{color:#fff;background-color:#28415b}a.badge-primary:focus,a.badge-primary.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(55,90,127,0.5);box-shadow:0 0 0 0.2rem rgba(55,90,127,0.5)}.badge-secondary{color:#fff;background-color:#444}a.badge-secondary:hover,a.badge-secondary:focus{color:#fff;background-color:#2b2a2a}a.badge-secondary:focus,a.badge-secondary.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(68,68,68,0.5);box-shadow:0 0 0 0.2rem rgba(68,68,68,0.5)}.badge-success{color:#fff;background-color:#00bc8c}a.badge-success:hover,a.badge-success:focus{color:#fff;background-color:#008966}a.badge-success:focus,a.badge-success.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(0,188,140,0.5);box-shadow:0 0 0 0.2rem rgba(0,188,140,0.5)}.badge-info{color:#fff;background-color:#3498DB}a.badge-info:hover,a.badge-info:focus{color:#fff;background-color:#217dbb}a.badge-info:focus,a.badge-info.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(52,152,219,0.5);box-shadow:0 0 0 0.2rem rgba(52,152,219,0.5)}.badge-warning{color:#fff;background-color:#F39C12}a.badge-warning:hover,a.badge-warning:focus{color:#fff;background-color:#c87f0a}a.badge-warning:focus,a.badge-warning.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(243,156,18,0.5);box-shadow:0 0 0 0.2rem rgba(243,156,18,0.5)}.badge-danger{color:#fff;background-color:#E74C3C}a.badge-danger:hover,a.badge-danger:focus{color:#fff;background-color:#d62c1a}a.badge-danger:focus,a.badge-danger.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(231,76,60,0.5);box-shadow:0 0 0 0.2rem rgba(231,76,60,0.5)}.badge-light{color:#222;background-color:#adb5bd}a.badge-light:hover,a.badge-light:focus{color:#222;background-color:#919ca6}a.badge-light:focus,a.badge-light.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(173,181,189,0.5);box-shadow:0 0 0 0.2rem rgba(173,181,189,0.5)}.badge-dark{color:#fff;background-color:#303030}a.badge-dark:hover,a.badge-dark:focus{color:#fff;background-color:#171616}a.badge-dark:focus,a.badge-dark.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(48,48,48,0.5);box-shadow:0 0 0 0.2rem rgba(48,48,48,0.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#303030;border-radius:0.3rem}@media (min-width: 576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:0.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:0.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3.90625rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:0.75rem 1.25rem;color:inherit}.alert-primary{color:#1d2f42;background-color:#d7dee5;border-color:#c7d1db}.alert-primary hr{border-top-color:#b7c4d1}.alert-primary .alert-link{color:#0d161f}.alert-secondary{color:#232323;background-color:#dadada;border-color:#cbcbcb}.alert-secondary hr{border-top-color:#bebebe}.alert-secondary .alert-link{color:#0a0909}.alert-success{color:#006249;background-color:#ccf2e8;border-color:#b8ecdf}.alert-success hr{border-top-color:#a4e7d6}.alert-success .alert-link{color:#002f23}.alert-info{color:#1b4f72;background-color:#d6eaf8;border-color:#c6e2f5}.alert-info hr{border-top-color:#b0d7f1}.alert-info .alert-link{color:#113249}.alert-warning{color:#7e5109;background-color:#fdebd0;border-color:#fce3bd}.alert-warning hr{border-top-color:#fbd9a5}.alert-warning .alert-link{color:#4e3206}.alert-danger{color:#78281f;background-color:#fadbd8;border-color:#f8cdc8}.alert-danger hr{border-top-color:#f5b8b1}.alert-danger .alert-link{color:#4f1a15}.alert-light{color:#5a5e62;background-color:#eff0f2;border-color:#e8eaed}.alert-light hr{border-top-color:#dadde2}.alert-light .alert-link{color:#424547}.alert-dark{color:#191919;background-color:#d6d6d6;border-color:#c5c5c5}.alert-dark hr{border-top-color:#b8b8b8}.alert-dark .alert-link{color:black}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:0.703125rem;background-color:#444;border-radius:0.25rem}.progress-bar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#375a7f;-webkit-transition:width 0.6s ease;transition:width 0.6s ease}@media (prefers-reduced-motion: reduce){.progress-bar{-webkit-transition:none;transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion: reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-ms-flex:1;flex:1}.list-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:0.25rem}.list-group-item-action{width:100%;color:#444;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:#444;text-decoration:none;background-color:#444}.list-group-item-action:active{color:#fff;background-color:#ebebeb}.list-group-item{position:relative;display:block;padding:0.75rem 1.25rem;background-color:#303030;border:1px solid #444}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#888;pointer-events:none;background-color:#303030}.list-group-item.active{z-index:2;color:#fff;background-color:#375a7f;border-color:#375a7f}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width: 576px){.list-group-horizontal-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 768px){.list-group-horizontal-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 992px){.list-group-horizontal-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 1200px){.list-group-horizontal-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:0.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:0.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#1d2f42;background-color:#c7d1db}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#1d2f42;background-color:#b7c4d1}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#1d2f42;border-color:#1d2f42}.list-group-item-secondary{color:#232323;background-color:#cbcbcb}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#232323;background-color:#bebebe}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#232323;border-color:#232323}.list-group-item-success{color:#006249;background-color:#b8ecdf}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#006249;background-color:#a4e7d6}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#006249;border-color:#006249}.list-group-item-info{color:#1b4f72;background-color:#c6e2f5}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#1b4f72;background-color:#b0d7f1}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#1b4f72;border-color:#1b4f72}.list-group-item-warning{color:#7e5109;background-color:#fce3bd}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#7e5109;background-color:#fbd9a5}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#7e5109;border-color:#7e5109}.list-group-item-danger{color:#78281f;background-color:#f8cdc8}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#78281f;background-color:#f5b8b1}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#78281f;border-color:#78281f}.list-group-item-light{color:#5a5e62;background-color:#e8eaed}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#5a5e62;background-color:#dadde2}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#5a5e62;border-color:#5a5e62}.list-group-item-dark{color:#191919;background-color:#c5c5c5}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#191919;background-color:#b8b8b8}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#191919;border-color:#191919}.close{float:right;font-size:1.40625rem;font-weight:700;line-height:1;color:#fff;text-shadow:none;opacity:.5}.close:hover{color:#fff;text-decoration:none}.close:not(:disabled):not(.disabled):hover,.close:not(:disabled):not(.disabled):focus{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:0.875rem;background-color:#444;background-clip:padding-box;border:1px solid rgba(0,0,0,0.1);-webkit-box-shadow:0 0.25rem 0.75rem rgba(0,0,0,0.1);box-shadow:0 0.25rem 0.75rem rgba(0,0,0,0.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:0.25rem}.toast:not(:last-child){margin-bottom:0.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0.25rem 0.75rem;color:#888;background-color:#303030;background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,0.05)}.toast-body{padding:0.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:0.5rem;pointer-events:none}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform 0.3s ease-out;transition:-webkit-transform 0.3s ease-out;transition:transform 0.3s ease-out;transition:transform 0.3s ease-out, -webkit-transform 0.3s ease-out;-webkit-transform:translate(0, -50px);transform:translate(0, -50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{-webkit-transition:none;transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-webkit-box;display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-header,.modal-dialog-scrollable .modal-footer{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#303030;background-clip:padding-box;border:1px solid #444;border-radius:0.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:0.5}.modal-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #444;border-top-left-radius:calc(0.3rem - 1px);border-top-right-radius:calc(0.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:0.75rem;border-top:1px solid #444;border-bottom-right-radius:calc(0.3rem - 1px);border-bottom-left-radius:calc(0.3rem - 1px)}.modal-footer>*{margin:0.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width: 1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:"Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.8203125rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:0.9}.tooltip .arrow{position:absolute;display:block;width:0.8rem;height:0.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^="top"]{padding:0.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^="top"] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^="top"] .arrow::before{top:0;border-width:0.4rem 0.4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^="right"]{padding:0 0.4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^="right"] .arrow{left:0;width:0.4rem;height:0.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^="right"] .arrow::before{right:0;border-width:0.4rem 0.4rem 0.4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^="bottom"]{padding:0.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^="bottom"] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^="bottom"] .arrow::before{bottom:0;border-width:0 0.4rem 0.4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^="left"]{padding:0 0.4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^="left"] .arrow{right:0;width:0.4rem;height:0.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^="left"] .arrow::before{left:0;border-width:0.4rem 0 0.4rem 0.4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:0.25rem 0.5rem;color:#fff;text-align:center;background-color:#000;border-radius:0.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:"Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.8203125rem;word-wrap:break-word;background-color:#303030;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);border-radius:0.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:0.5rem;margin:0 0.3rem}.popover .arrow::before,.popover .arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-top,.bs-popover-auto[x-placement^="top"]{margin-bottom:0.5rem}.bs-popover-top>.arrow,.bs-popover-auto[x-placement^="top"]>.arrow{bottom:calc(-0.5rem - 1px)}.bs-popover-top>.arrow::before,.bs-popover-auto[x-placement^="top"]>.arrow::before{bottom:0;border-width:0.5rem 0.5rem 0;border-top-color:rgba(0,0,0,0.25)}.bs-popover-top>.arrow::after,.bs-popover-auto[x-placement^="top"]>.arrow::after{bottom:1px;border-width:0.5rem 0.5rem 0;border-top-color:#303030}.bs-popover-right,.bs-popover-auto[x-placement^="right"]{margin-left:0.5rem}.bs-popover-right>.arrow,.bs-popover-auto[x-placement^="right"]>.arrow{left:calc(-0.5rem - 1px);width:0.5rem;height:1rem;margin:0.3rem 0}.bs-popover-right>.arrow::before,.bs-popover-auto[x-placement^="right"]>.arrow::before{left:0;border-width:0.5rem 0.5rem 0.5rem 0;border-right-color:rgba(0,0,0,0.25)}.bs-popover-right>.arrow::after,.bs-popover-auto[x-placement^="right"]>.arrow::after{left:1px;border-width:0.5rem 0.5rem 0.5rem 0;border-right-color:#303030}.bs-popover-bottom,.bs-popover-auto[x-placement^="bottom"]{margin-top:0.5rem}.bs-popover-bottom>.arrow,.bs-popover-auto[x-placement^="bottom"]>.arrow{top:calc(-0.5rem - 1px)}.bs-popover-bottom>.arrow::before,.bs-popover-auto[x-placement^="bottom"]>.arrow::before{top:0;border-width:0 0.5rem 0.5rem 0.5rem;border-bottom-color:rgba(0,0,0,0.25)}.bs-popover-bottom>.arrow::after,.bs-popover-auto[x-placement^="bottom"]>.arrow::after{top:1px;border-width:0 0.5rem 0.5rem 0.5rem;border-bottom-color:#303030}.bs-popover-bottom .popover-header::before,.bs-popover-auto[x-placement^="bottom"] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-0.5rem;content:"";border-bottom:1px solid #444}.bs-popover-left,.bs-popover-auto[x-placement^="left"]{margin-right:0.5rem}.bs-popover-left>.arrow,.bs-popover-auto[x-placement^="left"]>.arrow{right:calc(-0.5rem - 1px);width:0.5rem;height:1rem;margin:0.3rem 0}.bs-popover-left>.arrow::before,.bs-popover-auto[x-placement^="left"]>.arrow::before{right:0;border-width:0.5rem 0 0.5rem 0.5rem;border-left-color:rgba(0,0,0,0.25)}.bs-popover-left>.arrow::after,.bs-popover-auto[x-placement^="left"]>.arrow::after{right:1px;border-width:0.5rem 0 0.5rem 0.5rem;border-left-color:#303030}.popover-header{padding:0.5rem 0.75rem;margin-bottom:0;font-size:0.9375rem;background-color:#444;border-bottom:1px solid #373737;border-top-left-radius:calc(0.3rem - 1px);border-top-right-radius:calc(0.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:0.5rem 0.75rem;color:#fff}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition:-webkit-transform 0.6s ease-in-out;transition:-webkit-transform 0.6s ease-in-out;transition:transform 0.6s ease-in-out;transition:transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out}@media (prefers-reduced-motion: reduce){.carousel-item{-webkit-transition:none;transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-left),.active.carousel-item-right{-webkit-transform:translateX(100%);transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-right),.active.carousel-item-left{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;-webkit-transition:opacity 0s 0.6s;transition:opacity 0s 0.6s}@media (prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{-webkit-transition:none;transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:0.5;-webkit-transition:opacity 0.15s ease;transition:opacity 0.15s ease}@media (prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{-webkit-transition:none;transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:0.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50% / 100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{-webkit-box-sizing:content-box;box-sizing:content-box;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;-webkit-transition:opacity 0.6s ease;transition:opacity 0.6s ease}@media (prefers-reduced-motion: reduce){.carousel-indicators li{-webkit-transition:none;transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:0.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:0.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.bg-primary{background-color:#375a7f !important}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#28415b !important}.bg-secondary{background-color:#444 !important}a.bg-secondary:hover,a.bg-secondary:focus,button.bg-secondary:hover,button.bg-secondary:focus{background-color:#2b2a2a !important}.bg-success{background-color:#00bc8c !important}a.bg-success:hover,a.bg-success:focus,button.bg-success:hover,button.bg-success:focus{background-color:#008966 !important}.bg-info{background-color:#3498DB !important}a.bg-info:hover,a.bg-info:focus,button.bg-info:hover,button.bg-info:focus{background-color:#217dbb !important}.bg-warning{background-color:#F39C12 !important}a.bg-warning:hover,a.bg-warning:focus,button.bg-warning:hover,button.bg-warning:focus{background-color:#c87f0a !important}.bg-danger{background-color:#E74C3C !important}a.bg-danger:hover,a.bg-danger:focus,button.bg-danger:hover,button.bg-danger:focus{background-color:#d62c1a !important}.bg-light{background-color:#adb5bd !important}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#919ca6 !important}.bg-dark{background-color:#303030 !important}a.bg-dark:hover,a.bg-dark:focus,button.bg-dark:hover,button.bg-dark:focus{background-color:#171616 !important}.bg-white{background-color:#fff !important}.bg-transparent{background-color:transparent !important}.border{border:1px solid #dee2e6 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-right{border-right:1px solid #dee2e6 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-left{border-left:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top-0{border-top:0 !important}.border-right-0{border-right:0 !important}.border-bottom-0{border-bottom:0 !important}.border-left-0{border-left:0 !important}.border-primary{border-color:#375a7f !important}.border-secondary{border-color:#444 !important}.border-success{border-color:#00bc8c !important}.border-info{border-color:#3498DB !important}.border-warning{border-color:#F39C12 !important}.border-danger{border-color:#E74C3C !important}.border-light{border-color:#adb5bd !important}.border-dark{border-color:#303030 !important}.border-white{border-color:#fff !important}.rounded-sm{border-radius:0.2rem !important}.rounded{border-radius:0.25rem !important}.rounded-top{border-top-left-radius:0.25rem !important;border-top-right-radius:0.25rem !important}.rounded-right{border-top-right-radius:0.25rem !important;border-bottom-right-radius:0.25rem !important}.rounded-bottom{border-bottom-right-radius:0.25rem !important;border-bottom-left-radius:0.25rem !important}.rounded-left{border-top-left-radius:0.25rem !important;border-bottom-left-radius:0.25rem !important}.rounded-lg{border-radius:0.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-0{border-radius:0 !important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}@media (min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-sm-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-md-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-lg-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-xl-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-print-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.8571428571%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}@media (min-width: 576px){.flex-sm-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-sm-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-sm-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-sm-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-sm-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-sm-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-sm-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-sm-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-sm-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-sm-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-sm-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-sm-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-sm-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-sm-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-sm-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-sm-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-sm-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-sm-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-sm-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-sm-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-sm-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-sm-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-sm-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-sm-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-sm-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-sm-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-sm-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-sm-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-sm-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-sm-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-sm-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-sm-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-sm-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 768px){.flex-md-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-md-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-md-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-md-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-md-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-md-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-md-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-md-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-md-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-md-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-md-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-md-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-md-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-md-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-md-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-md-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-md-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-md-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-md-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-md-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-md-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-md-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-md-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-md-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-md-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-md-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-md-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-md-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-md-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-md-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-md-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-md-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-md-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 992px){.flex-lg-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-lg-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-lg-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-lg-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-lg-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-lg-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-lg-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-lg-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-lg-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-lg-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-lg-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-lg-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-lg-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-lg-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-lg-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-lg-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-lg-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-lg-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-lg-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-lg-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-lg-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-lg-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-lg-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-lg-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-lg-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-lg-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-lg-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-lg-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-lg-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-lg-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-lg-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-lg-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-lg-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 1200px){.flex-xl-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-xl-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-xl-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-xl-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-xl-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-xl-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-xl-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-xl-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-xl-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-xl-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-xl-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-xl-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-xl-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-xl-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-xl-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-xl-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-xl-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-xl-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-xl-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-xl-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-xl-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-xl-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-xl-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-xl-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-xl-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-xl-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-xl-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-xl-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-xl-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-xl-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-xl-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-xl-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-xl-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}.float-left{float:left !important}.float-right{float:right !important}.float-none{float:none !important}@media (min-width: 576px){.float-sm-left{float:left !important}.float-sm-right{float:right !important}.float-sm-none{float:none !important}}@media (min-width: 768px){.float-md-left{float:left !important}.float-md-right{float:right !important}.float-md-none{float:none !important}}@media (min-width: 992px){.float-lg-left{float:left !important}.float-lg-right{float:right !important}.float-lg-none{float:none !important}}@media (min-width: 1200px){.float-xl-left{float:left !important}.float-xl-right{float:right !important}.float-xl-none{float:none !important}}.user-select-all{-webkit-user-select:all !important;-moz-user-select:all !important;-ms-user-select:all !important;user-select:all !important}.user-select-auto{-webkit-user-select:auto !important;-moz-user-select:auto !important;-ms-user-select:auto !important;user-select:auto !important}.user-select-none{-webkit-user-select:none !important;-moz-user-select:none !important;-ms-user-select:none !important;user-select:none !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:-webkit-sticky !important;position:sticky !important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports (position: -webkit-sticky) or (position: sticky){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{-webkit-box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important;box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important}.shadow{-webkit-box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important;box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important}.shadow-lg{-webkit-box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important;box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important}.shadow-none{-webkit-box-shadow:none !important;box-shadow:none !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mw-100{max-width:100% !important}.mh-100{max-height:100% !important}.min-vw-100{min-width:100vw !important}.min-vh-100{min-height:100vh !important}.vw-100{width:100vw !important}.vh-100{height:100vh !important}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:0.25rem !important}.mt-1,.my-1{margin-top:0.25rem !important}.mr-1,.mx-1{margin-right:0.25rem !important}.mb-1,.my-1{margin-bottom:0.25rem !important}.ml-1,.mx-1{margin-left:0.25rem !important}.m-2{margin:0.5rem !important}.mt-2,.my-2{margin-top:0.5rem !important}.mr-2,.mx-2{margin-right:0.5rem !important}.mb-2,.my-2{margin-bottom:0.5rem !important}.ml-2,.mx-2{margin-left:0.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:0.25rem !important}.pt-1,.py-1{padding-top:0.25rem !important}.pr-1,.px-1{padding-right:0.25rem !important}.pb-1,.py-1{padding-bottom:0.25rem !important}.pl-1,.px-1{padding-left:0.25rem !important}.p-2{padding:0.5rem !important}.pt-2,.py-2{padding-top:0.5rem !important}.pr-2,.px-2{padding-right:0.5rem !important}.pb-2,.py-2{padding-bottom:0.5rem !important}.pl-2,.px-2{padding-left:0.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-n1{margin:-0.25rem !important}.mt-n1,.my-n1{margin-top:-0.25rem !important}.mr-n1,.mx-n1{margin-right:-0.25rem !important}.mb-n1,.my-n1{margin-bottom:-0.25rem !important}.ml-n1,.mx-n1{margin-left:-0.25rem !important}.m-n2{margin:-0.5rem !important}.mt-n2,.my-n2{margin-top:-0.5rem !important}.mr-n2,.mx-n2{margin-right:-0.5rem !important}.mb-n2,.my-n2{margin-bottom:-0.5rem !important}.ml-n2,.mx-n2{margin-left:-0.5rem !important}.m-n3{margin:-1rem !important}.mt-n3,.my-n3{margin-top:-1rem !important}.mr-n3,.mx-n3{margin-right:-1rem !important}.mb-n3,.my-n3{margin-bottom:-1rem !important}.ml-n3,.mx-n3{margin-left:-1rem !important}.m-n4{margin:-1.5rem !important}.mt-n4,.my-n4{margin-top:-1.5rem !important}.mr-n4,.mx-n4{margin-right:-1.5rem !important}.mb-n4,.my-n4{margin-bottom:-1.5rem !important}.ml-n4,.mx-n4{margin-left:-1.5rem !important}.m-n5{margin:-3rem !important}.mt-n5,.my-n5{margin-top:-3rem !important}.mr-n5,.mx-n5{margin-right:-3rem !important}.mb-n5,.my-n5{margin-bottom:-3rem !important}.ml-n5,.mx-n5{margin-left:-3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media (min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:0.25rem !important}.mt-sm-1,.my-sm-1{margin-top:0.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:0.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:0.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:0.25rem !important}.m-sm-2{margin:0.5rem !important}.mt-sm-2,.my-sm-2{margin-top:0.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:0.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:0.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:0.5rem !important}.m-sm-3{margin:1rem !important}.mt-sm-3,.my-sm-3{margin-top:1rem !important}.mr-sm-3,.mx-sm-3{margin-right:1rem !important}.mb-sm-3,.my-sm-3{margin-bottom:1rem !important}.ml-sm-3,.mx-sm-3{margin-left:1rem !important}.m-sm-4{margin:1.5rem !important}.mt-sm-4,.my-sm-4{margin-top:1.5rem !important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem !important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem !important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem !important}.m-sm-5{margin:3rem !important}.mt-sm-5,.my-sm-5{margin-top:3rem !important}.mr-sm-5,.mx-sm-5{margin-right:3rem !important}.mb-sm-5,.my-sm-5{margin-bottom:3rem !important}.ml-sm-5,.mx-sm-5{margin-left:3rem !important}.p-sm-0{padding:0 !important}.pt-sm-0,.py-sm-0{padding-top:0 !important}.pr-sm-0,.px-sm-0{padding-right:0 !important}.pb-sm-0,.py-sm-0{padding-bottom:0 !important}.pl-sm-0,.px-sm-0{padding-left:0 !important}.p-sm-1{padding:0.25rem !important}.pt-sm-1,.py-sm-1{padding-top:0.25rem !important}.pr-sm-1,.px-sm-1{padding-right:0.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:0.25rem !important}.pl-sm-1,.px-sm-1{padding-left:0.25rem !important}.p-sm-2{padding:0.5rem !important}.pt-sm-2,.py-sm-2{padding-top:0.5rem !important}.pr-sm-2,.px-sm-2{padding-right:0.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:0.5rem !important}.pl-sm-2,.px-sm-2{padding-left:0.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-n1{margin:-0.25rem !important}.mt-sm-n1,.my-sm-n1{margin-top:-0.25rem !important}.mr-sm-n1,.mx-sm-n1{margin-right:-0.25rem !important}.mb-sm-n1,.my-sm-n1{margin-bottom:-0.25rem !important}.ml-sm-n1,.mx-sm-n1{margin-left:-0.25rem !important}.m-sm-n2{margin:-0.5rem !important}.mt-sm-n2,.my-sm-n2{margin-top:-0.5rem !important}.mr-sm-n2,.mx-sm-n2{margin-right:-0.5rem !important}.mb-sm-n2,.my-sm-n2{margin-bottom:-0.5rem !important}.ml-sm-n2,.mx-sm-n2{margin-left:-0.5rem !important}.m-sm-n3{margin:-1rem !important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem !important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem !important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem !important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem !important}.m-sm-n4{margin:-1.5rem !important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem !important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem !important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem !important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem !important}.m-sm-n5{margin:-3rem !important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem !important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem !important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem !important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:0.25rem !important}.mt-md-1,.my-md-1{margin-top:0.25rem !important}.mr-md-1,.mx-md-1{margin-right:0.25rem !important}.mb-md-1,.my-md-1{margin-bottom:0.25rem !important}.ml-md-1,.mx-md-1{margin-left:0.25rem !important}.m-md-2{margin:0.5rem !important}.mt-md-2,.my-md-2{margin-top:0.5rem !important}.mr-md-2,.mx-md-2{margin-right:0.5rem !important}.mb-md-2,.my-md-2{margin-bottom:0.5rem !important}.ml-md-2,.mx-md-2{margin-left:0.5rem !important}.m-md-3{margin:1rem !important}.mt-md-3,.my-md-3{margin-top:1rem !important}.mr-md-3,.mx-md-3{margin-right:1rem !important}.mb-md-3,.my-md-3{margin-bottom:1rem !important}.ml-md-3,.mx-md-3{margin-left:1rem !important}.m-md-4{margin:1.5rem !important}.mt-md-4,.my-md-4{margin-top:1.5rem !important}.mr-md-4,.mx-md-4{margin-right:1.5rem !important}.mb-md-4,.my-md-4{margin-bottom:1.5rem !important}.ml-md-4,.mx-md-4{margin-left:1.5rem !important}.m-md-5{margin:3rem !important}.mt-md-5,.my-md-5{margin-top:3rem !important}.mr-md-5,.mx-md-5{margin-right:3rem !important}.mb-md-5,.my-md-5{margin-bottom:3rem !important}.ml-md-5,.mx-md-5{margin-left:3rem !important}.p-md-0{padding:0 !important}.pt-md-0,.py-md-0{padding-top:0 !important}.pr-md-0,.px-md-0{padding-right:0 !important}.pb-md-0,.py-md-0{padding-bottom:0 !important}.pl-md-0,.px-md-0{padding-left:0 !important}.p-md-1{padding:0.25rem !important}.pt-md-1,.py-md-1{padding-top:0.25rem !important}.pr-md-1,.px-md-1{padding-right:0.25rem !important}.pb-md-1,.py-md-1{padding-bottom:0.25rem !important}.pl-md-1,.px-md-1{padding-left:0.25rem !important}.p-md-2{padding:0.5rem !important}.pt-md-2,.py-md-2{padding-top:0.5rem !important}.pr-md-2,.px-md-2{padding-right:0.5rem !important}.pb-md-2,.py-md-2{padding-bottom:0.5rem !important}.pl-md-2,.px-md-2{padding-left:0.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-n1{margin:-0.25rem !important}.mt-md-n1,.my-md-n1{margin-top:-0.25rem !important}.mr-md-n1,.mx-md-n1{margin-right:-0.25rem !important}.mb-md-n1,.my-md-n1{margin-bottom:-0.25rem !important}.ml-md-n1,.mx-md-n1{margin-left:-0.25rem !important}.m-md-n2{margin:-0.5rem !important}.mt-md-n2,.my-md-n2{margin-top:-0.5rem !important}.mr-md-n2,.mx-md-n2{margin-right:-0.5rem !important}.mb-md-n2,.my-md-n2{margin-bottom:-0.5rem !important}.ml-md-n2,.mx-md-n2{margin-left:-0.5rem !important}.m-md-n3{margin:-1rem !important}.mt-md-n3,.my-md-n3{margin-top:-1rem !important}.mr-md-n3,.mx-md-n3{margin-right:-1rem !important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem !important}.ml-md-n3,.mx-md-n3{margin-left:-1rem !important}.m-md-n4{margin:-1.5rem !important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem !important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem !important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem !important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem !important}.m-md-n5{margin:-3rem !important}.mt-md-n5,.my-md-n5{margin-top:-3rem !important}.mr-md-n5,.mx-md-n5{margin-right:-3rem !important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem !important}.ml-md-n5,.mx-md-n5{margin-left:-3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media (min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:0.25rem !important}.mt-lg-1,.my-lg-1{margin-top:0.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:0.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:0.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:0.25rem !important}.m-lg-2{margin:0.5rem !important}.mt-lg-2,.my-lg-2{margin-top:0.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:0.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:0.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:0.5rem !important}.m-lg-3{margin:1rem !important}.mt-lg-3,.my-lg-3{margin-top:1rem !important}.mr-lg-3,.mx-lg-3{margin-right:1rem !important}.mb-lg-3,.my-lg-3{margin-bottom:1rem !important}.ml-lg-3,.mx-lg-3{margin-left:1rem !important}.m-lg-4{margin:1.5rem !important}.mt-lg-4,.my-lg-4{margin-top:1.5rem !important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem !important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem !important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem !important}.m-lg-5{margin:3rem !important}.mt-lg-5,.my-lg-5{margin-top:3rem !important}.mr-lg-5,.mx-lg-5{margin-right:3rem !important}.mb-lg-5,.my-lg-5{margin-bottom:3rem !important}.ml-lg-5,.mx-lg-5{margin-left:3rem !important}.p-lg-0{padding:0 !important}.pt-lg-0,.py-lg-0{padding-top:0 !important}.pr-lg-0,.px-lg-0{padding-right:0 !important}.pb-lg-0,.py-lg-0{padding-bottom:0 !important}.pl-lg-0,.px-lg-0{padding-left:0 !important}.p-lg-1{padding:0.25rem !important}.pt-lg-1,.py-lg-1{padding-top:0.25rem !important}.pr-lg-1,.px-lg-1{padding-right:0.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:0.25rem !important}.pl-lg-1,.px-lg-1{padding-left:0.25rem !important}.p-lg-2{padding:0.5rem !important}.pt-lg-2,.py-lg-2{padding-top:0.5rem !important}.pr-lg-2,.px-lg-2{padding-right:0.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:0.5rem !important}.pl-lg-2,.px-lg-2{padding-left:0.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-n1{margin:-0.25rem !important}.mt-lg-n1,.my-lg-n1{margin-top:-0.25rem !important}.mr-lg-n1,.mx-lg-n1{margin-right:-0.25rem !important}.mb-lg-n1,.my-lg-n1{margin-bottom:-0.25rem !important}.ml-lg-n1,.mx-lg-n1{margin-left:-0.25rem !important}.m-lg-n2{margin:-0.5rem !important}.mt-lg-n2,.my-lg-n2{margin-top:-0.5rem !important}.mr-lg-n2,.mx-lg-n2{margin-right:-0.5rem !important}.mb-lg-n2,.my-lg-n2{margin-bottom:-0.5rem !important}.ml-lg-n2,.mx-lg-n2{margin-left:-0.5rem !important}.m-lg-n3{margin:-1rem !important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem !important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem !important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem !important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem !important}.m-lg-n4{margin:-1.5rem !important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem !important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem !important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem !important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem !important}.m-lg-n5{margin:-3rem !important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem !important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem !important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem !important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media (min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:0.25rem !important}.mt-xl-1,.my-xl-1{margin-top:0.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:0.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:0.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:0.25rem !important}.m-xl-2{margin:0.5rem !important}.mt-xl-2,.my-xl-2{margin-top:0.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:0.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:0.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:0.5rem !important}.m-xl-3{margin:1rem !important}.mt-xl-3,.my-xl-3{margin-top:1rem !important}.mr-xl-3,.mx-xl-3{margin-right:1rem !important}.mb-xl-3,.my-xl-3{margin-bottom:1rem !important}.ml-xl-3,.mx-xl-3{margin-left:1rem !important}.m-xl-4{margin:1.5rem !important}.mt-xl-4,.my-xl-4{margin-top:1.5rem !important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem !important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem !important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem !important}.m-xl-5{margin:3rem !important}.mt-xl-5,.my-xl-5{margin-top:3rem !important}.mr-xl-5,.mx-xl-5{margin-right:3rem !important}.mb-xl-5,.my-xl-5{margin-bottom:3rem !important}.ml-xl-5,.mx-xl-5{margin-left:3rem !important}.p-xl-0{padding:0 !important}.pt-xl-0,.py-xl-0{padding-top:0 !important}.pr-xl-0,.px-xl-0{padding-right:0 !important}.pb-xl-0,.py-xl-0{padding-bottom:0 !important}.pl-xl-0,.px-xl-0{padding-left:0 !important}.p-xl-1{padding:0.25rem !important}.pt-xl-1,.py-xl-1{padding-top:0.25rem !important}.pr-xl-1,.px-xl-1{padding-right:0.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:0.25rem !important}.pl-xl-1,.px-xl-1{padding-left:0.25rem !important}.p-xl-2{padding:0.5rem !important}.pt-xl-2,.py-xl-2{padding-top:0.5rem !important}.pr-xl-2,.px-xl-2{padding-right:0.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:0.5rem !important}.pl-xl-2,.px-xl-2{padding-left:0.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-n1{margin:-0.25rem !important}.mt-xl-n1,.my-xl-n1{margin-top:-0.25rem !important}.mr-xl-n1,.mx-xl-n1{margin-right:-0.25rem !important}.mb-xl-n1,.my-xl-n1{margin-bottom:-0.25rem !important}.ml-xl-n1,.mx-xl-n1{margin-left:-0.25rem !important}.m-xl-n2{margin:-0.5rem !important}.mt-xl-n2,.my-xl-n2{margin-top:-0.5rem !important}.mr-xl-n2,.mx-xl-n2{margin-right:-0.5rem !important}.mb-xl-n2,.my-xl-n2{margin-bottom:-0.5rem !important}.ml-xl-n2,.mx-xl-n2{margin-left:-0.5rem !important}.m-xl-n3{margin:-1rem !important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem !important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem !important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem !important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem !important}.m-xl-n4{margin:-1.5rem !important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem !important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem !important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem !important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem !important}.m-xl-n5{margin:-3rem !important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem !important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem !important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem !important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important}.text-justify{text-align:justify !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}@media (min-width: 576px){.text-sm-left{text-align:left !important}.text-sm-right{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.text-md-left{text-align:left !important}.text-md-right{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.text-lg-left{text-align:left !important}.text-lg-right{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.text-xl-left{text-align:left !important}.text-xl-right{text-align:right !important}.text-xl-center{text-align:center !important}}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.font-weight-light{font-weight:300 !important}.font-weight-lighter{font-weight:lighter !important}.font-weight-normal{font-weight:400 !important}.font-weight-bold{font-weight:700 !important}.font-weight-bolder{font-weight:bolder !important}.font-italic{font-style:italic !important}.text-white{color:#fff !important}.text-primary{color:#375a7f !important}a.text-primary:hover,a.text-primary:focus{color:#20344a !important}.text-secondary{color:#444 !important}a.text-secondary:hover,a.text-secondary:focus{color:#1e1e1e !important}.text-success{color:#00bc8c !important}a.text-success:hover,a.text-success:focus{color:#007053 !important}.text-info{color:#3498DB !important}a.text-info:hover,a.text-info:focus{color:#1d6fa5 !important}.text-warning{color:#F39C12 !important}a.text-warning:hover,a.text-warning:focus{color:#b06f09 !important}.text-danger{color:#E74C3C !important}a.text-danger:hover,a.text-danger:focus{color:#bf2718 !important}.text-light{color:#adb5bd !important}a.text-light:hover,a.text-light:focus{color:#838f9b !important}.text-dark{color:#303030 !important}a.text-dark:hover,a.text-dark:focus{color:#0a0a0a !important}.text-body{color:#fff !important}.text-muted{color:#888 !important}.text-black-50{color:rgba(0,0,0,0.5) !important}.text-white-50{color:rgba(255,255,255,0.5) !important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none !important}.text-break{word-wrap:break-word !important}.text-reset{color:inherit !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media print{*,*::before,*::after{text-shadow:none !important;-webkit-box-shadow:none !important;box-shadow:none !important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap !important}pre,blockquote{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px !important}.container{min-width:992px !important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #dee2e6 !important}.table-dark{color:inherit}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#444}.table .thead-dark th{color:inherit;border-color:#444}}.blockquote-footer{color:#888}.table-primary,.table-primary>th,.table-primary>td{background-color:#375a7f}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#444}.table-light,.table-light>th,.table-light>td{background-color:#adb5bd}.table-dark,.table-dark>th,.table-dark>td{background-color:#303030}.table-success,.table-success>th,.table-success>td{background-color:#00bc8c}.table-info,.table-info>th,.table-info>td{background-color:#3498DB}.table-danger,.table-danger>th,.table-danger>td{background-color:#E74C3C}.table-warning,.table-warning>th,.table-warning>td{background-color:#F39C12}.table-active,.table-active>th,.table-active>td{background-color:rgba(0,0,0,0.075)}.table-hover .table-primary:hover,.table-hover .table-primary:hover>th,.table-hover .table-primary:hover>td{background-color:#2f4d6d}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>th,.table-hover .table-secondary:hover>td{background-color:#373737}.table-hover .table-light:hover,.table-hover .table-light:hover>th,.table-hover .table-light:hover>td{background-color:#9fa8b2}.table-hover .table-dark:hover,.table-hover .table-dark:hover>th,.table-hover .table-dark:hover>td{background-color:#232323}.table-hover .table-success:hover,.table-hover .table-success:hover>th,.table-hover .table-success:hover>td{background-color:#00a379}.table-hover .table-info:hover,.table-hover .table-info:hover>th,.table-hover .table-info:hover>td{background-color:#258cd1}.table-hover .table-danger:hover,.table-hover .table-danger:hover>th,.table-hover .table-danger:hover>td{background-color:#e43725}.table-hover .table-warning:hover,.table-hover .table-warning:hover>th,.table-hover .table-warning:hover>td{background-color:#e08e0b}.table-hover .table-active:hover,.table-hover .table-active:hover>th,.table-hover .table-active:hover>td{background-color:rgba(0,0,0,0.075)}.input-group-addon{color:#fff}.nav-tabs .nav-link,.nav-tabs .nav-link.active,.nav-tabs .nav-link.active:focus,.nav-tabs .nav-link.active:hover,.nav-tabs .nav-item.open .nav-link,.nav-tabs .nav-item.open .nav-link:focus,.nav-tabs .nav-item.open .nav-link:hover,.nav-pills .nav-link,.nav-pills .nav-link.active,.nav-pills .nav-link.active:focus,.nav-pills .nav-link.active:hover,.nav-pills .nav-item.open .nav-link,.nav-pills .nav-item.open .nav-link:focus,.nav-pills .nav-item.open .nav-link:hover{color:#fff}.breadcrumb a{color:#fff}.pagination a:hover{text-decoration:none}.close{opacity:0.4}.close:hover,.close:focus{opacity:1}.alert{border:none;color:#fff}.alert a,.alert .alert-link{color:#fff;text-decoration:underline}.alert-primary{background-color:#375a7f}.alert-secondary{background-color:#444}.alert-success{background-color:#00bc8c}.alert-info{background-color:#3498DB}.alert-warning{background-color:#F39C12}.alert-danger{background-color:#E74C3C}.alert-light{background-color:#adb5bd}.alert-dark{background-color:#303030}.list-group-item-action{color:#fff}.list-group-item-action:hover,.list-group-item-action:focus{background-color:#444;color:#fff}.list-group-item-action .list-group-item-heading{color:#fff} diff --git a/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/css/site.css b/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/css/site.css index f387e3dde..2f22560a1 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/css/site.css +++ b/src/Features/Blockcore.Features.NodeHost/UI/wwwroot/css/site.css @@ -31,8 +31,8 @@ app { } .main .top-row { - background-color: #f7f7f7; - border-bottom: 1px solid #d6d5d5; + /* background-color: #f7f7f7; + border-bottom: 1px solid #d6d5d5; */ justify-content: flex-end; } @@ -47,7 +47,7 @@ app { } .sidebar { - background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #375d7d 70%); + /* background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #375d7d 70%); */ } .sidebar .top-row { diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor index 54d34be81..3b9b5bb97 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletAccount.razor @@ -20,39 +20,61 @@ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Sin
-
-

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

-

@accountBalance.AmountUnconfirmed (unconfirmed)

+
+
+
+
+
Main Balance
+
+
+
+

@accountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@accountBalance.AmountUnconfirmed (unconfirmed)
+
+
+
// For now just show last 100 trx of history. var model = WalletModelBuilder.GetHistory(this.WalletManager, Network, new WalletHistoryRequest { WalletName = walletname, AccountName = accountname, Take = 100 }); - -
- - - - - - - - - - - @foreach (var history in model.AccountsHistoryModel) - { - foreach (var transaction in history.TransactionsHistory) - { - @*@onclick="() => { NavigateToViewTx(transaction.Id); }" > *@ - - - - - - } - } - -
TYPEDATE/TIMEAMOUNTBLOCK
@transaction.Type@String.Format("{0:f}", transaction.Timestamp)@transaction.Amount@transaction.ConfirmedInBlock
+
+
+
+
+

History

+
+ + + + + + + + + + + @foreach (var history in model.AccountsHistoryModel) + { + foreach (var transaction in history.TransactionsHistory) + { + @*@onclick="() => { NavigateToViewTx(transaction.Id); }" > *@ + + + + + + } + } + +
TYPEDATE/TIMEAMOUNTBLOCK
@transaction.Type@String.Format("{0:f}", transaction.Timestamp)@transaction.Amount@transaction.ConfirmedInBlock
+
+
+
+
} diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletBroadcastTx.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletBroadcastTx.razor new file mode 100644 index 000000000..092fb312f --- /dev/null +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletBroadcastTx.razor @@ -0,0 +1,109 @@ +@page "/walletbroadcasttx/{walletname}/{accountname}" + +@using Blockcore.Features.Wallet.Interfaces +@using Blockcore.Features.Wallet; +@using NBitcoin; +@using Blockcore.Connection.Broadcasting +@using Blockcore.Features.Wallet.Types +@using Blockcore.Interfaces + +@inject IWalletManager WalletManager +@inject NavigationManager NavigationManager +@inject Network Network +@inject Blockcore.Connection.IConnectionManager ConnectionManager +@inject IWalletTransactionHandler WalletTransactionHandler +@inject IBroadcasterManager BroadcasterManager + + +
+

Broadcast Transaction from: @walletname

+
+
+
+ +@{ +var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); +
+
+
+
+
Main Balance
+
+
+
+

@accountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@accountBalance.AmountUnconfirmed (unconfirmed)
+
+
+
+
+ +
+
+
+
+
+
+ Raw Transaction +
+ +
+
+ +
+
+
@Alert
+
+
+
@Success
+
+
+
+
+
+} + +@code +{ + [Parameter] + public string walletname { get; set; } + [Parameter] + public string accountname { get; set; } + + string TransactionHex { get; set; } + + string Alert { get; set; } + + string Success { get; set; } + + private async Task Broadcast() + { + if (string.IsNullOrEmpty(this.TransactionHex)) { this.Alert = "No transaction details, please click send coins first"; return; } + this.Alert = string.Empty; + + if (!this.ConnectionManager.ConnectedPeers.Any()) + { + this.Alert = "No peers connected. You need connections before a transaction can be brodcast to the network."; + return; + } + + Transaction transaction = this.Network.CreateTransaction(this.TransactionHex); + + await this.BroadcasterManager.BroadcastTransactionAsync(transaction); + + var transactionBroadCastEntry = this.BroadcasterManager.GetTransaction(transaction.GetHash()); + + if (transactionBroadCastEntry.TransactionBroadcastState == TransactionBroadcastState.FailedBroadcast) + { + this.Alert = "An error occurred: " + transactionBroadCastEntry.ErrorMessage; + return; + } + + this.Success = "Coins sent."; + } + +} \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor index cd1d51757..e0a38e414 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletCreate.razor @@ -17,48 +17,47 @@

Create your wallet by generating a Mnemonic & adding an optional phrase. Then give your wallet a name & password.

@{ - -
- -
- -
-
- Mnemonic: +
+
+
+
+
+ +
+
+
+ Mnemonic: +
+ +
+

Important: The Mnemonic is your wallet and must be kept safe and secure.

+
+
+ Passphrase (optional): +
+ +
+

Important: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

+
+
+ Wallet name: +
+ +
+
+
+ Wallet Password: +
+ +
+ +
+
@Alert
+
+
- -
-

Important: The Mnemonic is your wallet and must be kept safe and secure.

- -
-
- Passphrase (optional): -
- -
-

Important: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

- - -
-
- Wallet name: -
- -
- -
-
- Wallet Password: -
- -
- - - -
-
-
@Alert
+
} @code { diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor index fc6529e5a..5cbb91524 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletReceive.razor @@ -14,21 +14,29 @@
@{ - var result = this.WalletManager.GetUnusedAddress(new WalletAccountReference(walletname, accountname)); +var result = this.WalletManager.GetUnusedAddress(new WalletAccountReference(walletname, accountname)); -
- - - - - - - - - - - -
Address:
Segwit Address:
+
+
+
+
+
+ + + + + + + + + + + +
Address:
Segwit Address:
+
+
+
+
} diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor index 82fda0174..b70612d69 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletRecover.razor @@ -17,42 +17,50 @@

Recover your wallet by entering your Mnemonic & your passphrase. Then give your wallet a name & password.

@{ -
-
- Mnemonic +
+
+
+
+
+
+ Mnemonic +
+ +
+

Reminder: The Mnemonic is your wallet and must be kept safe and secure.

+ +
+
+ Passphrase (optional): +
+ +
+

Reminder: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

+ +
+
+ Wallet name: +
+ +
+ +
+
+ Wallet Password: +
+ +
+ + + +
+
+
@Alert
+
+
- -
-

Reminder: The Mnemonic is your wallet and must be kept safe and secure.

- -
-
- Passphrase (optional): -
- -
-

Reminder: The Passphrase is permanently linked to the wallet and must be kept safe and secure.

- -
-
- Wallet name: -
- -
- -
-
- Wallet Password: -
- -
- - - -
-
-
@Alert
+
} @code { diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index f5fe46f32..dc36edea7 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -14,85 +14,115 @@ @inject IWalletTransactionHandler WalletTransactionHandler @inject IBroadcasterManager BroadcasterManager - +@{

Send coins from: @walletname

+
-@{ - - var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); - -
-

@accountBalance.AmountConfirmed @this.Network.CoinTicker.ToUpper()

-

@accountBalance.AmountUnconfirmed (unconfirmed)

-
- -
-
- To Address: -
- -
- -
-
- Amount: -
- -
- @this.Network.CoinTicker.ToUpper() -
-
- -
-
- Fee: -
- -
- Optional (default to low) +var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Single(); +
+
+
+
+
Main Balance
+
+
+
+

@accountBalance.AmountConfirmed

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@accountBalance.AmountUnconfirmed (unconfirmed)
+
+
-
-
- Password: +
+
+
+
+
+
+ To Address: +
+ +
+ +
+
+ Amount: +
+ +
+ @this.Network.CoinTicker.ToUpper() +
+
+ +
+
+ Fee: +
+ +
+ +
+
+ +
+
+ Password: +
+ +
+ +
+ @if (IsSending) + { } + else + { } +
+ +
+
@Alert
+
+ +
+
@Success
+
+
-
+
-
- -
-
- -
-
@Alert
-
- -

Broadcast Transaction

- -

Transaction hash: @SentTransactionHash

- -
-
- Raw Transaction +

Transaction Details

+ +
+
+
+
+

Transaction hash: @SentTransactionHash

+
+
+ Raw Transaction +
+ +
+
+ + @*
+ +
*@ +
- -
-
-
- -
- -
-
@Success
+
} - @code { [Parameter] @@ -115,14 +145,16 @@ string Alert { get; set; } string Success { get; set; } - protected override void OnInitialized() { this.Fee = new Money(this.Network.MinTxFee).ToDecimal(MoneyUnit.BTC); } - public void EstimateFee() { + if (string.IsNullOrEmpty(this.Address)) { this.Alert = "Please enter a valid address"; return; } + if (this.Amount == 0) { this.Alert = "Please enter the number of coins you want to send"; return; } + this.Alert = string.Empty; + var recipients = new List(); recipients.Add(new Recipient { @@ -140,40 +172,21 @@ this.Fee = this.WalletTransactionHandler.EstimateFee(context).ToDecimal(MoneyUnit.BTC); } - - private void NavigateToWalletAccount(string walletName, string accountname) - { - NavigationManager.NavigateTo("walletaccount/" + walletName + "/" + accountname); - } - - private async Task Broadcast() + private bool IsSending { get; set; } + private async Task callSendCoins() { - if (string.IsNullOrEmpty(this.TransactionHex)) { this.Alert = "No transaction details, please click send coins first"; return; } - - this.Alert = string.Empty; - - if (!this.ConnectionManager.ConnectedPeers.Any()) + IsSending = true; + StateHasChanged(); + await Task.Delay(1); { - this.Alert = "No peers connected. You need connections before a transaction can be brodcast to the network."; - return; + SendCoins(); } - - Transaction transaction = this.Network.CreateTransaction(this.TransactionHex); - - await this.BroadcasterManager.BroadcastTransactionAsync(transaction); - - var transactionBroadCastEntry = this.BroadcasterManager.GetTransaction(transaction.GetHash()); - - if (transactionBroadCastEntry.TransactionBroadcastState == TransactionBroadcastState.FailedBroadcast) - { - this.Alert = "An error occurred: " + transactionBroadCastEntry.ErrorMessage; - return; - } - - this.Success = "Coins sent."; + IsSending = false; + StateHasChanged(); + await Task.Delay(1); } - private void SendCoins() + private async Task SendCoins() { if (string.IsNullOrEmpty(this.Password)) { this.Alert = "Please enter a password"; return; } if (string.IsNullOrEmpty(this.Address)) { this.Alert = "Please enter a valid address"; return; } @@ -182,6 +195,12 @@ this.Alert = string.Empty; + if (!this.ConnectionManager.ConnectedPeers.Any()) + { + this.Alert = "No peers connected. You need connections before a transaction can be brodcast to the network."; + return; + } + var recipients = new List(); recipients.Add(new Recipient { @@ -203,5 +222,28 @@ this.SentTransactionHash = transactionResult.GetHash(); this.TransactionHex = transactionResult.ToHex(this.Network.Consensus.ConsensusFactory); + @* } + private async Task Broadcast() + { + if (string.IsNullOrEmpty(this.TransactionHex)) { this.Alert = "No transaction details, please click send coins first"; return; } + this.Alert = string.Empty; *@ + + Transaction transaction = this.Network.CreateTransaction(this.TransactionHex); + + await this.BroadcasterManager.BroadcastTransactionAsync(transaction); + + var transactionBroadCastEntry = this.BroadcasterManager.GetTransaction(transaction.GetHash()); + + if (transactionBroadCastEntry.TransactionBroadcastState == TransactionBroadcastState.FailedBroadcast) + { + this.Alert = "An error occurred: " + transactionBroadCastEntry.ErrorMessage; + return; + } + StateHasChanged(); + this.Success = "Coins sent."; + } + private void NavigateToBroadcastTx(string walletName, string accountname) + { + NavigationManager.NavigateTo("walletbroadcasttx/" + walletName + "/" + accountname); } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor index c29288f4b..12980ec3e 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Wallets.razor @@ -22,45 +22,65 @@
- -
-
-

@totalBalance() @this.Network.CoinTicker.ToUpper()

-

@totalUnconfirmedBalance() (unconfirmed)

-
+
+
+
+
+
Main Balance
+
+
+
+

@totalBalance()

+

@this.Network.CoinTicker.ToUpper()

+
+
+
+
@totalUnconfirmedBalance() (unconfirmed)
+
+
+
-
- - - - - - - - - - @{ - foreach (var walletName in this.WalletManager.GetWalletsNames()) - { - foreach (var account in this.WalletManager.GetAccounts(walletName)) - { - var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); +
+
+
+
+

Balances

-
- - - - - } - } - } - -
WalletConfirmed balanceUnconfirmed balance
@walletName@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed
+
+ + + + + + + + + + @{ + foreach (var walletName in this.WalletManager.GetWalletsNames()) + { + foreach (var account in this.WalletManager.GetAccounts(walletName)) + { + var accountBalance = this.WalletManager.GetBalances(walletName, account.Name).Single(); + + + + + + + } + } + } + +
WalletConfirmed balanceUnconfirmed balance
@walletName@accountBalance.AmountConfirmed@accountBalance.AmountUnconfirmed
+
+

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

+
+
+
-

Wallet Tip: @this.WalletSyncManager.WalletTip.Height / @ChainIndexer.Height

} - @code { private void NavigateToWallet(string walletName, string accountname) From 2b694bd1cc3ebcd7881070006a5d1c2952b32ece Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 1 Jun 2020 13:11:59 +0100 Subject: [PATCH 39/44] Add redirection after tx broadcast --- .../UI/Pages/ColdStakeDelegate.razor | 5 ++--- .../UI/Pages/ColdStakeSetup.razor | 4 ++-- .../UI/Pages/ColdStakeWithdraw.razor | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor index 9b520143c..e1e42b4c1 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor @@ -135,7 +135,6 @@ var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0") protected override Task OnInitializedAsync() { - //TODO Check Coldstake Address ColdStakingManager = this.WalletManager as ColdStakingManager; this.Fee = new Money(this.Network.MinTxFee).ToDecimal(MoneyUnit.BTC); var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(this.walletname, true); @@ -191,7 +190,7 @@ var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0") Alert = ex.Message; return; } - - NavigationManager.NavigateTo("coldstaking"); + //TODO: Add confirmation screen + NavigationManager.NavigateTo("coldstakeview/" + walletname + "/coldStakingColdAddresses"); } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor index 085fb69c3..d554a7ca3 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor @@ -232,7 +232,7 @@ var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0") Alert = ex.Message; return; } - - NavigationManager.NavigateTo("coldstaking"); + //TODO: Add confirmation screen + NavigationManager.NavigateTo("coldstakeview/" + walletname + "/coldStakingColdAddresses"); } } \ No newline at end of file diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor index 4a52d6649..5fb8d94ec 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor @@ -177,7 +177,7 @@ var mainAccountBalance = this.WalletManager.GetBalances(walletname, "account 0") Alert = ex.Message; return; } - - NavigationManager.NavigateTo("coldstaking"); + //TODO: Add confirmation screen + NavigationManager.NavigateTo("coldstakeview/" + walletname + "/coldStakingColdAddresses"); } } \ No newline at end of file From 42652862720edaea7f0416cee84a1415c99b4833 Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 1 Jun 2020 13:13:17 +0100 Subject: [PATCH 40/44] Remove tx hex & add redirection --- .../UI/Pages/WalletSend.razor | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index dc36edea7..7714f2a4b 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -99,7 +99,8 @@ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Sin
- +@* +// TODO add confirmation screeen

Transaction Details

@@ -107,21 +108,16 @@ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Sin

Transaction hash: @SentTransactionHash

-
-
- Raw Transaction +
+
+ Raw Transaction +
+
- -
-
- - @*
- -
*@
-
+
*@ } @code { @@ -222,11 +218,6 @@ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Sin this.SentTransactionHash = transactionResult.GetHash(); this.TransactionHex = transactionResult.ToHex(this.Network.Consensus.ConsensusFactory); - @* } - private async Task Broadcast() - { - if (string.IsNullOrEmpty(this.TransactionHex)) { this.Alert = "No transaction details, please click send coins first"; return; } - this.Alert = string.Empty; *@ Transaction transaction = this.Network.CreateTransaction(this.TransactionHex); @@ -239,8 +230,9 @@ var accountBalance = this.WalletManager.GetBalances(walletname, accountname).Sin this.Alert = "An error occurred: " + transactionBroadCastEntry.ErrorMessage; return; } - StateHasChanged(); this.Success = "Coins sent."; + + NavigationManager.NavigateTo("walletaccount/" + walletname + "/" + accountname); } private void NavigateToBroadcastTx(string walletName, string accountname) { From f2510c8bea969362274dfa5acc212666dc6c226e Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 1 Jun 2020 13:13:43 +0100 Subject: [PATCH 41/44] UI tweaks --- .../UI/Pages/Index.razor | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor index a984e0220..88005f772 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Pages/Index.razor @@ -40,20 +40,20 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload())
- +
- - - - - - - - - - - - + + + + + + + + + + + +
Connected peers:@this.ConnectionManager.ConnectedPeers.Count()
Current tip at height:@this.ChainIndexer.Tip.Height
Current tip Hash:@this.ChainIndexer.Tip.HashBlock
Connected peers:@this.ConnectionManager.ConnectedPeers.Count()
Current tip at height:@this.ChainIndexer.Tip.Height
Current tip Hash:@this.ChainIndexer.Tip.HashBlock
@@ -62,7 +62,7 @@ if (this.InitialBlockDownloadState.IsInitialBlockDownload())
-
+
From 4f6f37ab319f9feff97c965bd4dd69c7741304f6 Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 1 Jun 2020 17:18:20 +0100 Subject: [PATCH 42/44] Add referenc for menu icons --- src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor index c7cef8a45..ee279ebb8 100644 --- a/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor +++ b/src/Features/Blockcore.Features.NodeHost/UI/Shared/NavMenu.razor @@ -25,6 +25,7 @@ } From f74457e2fe037d42240aa68ed2688d247d877fe6 Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 1 Jun 2020 17:18:46 +0100 Subject: [PATCH 43/44] ensure menu not broken with long wallet names --- .../Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor index cf851207f..c889ab2dd 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeView.razor @@ -12,7 +12,7 @@ @{
-

Cold Staking Dashboard for @walletname

+

Cold Staking Dashboard for @walletname

From 6cc443c8b972e8f8b6942c35c555fc1bd8af605c Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 1 Jun 2020 17:22:50 +0100 Subject: [PATCH 44/44] change icon for cold staking --- src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs b/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs index 84e60e425..2ae003eaf 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs +++ b/src/Features/Blockcore.Features.ColdStaking/UI/NavItem.cs @@ -6,6 +6,6 @@ public class ColdStakingNavigationItem : INavigationItem { public string Name => "Cold Staking"; public string Navigation => "ColdStaking"; - public string Icon => "oi-cloud"; + public string Icon => "oi-pulse"; } } \ No newline at end of file