btcpayserver/BTCPayServer/Views/Server/ListPlugins.cshtml

193 lines
8.9 KiB
Plaintext
Raw Normal View History

@using BTCPayServer.Configuration
@model BTCPayServer.Controllers.ServerController.ListPluginsViewModel
@inject BTCPayServerOptions BTCPayServerOptions
@{
ViewData.SetActivePageAndTitle(ServerNavPages.Plugins);
var installed = Model.Installed.Select(plugin => plugin.Identifier);
var availableAndNotInstalled = Model.Available.Where(plugin => !installed.Contains(plugin.Identifier)).Select(plugin => (plugin, BTCPayServerOptions.RecommendedPlugins.Contains(plugin.Identifier.ToLowerInvariant()))).OrderBy(tuple => tuple.Item1);
}
2020-10-22 10:58:22 +02:00
<partial name="_StatusMessage"/>
@if (Model.Commands.Any())
{
2020-10-22 10:58:22 +02:00
<div class="alert alert-info mb-5">
You need to restart BTCPay Server in order to update your active plugins.
@if (Model.CanShowRestart)
{
2020-10-22 10:58:22 +02:00
<form method="post" asp-action="Maintenance" class="mt-2">
<button type="submit" name="command" value="restart" class="btn btn-info" asp-action="Maintenance">Restart now</button>
</form>
}
</div>
}
@if (Model.Installed.Any())
{
2020-10-22 10:58:22 +02:00
<h3 class="mb-3">Installed Plugins</h3>
<div class="row mb-4">
@foreach (var plugin in Model.Installed)
{
var matchedAvailable = Model.Available.SingleOrDefault(availablePlugin => availablePlugin.Identifier == plugin.Identifier);
2020-10-22 10:58:22 +02:00
var updateAvailable = matchedAvailable != null && plugin.Version < matchedAvailable.Version;
<div class="col col-12 col-lg-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h4 class="card-title">@plugin.Name</h4>
<h5 class="card-subtitle mb-3 text-muted d-flex align-items-center">
@plugin.Version
@if (plugin.SystemPlugin)
{
<div class="badge badge-secondary ml-2">System plugin</div>
}
else if (updateAvailable)
{
<div class="badge badge-secondary ml-2">@matchedAvailable.Version available</div>
}
</h5>
<p class="card-text">@plugin.Description</p>
</div>
@if (!plugin.SystemPlugin)
{
<div class="card-footer border-0 pb-3 d-flex">
@if (Model.Commands.Any(tuple => tuple.plugin.Equals(plugin.Identifier, StringComparison.InvariantCultureIgnoreCase)))
{
<form asp-action="CancelPluginCommands" asp-route-plugin="@plugin.Identifier">
2020-10-22 10:58:22 +02:00
<button type="submit" class="btn btn-outline-secondary">Cancel pending action</button>
</form>
2020-10-22 10:58:22 +02:00
}
else
{
2020-10-22 10:58:22 +02:00
@if (updateAvailable)
{
<form asp-action="InstallPlugin" asp-route-plugin="@plugin.Identifier" class="mr-3">
2020-10-22 10:58:22 +02:00
<button type="submit" class="btn btn-secondary">Update</button>
</form>
}
<form asp-action="UnInstallPlugin" asp-route-plugin="@plugin.Identifier">
<button type="submit" class="btn btn-outline-danger">Uninstall</button>
</form>
}
</div>
2020-10-22 10:58:22 +02:00
}
</div>
</div>
}
</div>
}
@if (availableAndNotInstalled.Any())
{
2020-10-22 10:58:22 +02:00
<h3 class="mb-3">Available Plugins</h3>
<div class="row mb-4">
@foreach (var pluginT in availableAndNotInstalled)
{
var plugin = pluginT.Item1;
2020-10-22 10:58:22 +02:00
<div class="col col-12 col-lg-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h4 class="card-title">@plugin.Name</h4>
<h5 class="card-subtitle mb-3 text-muted d-flex justify-content-between">
<span>@plugin.Version</span>
@if (pluginT.Item2)
{
<span data-toggle="tooltip" title="This plugin has been recommended to be installed by your deployment method.">Recommended <span class="fa fa-question-circle-o"></span></span>
}
</h5>
2020-10-22 10:58:22 +02:00
<p class="card-text">@plugin.Description</p>
</div>
<div class="card-footer border-0 pb-3">
@if (Model.Commands.Any(tuple => tuple.plugin.Equals(plugin.Identifier, StringComparison.InvariantCultureIgnoreCase)))
{
<form asp-action="CancelPluginCommands" asp-route-plugin="@plugin.Identifier">
2020-10-22 10:58:22 +02:00
<button type="submit" class="btn btn-outline-secondary">Cancel pending install</button>
</form>
2020-10-22 10:58:22 +02:00
}
else
{
<form asp-action="InstallPlugin" asp-route-plugin="@plugin.Identifier">
2020-10-22 10:58:22 +02:00
<button type="submit" class="btn btn-primary">Install</button>
</form>
}
</div>
</div>
</div>
}
</div>
}
2020-10-22 10:58:22 +02:00
<div class="mb-4">
<button class="btn btn-link text-secondary mb-2" type="button" data-toggle="collapse" data-target="#manual-upload">
Upload plugin
</button>
<div class="row collapse" id="manual-upload">
<div class="col col-12 col-lg-6 mb-4">
<div class="card">
<div class="card-body">
<h4 class="card-title">Add plugin manually</h4>
<div class="alert alert-warning my-3">
<h6 class="mr-1">This is an extremely dangerous operation!</h6>
Only upload plugins from trusted sources.
</div>
2020-10-22 10:58:22 +02:00
<form method="post" enctype="multipart/form-data" asp-action="UploadPlugin">
<div class="form-group">
<div class="custom-file">
<input type="file" class="custom-file-input form-control-file" required name="files" accept=".btcpay" id="files">
<label class="custom-file-label" for="files">Choose file</label>
</div>
</div>
<button class="btn btn-primary" type="submit">Upload</button>
</form>
</div>
2020-10-22 10:58:22 +02:00
</div>
</div>
</div>
</div>
2020-10-22 10:58:22 +02:00
@if (Model.Commands.Any())
{
2020-10-22 10:58:22 +02:00
<div class="mb-4">
<button class="btn btn-link text-secondary mb-2" type="button" data-toggle="collapse" data-target="#pending-actions">
Pending actions
</button>
<div class="row collapse" id="pending-actions">
<div class="col col-12 col-lg-6 mb-4">
<div class="card">
<div class="card-body">
<h4 class="card-title">Pending actions</h4>
<ul class="list-group list-group-flush">
@foreach (var extComm in Model.Commands.GroupBy(tuple => tuple.plugin))
{
<li class="list-group-item px-0">
<div class="d-flex flex-wrap align-items-center justify-content-between">
<span class="my-2 mr-3">@extComm.Key</span>
<form asp-action="CancelPluginCommands" asp-route-plugin="@extComm.Key">
<button type="submit" class="btn btn-outline-secondary">Cancel pending @extComm.Last().command</button>
</form>
</div>
</li>
}
</ul>
</div>
</div>
</div>
</div>
</div>
}
@section Scripts {
<script>
2020-10-22 10:58:22 +02:00
$(document).ready(function () {
$(".custom-file-input").on("change", function () {
var label = $(this).next("label");
var el = $(this).get(0);
if (el.files.length > 0) {
var fileName = el.files[0].name;
label.addClass("selected").html(fileName);
} else {
label.removeClass("selected").html("Choose file");
}
});
2020-10-22 10:58:22 +02:00
});
</script>
}