Merge pull request #1727 from dennisreimann/ui-updates-server

UI updates: Server settings section
This commit is contained in:
Nicolas Dorier
2020-07-13 17:38:33 +09:00
committed by GitHub
11 changed files with 258 additions and 252 deletions

View File

@@ -115,7 +115,7 @@ namespace BTCPayServer.Controllers
MaintenanceViewModel vm = new MaintenanceViewModel();
vm.CanUseSSH = _sshState.CanUseSSH;
if (!vm.CanUseSSH)
TempData[WellKnownTempData.ErrorMessage] = "Maintenance feature requires access to SSH properly configured in BTCPayServer configuration";
TempData[WellKnownTempData.ErrorMessage] = "Maintenance feature requires access to SSH properly configured in BTCPayServer configuration.";
vm.DNSDomain = this.Request.Host.Host;
if (IPAddress.TryParse(vm.DNSDomain, out var unused))
vm.DNSDomain = null;

View File

@@ -1,6 +1,6 @@
@inject SignInManager<ApplicationUser> SignInManager
<div class="nav flex-column nav-pills">
<div class="nav flex-column nav-pills mb-4">
<a id="@ManageNavPages.Index.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.Index)" asp-action="Index">Profile</a>
<a id="@ManageNavPages.ChangePassword.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.ChangePassword)" asp-action="ChangePassword">Password</a>
<a id="@ManageNavPages.TwoFactorAuthentication.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.TwoFactorAuthentication)" asp-action="TwoFactorAuthentication">Two-factor authentication</a>

View File

@@ -6,87 +6,93 @@
<partial name="_StatusMessage" />
<div class="row button-row">
<div class="col align-self-center">Total Users: @Model.Total</div>
<div class="col text-right">
<a asp-controller="Account"
asp-action="Register"
asp-route-returnUrl="@Context.Request.GetCurrentPath()"
asp-route-logon="false"
asp-route-useBasicLayout="true"
class="btn btn-primary"
role="button">
<span class="fa fa-plus"></span> Add User
</a>
<div class="col-lg-9 col-xl-8">
<span>Total Users: @Model.Total</span>
<span class="pull-right">
<a asp-controller="Account"
asp-action="Register"
asp-route-returnUrl="@Context.Request.GetCurrentPath()"
asp-route-logon="false"
asp-route-useBasicLayout="true"
class="btn btn-primary"
role="button">
<span class="fa fa-plus"></span> Add User
</a>
</span>
</div>
</div>
<table class="table table-sm table-responsive-md">
<thead>
<tr>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var user in Model.Users)
{
<div class="row">
<div class="col-lg-9 col-xl-8">
<table class="table table-sm">
<thead>
<tr>
<td>@user.Email</td>
<td><a asp-action="User" asp-route-userId="@user.Id">Edit</a> <span> - </span> <a asp-action="DeleteUser" asp-route-userId="@user.Id">Remove</a></td>
<th>Email</th>
<th class="text-right">Actions</th>
</tr>
}
</tbody>
</table>
</thead>
<tbody>
@foreach (var user in Model.Users)
{
<tr>
<td>@user.Email</td>
<td class="text-right"><a asp-action="User" asp-route-userId="@user.Id">Edit</a> <span> - </span> <a asp-action="DeleteUser" asp-route-userId="@user.Id">Remove</a></td>
</tr>
}
</tbody>
</table>
<nav aria-label="..." class="w-100">
<ul class="pagination float-left">
<li class="page-item @(Model.Skip == 0 ? "disabled" : null)">
<a class="page-link" tabindex="-1" href="@listUsers(-1, Model.Count)">&laquo;</a>
</li>
<li class="page-item disabled">
<span class="page-link">@(Model.Skip + 1) to @(Model.Skip + Model.Users.Count) of @Model.Total</span>
</li>
<li class="page-item @(Model.Total > (Model.Skip + Model.Users.Count) ? null : "disabled")">
<a class="page-link" href="@listUsers(1, Model.Count)">&raquo;</a>
</li>
</ul>
<ul class="pagination float-right">
<li class="page-item disabled">
<span class="page-link">Page Size:</span>
</li>
<li class="page-item @(Model.Count == 50 ? "active" : null)">
<a class="page-link" href="@listUsers(0, 50)">50</a>
</li>
<li class="page-item @(Model.Count == 100 ? "active" : null)">
<a class="page-link" href="@listUsers(0, 100)">100</a>
</li>
<li class="page-item @(Model.Count == 250 ? "active" : null)">
<a class="page-link" href="@listUsers(0, 250)">250</a>
</li>
<li class="page-item @(Model.Count == 500 ? "active" : null)">
<a class="page-link" href="@listUsers(0, 500)">500</a>
</li>
</ul>
</nav>
@{
string listUsers(int prevNext, int count)
{
var skip = Model.Skip;
if (prevNext == -1)
{
skip = Math.Max(0, Model.Skip - Model.Count);
}
else if (prevNext == 1)
{
skip = Model.Skip + count;
}
<nav aria-label="..." class="w-100">
<ul class="pagination float-left">
<li class="page-item @(Model.Skip == 0 ? "disabled" : null)">
<a class="page-link" tabindex="-1" href="@listUsers(-1, Model.Count)">&laquo;</a>
</li>
<li class="page-item disabled">
<span class="page-link">@(Model.Skip + 1) to @(Model.Skip + Model.Users.Count) of @Model.Total</span>
</li>
<li class="page-item @(Model.Total > (Model.Skip + Model.Users.Count) ? null : "disabled")">
<a class="page-link" href="@listUsers(1, Model.Count)">&raquo;</a>
</li>
</ul>
<ul class="pagination float-right">
<li class="page-item disabled">
<span class="page-link">Page Size:</span>
</li>
<li class="page-item @(Model.Count == 50 ? "active" : null)">
<a class="page-link" href="@listUsers(0, 50)">50</a>
</li>
<li class="page-item @(Model.Count == 100 ? "active" : null)">
<a class="page-link" href="@listUsers(0, 100)">100</a>
</li>
<li class="page-item @(Model.Count == 250 ? "active" : null)">
<a class="page-link" href="@listUsers(0, 250)">250</a>
</li>
<li class="page-item @(Model.Count == 500 ? "active" : null)">
<a class="page-link" href="@listUsers(0, 500)">500</a>
</li>
</ul>
</nav>
@{
string listUsers(int prevNext, int count)
{
var skip = Model.Skip;
if (prevNext == -1)
{
skip = Math.Max(0, Model.Skip - Model.Count);
}
else if (prevNext == 1)
{
skip = Model.Skip + count;
}
var act = Url.Action("ListUsers", new
{
skip = skip,
count = count,
});
var act = Url.Action("ListUsers", new
{
skip = skip,
count = count,
});
return act;
}
}
return act;
}
}
</div>
</div>

