Merge pull request #1629 from sbwalker/dev

fix Type label in Add Folder UI, make Profile description required, fix misc Bootstrap 5 cosmetic issues, fix #1618 Alias case sensitivity in router, fix File add and update methods so they return Url, fix UrlCombine helper method to use proper slash, enhance package installation to support commercial options
This commit is contained in:
Shaun Walker 2021-08-26 18:14:59 -04:00 committed by GitHub
commit e3af463e65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 168 additions and 89 deletions

View File

@ -32,7 +32,7 @@
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="type" HelpText="Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users" ResourceKey="Name">Type: </Label>
<Label Class="col-sm-3" For="type" HelpText="Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users" ResourceKey="Type">Type: </Label>
<div class="col-sm-9">
@if (PageState.QueryString.ContainsKey("id"))
{

View File

@ -79,12 +79,23 @@ else
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"]&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Source"]: <strong>@context.PackageUrl</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Price"]: <strong>@((context.Price == 0) ? "FREE" : context.Price.ToString("$#,##0.00") )</strong>
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
</td>
<td style="vertical-align: middle;">
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetLanguage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
<td style="width: 1px; vertical-align: middle;">
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PackageUrl))
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
</td>
<td style="width: 1px; vertical-align: middle;">
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PaymentUrl))
{
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.ToString("$#,##0.00")</a>
}
else
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
</td>
</Row>
</Pager>
@ -105,7 +116,7 @@ else
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Upload one or more translations. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Language: </Label>
<div class="col-sm-9">
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" UploadMultiple="true" />
<FileManager Filter="nupkg" ShowFiles="true" Folder="Packages" UploadMultiple="true" />
</div>
</div>
</div>
@ -278,7 +289,7 @@ else
StateHasChanged();
}
private async Task GetLanguage(string packageid, string version)
private async Task GetPackage(string packageid, string version)
{
try
{

View File

@ -36,12 +36,23 @@
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"]&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Source"]: <strong>@context.PackageUrl</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Price"]: <strong>@((context.Price == 0) ? "FREE" : context.Price.ToString("$#,##0.00") )</strong>
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
</td>
<td style="vertical-align: middle;">
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
<td style="width: 1px; vertical-align: middle;">
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PackageUrl))
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
</td>
<td style="width: 1px; vertical-align: middle;">
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PaymentUrl))
{
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.ToString("$#,##0.00")</a>
}
else
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
</td>
</Row>
</Pager>

View File

@ -22,7 +22,7 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="description" HelpText="The help text displayed to the user for this profile item" ResourceKey="Description">Description: </Label>
<div class="col-sm-9">
<textarea id="description" class="form-control" @bind="@_description" rows="5" maxlength="256"></textarea>
<textarea id="description" class="form-control" @bind="@_description" rows="5" maxlength="256" required ></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">

View File

@ -36,12 +36,23 @@
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"]&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Source"]: <strong>@context.PackageUrl</strong>&nbsp;&nbsp;|&nbsp;&nbsp;
@SharedLocalizer["Search.Price"]: <strong>@((context.Price == 0) ? "FREE" : context.Price.ToString("$#,##0.00") )</strong>
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
</td>
<td style="vertical-align: middle;">
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
<td style="width: 1px; vertical-align: middle;">
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PackageUrl))
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
</td>
<td style="width: 1px; vertical-align: middle;">
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PaymentUrl))
{
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.ToString("$#,##0.00")</a>
}
else
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
</td>
</Row>
</Pager>

View File

@ -58,7 +58,6 @@
</span>
</div>
}
<ModuleMessage Message="@_message" Type="@_messagetype"></ModuleMessage>
</div>
@if (_image != string.Empty)
{
@ -67,6 +66,14 @@
</div>
}
</div>
@if (!string.IsNullOrEmpty(_message))
{
<div class="row">
<div class="col mt-2">
<ModuleMessage Message="@_message" Type="@_messagetype" />
</div>
</div>
}
</div>
}

View File

