oqtane.framework/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor
2023-08-04 16:07:37 -04:00

315 lines
14 KiB
Plaintext

@namespace Oqtane.Modules.Admin.ModuleDefinitions
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IFileService FileService
@inject IModuleDefinitionService ModuleDefinitionService
@inject IPackageService PackageService
@inject IStringLocalizer<Add> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<TabStrip>
<TabPanel Name="Download" ResourceKey="Download">
<div class="row justify-content-center mb-3">
<div class="text-center">
<div class="form-check form-check-inline">
<input id="free" class="form-check-input" type="radio" checked="@(_price == "free")" name="Price" @onchange="@(() => PriceChanged("free"))" />
<label class="form-check-label" for="free">@SharedLocalizer["Free"]</label>
</div>
<div class="form-check form-check-inline">
<input id="paid" class="form-check-input" type="radio" checked="@(_price == "paid")" name="Price" @onchange="@(() => PriceChanged("paid"))" />
<label class="form-check-label" for="paid">@SharedLocalizer["Paid"]</label>
</div>
</div>
</div>
<div class="row justify-content-center mb-3">
<div class="col">
<div class="input-group">
<span class="input-group-text">Product</span>
<input id="search" class="form-control" placeholder="@SharedLocalizer["Search.Hint"]" @bind="@_search" />
<button type="button" class="btn btn-primary" @onclick="Search">@SharedLocalizer["Search"]</button>
<button type="button" class="btn btn-secondary" @onclick="Reset">@SharedLocalizer["Reset"]</button>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col">
@if (_initialized)
{
<br />
<div class="row mb-3">
<div class="col-sm-4">
<h3>@((_packages != null) ? _packages.Count : 0) @SharedLocalizer["Search.Results"]</h3>
</div>
<div class="col-sm-4">
&nbsp;
</div>
<div class="col-sm-4">
<select class="form-select" value="@_sort" @onchange="(e => SortChanged(e))">
<option value="popularity">@SharedLocalizer["Search.Popularity"]</option>
<option value="alphabetical">@SharedLocalizer["Search.Alphabetical"]</option>
<option value="downloads">@SharedLocalizer["Search.Downloads"]</option>
<option value="recent">@SharedLocalizer["Search.RecentlyReleased"]</option>
@if (_price == "paid")
{
<option value="price">@SharedLocalizer["Search.Price"]</option>
}
</select>
</div>
</div>
<Pager Format="Grid" Items="@_packages" DisplayPages="1" PageSize="9" Toolbar="Both" Class="container-fluid px-0" RowClass="row g-0" ColumnClass="col-lg-4 col-md-6">
<Row>
<div class="m-2 p-2 d-flex justify-content-center">
<div class="container-fluid px-0">
<div class="row g-0">
<div class="col-6">
@if (context.LogoFileId != null)
{
<img src="@GetLogo(context.LogoFileId.Value)" class="img-fluid" alt="@context.Name" />
}
else
{
<img src="/package.png" class="img-fluid" alt="@context.Name" />
}
</div>
<div class="col-6 text-end">
<small>@SharedLocalizer["Search.Version"]:</small> <strong>@context.Version</strong>
<br /><small>@SharedLocalizer["Search.Downloads"]:</small> <strong>@(String.Format("{0:n0}", context.Downloads))</strong>
<br /><small>@SharedLocalizer["Search.Released"]:</small> <strong>@context.ReleaseDate.ToString("MM/dd/yyyy")</strong>
@if (!string.IsNullOrEmpty(context.PackageUrl))
{
<br /><small>@SharedLocalizer["Search.Source"]:</small> <strong>@(new Uri(context.PackageUrl).Host)</strong>
}
</div>
</div>
<div class="row g-0">
<div class="col">
<h3 style="display: inline;"><a href="@context.ProductUrl" target="_blank">@context.Name</a></h3><br />
<small>@SharedLocalizer["Search.By"]:</small> <strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
{
<small>@SharedLocalizer["Search.Price"]:</small> <strong>@context.Price.Value.ToString("$#,##0.00")</strong>
@((MarkupString)(context.TrialPeriod > 0 ? " <strong>(" + context.TrialPeriod + " Day Trial)</strong>" : ""))
}
<br />
@if (!string.IsNullOrEmpty(context.PackageUrl))
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
{
<a class="btn btn-success ms-2" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@SharedLocalizer["Buy"]</a>
}
<br />
</div>
</div>
</div>
</div>
</Row>
</Pager>
}
</div>
</div>
<br />
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
</TabPanel>
<TabPanel Name="Upload" ResourceKey="Upload">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
<div class="col-sm-9">
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" OnUpload="OnUpload" />
</div>
</div>
</div>
</TabPanel>
</TabStrip>
@if (_productname != "")
{
<div class="app-actiondialog">
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">@SharedLocalizer["Review License Terms"]</h5>
<button type="button" class="btn-close" aria-label="Close" @onclick="HideModal"></button>
</div>
<div class="modal-body">
<p style="height: 200px; overflow-y: scroll;">
<h3>@_productname</h3>
@if (!string.IsNullOrEmpty(_packagelicense))
{
@((MarkupString)_packagelicense)
}
else
{
@SharedLocalizer["License Not Specified"]
}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success" @onclick="DownloadPackage">@SharedLocalizer["Accept"]</button>
<button type="button" class="btn btn-secondary" @onclick="HideModal">@SharedLocalizer["Cancel"]</button>
</div>
</div>
</div>
</div>
</div>
}
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
@code {
private bool _initialized = false;
private List<Package> _packages;
private string _price = "free";
private string _sort = "popularity";
private string _search = "";
private string _productname = "";
private string _packageid = "";
private string _packagelicense = "";
private string _packageversion = "";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnInitializedAsync()
{
try
{
await LoadModuleDefinitions();
_initialized = true;
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Package.Load"], MessageType.Error);
}
}
private async Task LoadModuleDefinitions()
{
ShowProgressIndicator();
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "", _sort);
if (_packages != null)
{
foreach (Package package in _packages.ToArray())
{
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
{
_packages.Remove(package);
}
}
}
HideProgressIndicator();
}
private string GetLogo(int fileid)
{
var url = ImageUrl(fileid, 100, 100);
url = (!string.IsNullOrEmpty(PageState.Alias.Path)) ? url.Substring(PageState.Alias.Path.Length + 1) : url;
return Constants.PackageRegistryUrl + url;
}
private async void PriceChanged(string price)
{
_price = price;
await LoadModuleDefinitions();
StateHasChanged();
}
private async Task Search()
{
try
{
await LoadModuleDefinitions();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On Search");
}
}
private async Task Reset()
{
try
{
_search = "";
await LoadModuleDefinitions();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On Reset");
}
}
private async void SortChanged(ChangeEventArgs e)
{
_sort = (string)e.Value;
await LoadModuleDefinitions();
}
private void HideModal()
{
_productname = "";
_packagelicense = "";
StateHasChanged();
}
private async Task GetPackage(string packageid, string version)
{
try
{
var package = await PackageService.GetPackageAsync(packageid, version);
if (package != null)
{
_productname = package.Name;
_packageid = package.PackageId;
if (!string.IsNullOrEmpty(package.License))
{
_packagelicense = package.License.Replace("\n", "<br />");
}
_packageversion = package.Version;
StateHasChanged();
}
else
{
await logger.LogError("Error Getting Package {PackageId} {Version}", packageid, version);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
private async Task DownloadPackage()
{
try
{
await PackageService.DownloadPackageAsync(_packageid, _packageversion, Constants.PackagesFolder);
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _packageversion);
AddModuleMessage(string.Format(Localizer["Success.Module.Download"], NavigateUrl("admin/system")), MessageType.Success);
_productname = "";
_packagelicense = "";
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _packageversion);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
private void OnUpload()
{
AddModuleMessage(string.Format(Localizer["Success.Module.Download"], NavigateUrl("admin/system")), MessageType.Success);
}
}