View File

@@ -3,50 +3,47 @@
ViewData.SetActivePageAndTitle(ServerNavPages.Maintenance);
}
<partial name="_StatusMessage" />
<div class="row">
<div class="col-md-8">
<form method="post">
<form method="post">
<div class="row mb-5">
<div class="col-lg-9 col-xl-8">
<div class="form-group">
<h5>Change domain name</h5>
<span>You can change the domain name of your server by following <a href="https://docs.btcpayserver.org/ChangeDomain" target="_blank">this guide</a></span>
</div>
<div class="form-group">
<div class="input-group">
<input asp-for="DNSDomain" class="form-control" />
<span class="input-group-btn">
<button name="command" type="submit" class="btn btn-primary" value="changedomain" title="Change domain" disabled="@(Model.CanUseSSH ? null : "disabled")">
<span class="fa fa-check"></span> Confirm
</button>
</span>
<div class="form-inline">
<input asp-for="DNSDomain" class="form-control flex-fill" disabled="@(Model.CanUseSSH ? null : "disabled")" />
<button name="command" type="submit" class="btn btn-primary mt-2 mt-sm-0 ml-sm-2" value="changedomain" title="Change domain" disabled="@(Model.CanUseSSH ? null : "disabled")">
<span class="fa fa-check"></span> Confirm
</button>
</div>
<span asp-validation-for="DNSDomain" class="text-danger"></span>
</div>
<div class="form-group">
<h5>Update</h5>
<span>Click here to update your server</span>
</div>
</div>
</div>
<div class="row mb-5">
<div class="col-lg-9 col-xl-8">
<h5>Update</h5>
<p class="text-secondary mb-2">Update to the latest version of BTCPay server.</p>
<div class="form-group">
<div class="input-group">
<button name="command" type="submit" class="btn btn-primary" value="update" disabled="@(Model.CanUseSSH ? null : "disabled")">Update</button>
</div>
</div>
<div class="form-group">
<h5>Clean</h5>
<span>Click here to delete unused docker images present on your system</span>
</div>
<h5 class="mt-5">Clean</h5>
<p class="text-secondary mb-2">Delete unused docker images present on your system.</p>
<div class="form-group">
<div class="input-group">
<button name="command" type="submit" class="btn btn-primary" value="clean" disabled="@(Model.CanUseSSH ? null : "disabled")">Clean</button>
<button name="command" type="submit" class="btn btn-secondary" value="clean" disabled="@(Model.CanUseSSH ? null : "disabled")">Clean</button>
</div>
</div>
</form>
</div>
</div>
</div>
</form>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")