@ -4,7 +4,7 @@
@if (!string.IsNullOrEmpty(_message))
{
<div class="@_classname alert-dismissible fade show" role="alert">
<div class="@_classname alert-dismissible fade show mb-3" role="alert">
@((MarkupString)_message)
@if (Type == MessageType.Error && PageState != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{
@ -12,7 +12,6 @@
}
<button type="button" class="btn-close" aria-label="Close" @onclick="DismissModal"></button>
</div>
<br />
}
@code {

View File

@ -7,73 +7,96 @@
@if (_permissions != null)
{
<br />
<table class="table table-borderless" style="width: 50%; min-width: 250px;">
<tbody>
<tr>
<th scope="col">@Localizer["Role"]</th>
@foreach (PermissionString permission in _permissions)
{
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
}
</tr>
@foreach (Role role in _roles)
{
<tr>
<td>@role.Name</td>
@foreach (PermissionString permission in _permissions)
{
var p = permission;
<td style="text-align: center;">
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, role.Name) Disabled=@GetPermissionDisabled(role.Name) OnChange="@(e => PermissionChanged(e, p.PermissionName, role.Name))" />
</td>
}
</tr>
}
</tbody>
</table>
@if (_users.Count != 0)
{
<table class="table table-borderless" style="width: 50%; min-width: 250px;">
<thead>
<tr>
<th scope="col">@Localizer["User"]</th>
@foreach (PermissionString permission in _permissions)
{
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
}
</tr>
</thead>
<tbody>
@foreach (User user in _users)
{
string userid = "[" + user.UserId.ToString() + "]";
<div class="container">
<div class="row">
<div class="col">
<table class="table table-borderless">
<tbody>
<tr>
<td>@user.DisplayName</td>
<th scope="col">@Localizer["Role"]</th>
@foreach (PermissionString permission in _permissions)
{
var p = permission;
<td style="text-align: center; width: 1px;">
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" />
</td>
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
}
</tr>
}
</tbody>
</table>
}
<table class="table table-borderless" style="width: 50%; min-width: 250px;">
<tbody>
<tr>
<td class="input-group">
<input type="text" name="Username" class="form-control" placeholder="@Localizer["Username.Enter"]" @bind="@_username" />
<button type="button" class="btn btn-primary" @onclick="AddUser">@SharedLocalizer["Add"]</button>
</td>
</tr>
</tbody>
</table>
<br />
<ModuleMessage Type="MessageType.Error" Message="@_message" />
@foreach (Role role in _roles)
{
<tr>
<td>@role.Name</td>
@foreach (PermissionString permission in _permissions)
{
var p = permission;
<td style="text-align: center;">
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, role.Name) Disabled=@GetPermissionDisabled(role.Name) OnChange="@(e => PermissionChanged(e, p.PermissionName, role.Name))" />
</td>
}
</tr>
}
</tbody>
</table>
<br />
</div>
</div>
<div class="row">
<div class="col">
@if (_users.Count != 0)
{
<div class="row">
<div class="col">
</div>
</div>
<table class="table table-borderless">
<thead>
<tr>
<th scope="col">@Localizer["User"]</th>
@foreach (PermissionString permission in _permissions)
{
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
}
</tr>
</thead>
<tbody>
@foreach (User user in _users)
{
string userid = "[" + user.UserId.ToString() + "]";
<tr>
<td>@user.DisplayName</td>
@foreach (PermissionString permission in _permissions)
{
var p = permission;
<td style="text-align: center; width: 1px;">
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" />
</td>
}
</tr>
}
</tbody>
</table>
<br />
}
</div>
</div>
<div class="row">
<div class="col">
<table class="table table-borderless">
<tbody>
<tr>
<td class="input-group">
<input type="text" name="Username" class="form-control" placeholder="@Localizer["Username.Enter"]" @bind="@_username" />
<button type="button" class="btn btn-primary" @onclick="AddUser">@SharedLocalizer["Add"]</button>
</td>
</tr>
</tbody>
</table>
<br />
</div>
</div>
<div class="row">
<div class="col">
<ModuleMessage Type="MessageType.Error" Message="@_message" />
</div>
</div>
</div>
}
@code {

View File

@ -165,4 +165,10 @@
<data name="DeleteFolder.Message" xml:space="preserve">
<value>Are You Sure You Wish To Delete This Folder?</value>
</data>
<data name="Type.HelpText" xml:space="preserve">
<value>Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users</value>
</data>
<data name="Type.Text" xml:space="preserve">
<value>Type:</value>
</data>
</root>

View File

@ -27,6 +27,8 @@
protected override void OnParametersSet()
{
_message = "";
DynamicComponent = builder =>
{
Type moduleType = null;

View File

@ -89,7 +89,7 @@
else
{
// reload the client application if the user navigated to a site with a different alias or there is a forced reload
if ((!path.StartsWith(SiteState.Alias.Path) && SiteState.Alias.Path != "") || querystring.ContainsKey("reload"))
if ((!path.ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path)) || querystring.ContainsKey("reload"))
{
NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true);
return;

View File

@ -8,7 +8,6 @@ using Oqtane.Enums;
using Oqtane.Infrastructure;
using Oqtane.Repository;
using Microsoft.AspNetCore.Http;
using Oqtane.Themes.Controls;
using System.Linq;
namespace Oqtane.Controllers

View File

@ -34,7 +34,6 @@ namespace Oqtane.Controllers
// GET: api/<controller>?type=x&search=y&price=z&package=a
[HttpGet]
[Authorize(Roles = RoleNames.Host)]
public async Task<IEnumerable<Package>> Get(string type, string search, string price, string package)
{
// get packages

View File

@ -26,7 +26,7 @@ namespace Oqtane.Controllers
// GET: api/<controller>?siteid=x&global=true/false
[HttpGet]
[Authorize(Roles = RoleNames.Admin)]
[Authorize(Roles = RoleNames.Registered)]
public IEnumerable<Role> Get(string siteid, string global)
{
int SiteId;
@ -48,7 +48,7 @@ namespace Oqtane.Controllers
// GET api/<controller>/5
[HttpGet("{id}")]
[Authorize(Roles = RoleNames.Admin)]
[Authorize(Roles = RoleNames.Registered)]
public Role Get(int id)
{
var role = _roles.GetRole(id);

View File

@ -42,6 +42,7 @@ namespace Oqtane.Repository
{
_db.File.Add(file);
_db.SaveChanges();
file.Url = GetFileUrl(file, _tenants.GetAlias());
return file;
}
@ -49,6 +50,7 @@ namespace Oqtane.Repository
{
_db.Entry(file).State = EntityState.Modified;
_db.SaveChanges();
file.Url = GetFileUrl(file, _tenants.GetAlias());
return file;
}

View File

@ -71,5 +71,10 @@ namespace Oqtane.Models
/// The price of the package
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// The Url for purchasing the package ( if commercial )
/// </summary>
public string PaymentUrl { get; set; }
}
}

View File

@ -344,6 +344,10 @@ namespace Oqtane.Shared
public static string UrlCombine(params string[] segments)
{
for (int i = 1; i < segments.Length; i++)
{
segments[i] = segments[i].Replace("\\", "/");
}
return string.Join("/", segments);
}