View File

@@ -6,178 +6,104 @@
<partial name="_StatusMessage" />
<div class="row">
<div class="col-md-6">
<div class="col-lg-9 col-xl-8">
<div asp-validation-summary="All" class="text-danger"></div>
</div>
</div>
<div class="row">
<div class="row mb-5">
<div class="col-lg-9 col-xl-8">
<h4>Crypto services exposed by your server</h4>
<div class="col-md-8">
<h4>Crypto services</h4>
<div class="form-group">
<span>You can get access here to services exposed by your server</span>
</div>
<div class="form-group">
<table class="table table-sm table-responsive-md">
<thead>
<table class="table table-sm mt-2">
<thead>
<tr>
<th>Crypto</th>
<th>Access Type</th>
<th style="text-align: right">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.ExternalServices.Where(service => !string.IsNullOrEmpty(service.CryptoCode)))
{
<tr>
<td>@s.CryptoCode</td>
<td>
<span>@s.DisplayName</span>
@if (s.ConnectionString.IsOnion() == true ||
(s.ConnectionString.IsOnion() == false && this.Context.Request.IsOnion()))
{
<span><img style="display:inline; margin-top:-8px;" src="~/img/icons/Onion_Color.svg" height="20" asp-append-version="true" /></span>
}
</td>
<td style="text-align: right">
<a asp-action="Service" asp-route-serviceName="@s.ServiceName" asp-route-cryptoCode="@s.CryptoCode">See information</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</thead>
<tbody>
@foreach (var s in Model.ExternalServices.Where(service => !string.IsNullOrEmpty(service.CryptoCode)))
{
<tr>
<td>@s.CryptoCode</td>
<td>
<span>@s.DisplayName</span>
@if (s.ConnectionString.IsOnion() == true ||
(s.ConnectionString.IsOnion() == false && this.Context.Request.IsOnion()))
{
<span><img style="display:inline; margin-top:-8px;" src="~/img/icons/Onion_Color.svg" height="20" asp-append-version="true" /></span>
}
</td>
<td style="text-align: right">
<a asp-action="Service" asp-route-serviceName="@s.ServiceName" asp-route-cryptoCode="@s.CryptoCode">See information</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
@if (Model.OtherExternalServices.Count != 0 || Model.ExternalServices.Any(service => string.IsNullOrEmpty(service.CryptoCode)))
{
<div class="row">
<div class="col-md-8">
<h4>Other services</h4>
<div class="form-group">
<span>Other external services</span>
</div>
<div class="form-group">
<table class="table table-sm table-responsive-md">
<thead>
<div class="row mb-5">
<div class="col-lg-9 col-xl-8">
<h4>Other external services</h4>
<table class="table table-sm mt-2">
<thead>
<tr>
<th>Name</th>
<th style="text-align: right">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.ExternalServices.Where(service => string.IsNullOrEmpty(service.CryptoCode)))
{
<tr>
<td>@s.DisplayName</td>
<td style="text-align: right">
<a asp-action="Service" asp-route-serviceName="@s.ServiceName">See information</a>
</td>
</tr>
}
@foreach (var s in Model.OtherExternalServices)
{
<tr>
<td>@s.Name</td>
<td style="text-align: right">
<a href="@s.Link" target="_blank">See information</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</thead>
<tbody>
@foreach (var s in Model.ExternalServices.Where(service => string.IsNullOrEmpty(service.CryptoCode)))
{
<tr>
<td>@s.DisplayName</td>
<td style="text-align: right">
<a asp-action="Service" asp-route-serviceName="@s.ServiceName">See information</a>
</td>
</tr>
}
@foreach (var s in Model.OtherExternalServices)
{
<tr>
<td>@s.Name</td>
<td style="text-align: right">
<a href="@s.Link" target="_blank">See information</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}
@if (Model.TorHttpServices.Count != 0)
{
<div class="row">
<div class="col-md-8">
<h4>HTTP TOR hidden services</h4>
<div class="form-group">
<span>TOR services hosted on this server, only http servers are listed here.</span>
</div>
<div class="form-group">
<table class="table table-sm table-responsive-md">
<thead>
<tr>
<th>Name</th>
<th style="text-align: right">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.TorHttpServices)
{
<tr>
<td>@s.Name</td>
<td style="text-align: right">
<a href="@s.Link" target="_blank">See information</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
<div class="row mb-5">
<div class="col-lg-9 col-xl-8">
<h4>HTTP-based TOR hidden services</h4>
@if (Model.TorOtherServices.Count != 0)
{
<div class="row">
<div class="col-md-8">
<h4>Other TOR hidden services</h4>
<div class="form-group">
<span>TOR services hosted on this server which are not http based.</span>
</div>
<div class="form-group">
<table class="table table-sm table-responsive-md">
<thead>
<table class="table table-sm mt-2">
<thead>
<tr>
<th>Name</th>
<th style="text-align: right">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.TorOtherServices)
{
<tr>
<td>@s.Name</td>
<td style="text-align: right">@s.Link</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
<div class="row">
<div class="col-md-8">
<h4>External storage services</h4>
<div class="form-group">
<span>Integrated Storage providers to store file uploads from btcpay</span>
</div>
<div class="form-group">
<table class="table table-sm table-responsive-md">
<thead>
<tr>
<th>Name</th>
<th style="text-align: right">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.ExternalStorageServices)
@foreach (var s in Model.TorHttpServices)
{
<tr>
<td>@s.Name</td>
<td style="text-align: right">
<a href="@s.Link">Edit</a>
<a href="@s.Link" target="_blank">See information</a>
</td>
</tr>
}
@@ -185,6 +111,61 @@
</table>
</div>
</div>
}
@if (Model.TorOtherServices.Count != 0)
{
<div class="row mb-5">
<div class="col-lg-9 col-xl-8">
<h4>Other TOR hidden services</h4>
<table class="table table-sm mt-2">
<thead>
<tr>
<th>Name</th>
<th>URL</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.TorOtherServices)
{
<tr>
<td>@s.Name</td>
<td style="word-wrap: anywhere;">
<code>@s.Link</code>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}
<div class="row mb-5">
<div class="col-lg-9 col-xl-8">
<h4>External storage services</h4>
<p class="text-secondary mb-0">Integrated storage providers to store file uploads from BTCPay Server.</p>
<table class="table table-sm mt-2">
<thead>
<tr>
<th>Name</th>
<th style="text-align: right">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.ExternalStorageServices)
{
<tr>
<td>@s.Name</td>
<td style="text-align: right">
<a href="@s.Link">Edit</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
@section Scripts {

View File

@@ -1,4 +1,4 @@
<div class="nav flex-column nav-pills">
<div class="nav flex-column nav-pills mb-4">
<a class="nav-link @ViewData.IsActivePage(ServerNavPages.Users)" asp-action="ListUsers">Users</a>
<a class="nav-link @ViewData.IsActivePage(ServerNavPages.Emails)" asp-action="Emails">Email server</a>
<a class="nav-link @ViewData.IsActivePage(ServerNavPages.Policies)" asp-action="Policies">Policies</a>

View File

@@ -59,9 +59,9 @@ $(document).ready(function(){
});
</script>
<div class="row">
<div class="col-md-6">
<form method="post" autocomplete="off">
<form method="post" autocomplete="off">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label asp-for="Settings.Server"></label>
<input asp-for="Settings.Server" class="form-control"/>
@@ -104,19 +104,29 @@ $(document).ready(function(){
<label asp-for="Settings.EnableSSL" class="form-check-label"></label>
</div>
</div>
<button type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
</div>
<hr class="mt-5 mb-4" />
<div class="row">
<div class="col-md-6">
<div class="form-group">
<p class="form-text text-muted">
If you want to test your settings, enter an email address here and click "Send Test Email".
<strong>Your settings won't be saved</strong>, only a test email will be sent.
<br/>
After a successful test, you can click "Save".
</p>
<label asp-for="TestEmail"></label>
<input asp-for="TestEmail" class="form-control"/>
<small class="form-text text-muted">
If you want to test your settings, enter an email address here and click "Send Test Email." Your settings won't be saved, only a test email will be sent. After a successful test, you can click "Save".
</small>
<span asp-validation-for="TestEmail" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
<button type="submit" class="btn btn-primary" name="command" value="Test">Send Test Email</button>
</form>
<button type="submit" class="btn btn-secondary" name="command" value="Test">Send Test Email</button>
</div>
</div>
</div>
</form>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")

View File

@@ -4,7 +4,7 @@
@if (parsedModel != null)
{
<div class="alert alert-@parsedModel.SeverityCSS @(parsedModel.AllowDismiss? "alert-dismissible":"" )" role="alert">
<div class="alert alert-@parsedModel.SeverityCSS @(parsedModel.AllowDismiss? "alert-dismissible":"" ) mb-5" role="alert">
@if (parsedModel.AllowDismiss)
{
<button type="button" class="close" data-dismiss="alert" aria-label="Close">

View File

@@ -1,4 +1,4 @@
<div class="nav flex-column nav-pills">
<div class="nav flex-column nav-pills mb-4">
<a id="@(nameof(StoreNavPages.Index))"class="nav-link @ViewData.IsActivePage(StoreNavPages.Index)" asp-controller="Stores" asp-action="UpdateStore" asp-route-storeId="@this.Context.GetRouteValue("storeId")">General settings</a>
<a id="@(nameof(StoreNavPages.Rates))"class="nav-link @ViewData.IsActivePage(StoreNavPages.Rates)" asp-controller="Stores" asp-action="Rates" asp-route-storeId="@this.Context.GetRouteValue("storeId")">Rates</a>
<a id="@(nameof(StoreNavPages.Checkout))"class="nav-link @ViewData.IsActivePage(StoreNavPages.Checkout)" asp-controller="Stores" asp-action="CheckoutExperience" asp-route-storeId="@this.Context.GetRouteValue("storeId")">Checkout experience</a>

View File

@@ -4,7 +4,7 @@
var wallet = WalletId.Parse( this.Context.GetRouteValue("walletId").ToString());
var network = BtcPayNetworkProvider.GetNetwork<BTCPayNetwork>(wallet.CryptoCode);
}
<div class="nav flex-column nav-pills">
<div class="nav flex-column nav-pills mb-4">
<a class="nav-link @ViewData.IsActivePage(WalletsNavPages.Transactions)" asp-action="WalletTransactions" asp-route-walletId="@this.Context.GetRouteValue("walletId")" id="WalletTransactions">Transactions</a>
@if (!network.ReadonlyWallet)
{

View File

@@ -58,6 +58,9 @@
--btcpay-bg-tile: var(--btcpay-color-white);
--btcpay-bg-cta: var(--btcpay-brand-dark);
--btcpay-border-color-light: var(--btcpay-color-neutral-200);
--btcpay-border-color-medium: var(--btcpay-color-neutral-300);
--btcpay-body-color: var(--btcpay-color-neutral-900);
--btcpay-body-color-link: var(--btcpay-color-primary);
--btcpay-body-color-link-accent: var(--btcpay-color-primary);
@@ -74,6 +77,9 @@
--btcpay-font-family-head: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
--btcpay-font-family-base: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
--btcpay-font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--btcpay-font-weight-normal: 400;
--btcpay-font-weight-semibold: 600;
--btcpay-font-weight-bold: 700;
}
/* Bootstrap modifications */
@@ -102,9 +108,11 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
}
.table-sm thead th {
border-bottom: none;
border-bottom: 2px solid var(--btcpay-border-color-medium);
border-top: none;
font-size: 1.0rem;
color: var(--btcpay-color-secondary);
font-weight: var(--btcpay-font-weight-semibold);
}
.table-sm th,
@@ -112,6 +120,10 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
padding: .5rem;
}
.table-sm tbody tr:first-child td {
border-top: none;
}
.table-sm tbody tr:hover {
background-color: var(--btcpay-color-neutral-100);
}