Merge branch 'oqtane-dev' into dev
This commit is contained in:
commit
b496dc488c
|
@ -150,7 +150,8 @@
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
await interop.IncludeLink("app-stylesheet", "stylesheet", "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css", "text/css", "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", "anonymous", "");
|
await interop.IncludeLink("", "stylesheet", "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css", "text/css", "sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC", "anonymous", "");
|
||||||
|
await interop.IncludeScript("", "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js", "sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM", "anonymous", "", "head", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,12 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="description" HelpText="A description of the file. This can be used as a caption for image files." ResourceKey="Description">Description: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="description" class="form-control" @bind="@_description" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="size" HelpText="The size of the file (in bytes)" ResourceKey="Size">Size: </Label>
|
<Label Class="col-sm-3" For="size" HelpText="The size of the file (in bytes)" ResourceKey="Size">Size: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
|
@ -49,6 +55,7 @@
|
||||||
private string _name;
|
private string _name;
|
||||||
private List<Folder> _folders;
|
private List<Folder> _folders;
|
||||||
private int _folderId = -1;
|
private int _folderId = -1;
|
||||||
|
private string _description = string.Empty;
|
||||||
private int _size;
|
private int _size;
|
||||||
private string _createdBy;
|
private string _createdBy;
|
||||||
private DateTime _createdOn;
|
private DateTime _createdOn;
|
||||||
|
@ -70,6 +77,7 @@
|
||||||
{
|
{
|
||||||
_name = file.Name;
|
_name = file.Name;
|
||||||
_folderId = file.FolderId;
|
_folderId = file.FolderId;
|
||||||
|
_description = file.Description;
|
||||||
_size = file.Size;
|
_size = file.Size;
|
||||||
_createdBy = file.CreatedBy;
|
_createdBy = file.CreatedBy;
|
||||||
_createdOn = file.CreatedOn;
|
_createdOn = file.CreatedOn;
|
||||||
|
@ -97,6 +105,7 @@
|
||||||
File file = await FileService.GetFileAsync(_fileId);
|
File file = await FileService.GetFileAsync(_fileId);
|
||||||
file.Name = _name;
|
file.Name = _name;
|
||||||
file.FolderId = _folderId;
|
file.FolderId = _folderId;
|
||||||
|
file.Description = _description;
|
||||||
file = await FileService.UpdateFileAsync(file);
|
file = await FileService.UpdateFileAsync(file);
|
||||||
await logger.LogInformation("File Saved {File}", file);
|
await logger.LogInformation("File Saved {File}", file);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="name" HelpText="Enter the folder name" ResourceKey="Name">Name: </Label>
|
<Label Class="col-sm-3" For="name" HelpText="Enter the folder name" ResourceKey="Name">Name: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="name" class="form-control" @bind="@_name" maxlength="50" required />
|
<input id="name" class="form-control" @bind="@_name" maxlength="256" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
@ -47,6 +47,18 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="imagesizes" HelpText="Enter a list of image sizes which can be generated dynamically from uploaded images (ie. 200x200,x200,200x)" ResourceKey="ImageSizes">Image Sizes: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="imagesizes" class="form-control" @bind="@_imagesizes" maxlength="512" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="capacity" HelpText="Enter the maximum folder capacity (in megabytes). Specify zero if the capacity is unlimited." ResourceKey="Capacity">Capacity: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="capacity" class="form-control" @bind="@_capacity" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<Label Class="col-sm-3" For="permissions" HelpText="Select the permissions you want for the folder" ResourceKey="Permissions">Permissions: </Label>
|
<Label Class="col-sm-3" For="permissions" HelpText="Select the permissions you want for the folder" ResourceKey="Permissions">Permissions: </Label>
|
||||||
|
@ -84,6 +96,8 @@
|
||||||
private int _parentId = -1;
|
private int _parentId = -1;
|
||||||
private string _name;
|
private string _name;
|
||||||
private string _type = FolderTypes.Private;
|
private string _type = FolderTypes.Private;
|
||||||
|
private string _imagesizes = string.Empty;
|
||||||
|
private string _capacity = "0";
|
||||||
private bool _isSystem;
|
private bool _isSystem;
|
||||||
private string _permissions = string.Empty;
|
private string _permissions = string.Empty;
|
||||||
private string _createdBy;
|
private string _createdBy;
|
||||||
|
@ -114,6 +128,8 @@
|
||||||
_parentId = folder.ParentId ?? -1;
|
_parentId = folder.ParentId ?? -1;
|
||||||
_name = folder.Name;
|
_name = folder.Name;
|
||||||
_type = folder.Type;
|
_type = folder.Type;
|
||||||
|
_imagesizes = folder.ImageSizes;
|
||||||
|
_capacity = folder.Capacity.ToString();
|
||||||
_isSystem = folder.IsSystem;
|
_isSystem = folder.IsSystem;
|
||||||
_permissions = folder.Permissions;
|
_permissions = folder.Permissions;
|
||||||
_createdBy = folder.CreatedBy;
|
_createdBy = folder.CreatedBy;
|
||||||
|
@ -125,7 +141,6 @@
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_parentId = _folders[0].FolderId;
|
_parentId = _folders[0].FolderId;
|
||||||
_permissions = string.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -178,6 +193,8 @@
|
||||||
|
|
||||||
folder.Name = _name;
|
folder.Name = _name;
|
||||||
folder.Type = _type;
|
folder.Type = _type;
|
||||||
|
folder.ImageSizes = _imagesizes;
|
||||||
|
folder.Capacity = int.Parse(_capacity);
|
||||||
folder.IsSystem = _isSystem;
|
folder.IsSystem = _isSystem;
|
||||||
folder.Permissions = _permissionGrid.GetPermissions();
|
folder.Permissions = _permissionGrid.GetPermissions();
|
||||||
|
|
||||||
|
|
|
@ -80,17 +80,18 @@ else
|
||||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||||
|
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PackageUrl))
|
@if (context.Price != null && !string.IsNullOrEmpty(context.PackageUrl))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PaymentUrl))
|
@if (context.Price != null && !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>
|
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.Value.ToString("$#,##0.00")</a>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,17 +37,18 @@
|
||||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||||
|
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PackageUrl))
|
@if (context.Price != null && !string.IsNullOrEmpty(context.PackageUrl))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PaymentUrl))
|
@if (context.Price != null && !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>
|
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.Value.ToString("$#,##0.00")</a>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,7 @@ else
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>@SharedLocalizer["Name"]</th>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
<th>@SharedLocalizer["Version"]</th>
|
<th>@SharedLocalizer["Version"]</th>
|
||||||
|
<th>@SharedLocalizer["Expires"]</th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -34,6 +35,9 @@ else
|
||||||
</td>
|
</td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Version</td>
|
<td>@context.Version</td>
|
||||||
|
<td>
|
||||||
|
@((MarkupString)PurchaseLink(context.PackageName))
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if (UpgradeAvailable(context.PackageName, context.Version))
|
@if (UpgradeAvailable(context.PackageName, context.Version))
|
||||||
{
|
{
|
||||||
|
@ -67,6 +71,27 @@ else
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string PurchaseLink(string packagename)
|
||||||
|
{
|
||||||
|
string link = "";
|
||||||
|
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||||
|
{
|
||||||
|
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||||
|
if (package != null)
|
||||||
|
{
|
||||||
|
if (package.ExpiryDate != null && package.ExpiryDate.Value.Date != DateTime.MaxValue.Date)
|
||||||
|
{
|
||||||
|
link += "<span>" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + "</span>";
|
||||||
|
if (!string.IsNullOrEmpty(package.PaymentUrl))
|
||||||
|
{
|
||||||
|
link += " <a class=\"btn btn-primary\" style=\"text-decoration: none !important\" href=\"" + package.PaymentUrl + "\" target=\"_new\">" + SharedLocalizer["Extend"] + "</a>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string packagename, string version)
|
private bool UpgradeAvailable(string packagename, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
var upgradeavailable = false;
|
||||||
|
|
|
@ -322,6 +322,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(PagePathIsDeleted(page.Path, page.SiteId, _pageList))
|
||||||
|
{
|
||||||
|
AddModuleMessage(string.Format(Localizer["Message.Page.Deleted"], _path), MessageType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
|
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
|
||||||
{
|
{
|
||||||
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
|
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
|
||||||
|
@ -412,4 +418,9 @@
|
||||||
{
|
{
|
||||||
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath);
|
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool PagePathIsDeleted(string pagePath, int siteId, List<Page> existingPages)
|
||||||
|
{
|
||||||
|
return existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath && page.IsDeleted == true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
<Label Class="col-sm-3" For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="isautoassigned" class="form-select" @bind="@_isautoassigned">
|
<select id="isautoassigned" class="form-select" @bind="@_isautoassigned" required>
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Message.InfoRequired"], MessageType.Warning);
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
<Label Class="col-sm-3" For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="isautoassigned" class="form-select" @bind="@_isautoassigned">
|
<select id="isautoassigned" class="form-select" @bind="@_isautoassigned" required>
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -101,7 +101,7 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Message.InfoRequired"], MessageType.Warning);
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
<div class="container">
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="role" HelpText="The role you are assigning users to" ResourceKey="Role">Role: </Label>
|
<Label Class="col-sm-3" For="role" HelpText="The role you are assigning users to" ResourceKey="Role">Role: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
|
@ -22,7 +23,7 @@ else
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="user" HelpText="Select a user" ResourceKey="User">User: </Label>
|
<Label Class="col-sm-3" For="user" HelpText="Select a user" ResourceKey="User">User: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="user" class="form-select" @bind="@userid">
|
<select id="user" class="form-select" @bind="@userid" required>
|
||||||
<option value="-1"><@Localizer["User.Select"]></option>
|
<option value="-1"><@Localizer["User.Select"]></option>
|
||||||
@foreach (UserRole userrole in users)
|
@foreach (UserRole userrole in users)
|
||||||
{
|
{
|
||||||
|
@ -34,13 +35,13 @@ else
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this role assignment is active" ResourceKey="EffectiveDate">Effective Date: </Label>
|
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this role assignment is active" ResourceKey="EffectiveDate">Effective Date: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input type="date" id="effectiveDate" class="form-control" @bind="@effectivedate" />
|
<input type="date" id="effectiveDate" class="form-control" @bind="@effectivedate" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this role assignment expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
|
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this role assignment expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input type="date" id="expiryDate" class="form-control" @bind="@expirydate" />
|
<input type="date" id="expiryDate" class="form-control" @bind="@expirydate" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
|
@ -61,16 +62,20 @@ else
|
||||||
<td>@context.EffectiveDate</td>
|
<td>@context.EffectiveDate</td>
|
||||||
<td>@context.ExpiryDate</td>
|
<td>@context.ExpiryDate</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@context.Role.IsAutoAssigned" ResourceKey="DeleteUserRole" />
|
<ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || PageState.User.Username == UserNames.Host)" ResourceKey="DeleteUserRole" />
|
||||||
</td>
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private ElementReference form;
|
||||||
|
private bool validated = false;
|
||||||
|
|
||||||
private int roleid;
|
private int roleid;
|
||||||
private string name = string.Empty;
|
private string name = string.Empty;
|
||||||
private List<UserRole> users;
|
private List<UserRole> users;
|
||||||
|
@ -117,6 +122,10 @@ else
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveUserRole()
|
private async Task SaveUserRole()
|
||||||
|
{
|
||||||
|
validated = true;
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
if (await interop.FormValid(form))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -157,7 +166,17 @@ else
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task DeleteUserRole(int UserRoleId)
|
private async Task DeleteUserRole(int UserRoleId)
|
||||||
|
{
|
||||||
|
validated = true;
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
if (await interop.FormValid(form))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -173,4 +192,9 @@ else
|
||||||
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,12 +44,6 @@
|
||||||
<input id="installationid" class="form-control" @bind="@_installationid" readonly />
|
<input id="installationid" class="form-control" @bind="@_installationid" readonly />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<div class="col-sm-3"></div>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<br /><input type="checkbox" @onchange="(e => RegisterChecked(e))" /> @Localizer["Register"]
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
||||||
|
@ -196,20 +190,4 @@
|
||||||
await logger.LogError(ex, "Error Restarting Application");
|
await logger.LogError(ex, "Error Restarting Application");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RegisterChecked(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if ((bool)e.Value)
|
|
||||||
{
|
|
||||||
await InstallationService.RegisterAsync(PageState.User.Email);
|
|
||||||
AddModuleMessage(Localizer["Success.Register"], MessageType.Success);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error On Register");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -37,17 +37,18 @@
|
||||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||||
|
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PackageUrl))
|
@if (context.Price != null && !string.IsNullOrEmpty(context.PackageUrl))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td style="width: 1px; vertical-align: middle;">
|
<td style="width: 1px; vertical-align: middle;">
|
||||||
@if (context.Price > 0 && !string.IsNullOrEmpty(context.PaymentUrl))
|
@if (context.Price != null && !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>
|
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.Value.ToString("$#,##0.00")</a>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,8 +21,9 @@ else
|
||||||
<Header>
|
<Header>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th scope="col">@SharedLocalizer["Name"]</th>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
<th scope="col">@SharedLocalizer["Version"]</th>
|
<th>@SharedLocalizer["Version"]</th>
|
||||||
|
<th>@SharedLocalizer["Expires"]</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -35,6 +36,9 @@ else
|
||||||
</td>
|
</td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Version</td>
|
<td>@context.Version</td>
|
||||||
|
<td>
|
||||||
|
@((MarkupString)PurchaseLink(context.PackageName))
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if (UpgradeAvailable(context.PackageName, context.Version))
|
@if (UpgradeAvailable(context.PackageName, context.Version))
|
||||||
{
|
{
|
||||||
|
@ -69,6 +73,27 @@ else
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string PurchaseLink(string packagename)
|
||||||
|
{
|
||||||
|
string link = "";
|
||||||
|
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||||
|
{
|
||||||
|
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||||
|
if (package != null)
|
||||||
|
{
|
||||||
|
if (package.ExpiryDate != null && package.ExpiryDate.Value.Date != DateTime.MaxValue.Date)
|
||||||
|
{
|
||||||
|
link += "<span>" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + "</span>";
|
||||||
|
if (!string.IsNullOrEmpty(package.PaymentUrl))
|
||||||
|
{
|
||||||
|
link += " <a class=\"btn btn-primary\" style=\"text-decoration: none !important\" href=\"" + package.PaymentUrl + "\" target=\"_new\">" + SharedLocalizer["Extend"] + "</a>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string packagename, string version)
|
private bool UpgradeAvailable(string packagename, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
var upgradeavailable = false;
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
@inject ISettingService SettingService
|
@inject ISettingService SettingService
|
||||||
@inject INotificationService NotificationService
|
@inject INotificationService NotificationService
|
||||||
@inject IFileService FileService
|
@inject IFileService FileService
|
||||||
|
@inject IFolderService FolderService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
@if (PageState.User != null && photo != null)
|
@if (PageState.User != null && photo != null)
|
||||||
{
|
{
|
||||||
<img src="@photo.Url" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
<img src="@ImageUrl(photofileid, "400x400", "crop")" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -19,7 +20,7 @@ else
|
||||||
}
|
}
|
||||||
<TabStrip>
|
<TabStrip>
|
||||||
<TabPanel Name="Identity" ResourceKey="Identity">
|
<TabPanel Name="Identity" ResourceKey="Identity">
|
||||||
@if (PageState.User != null)
|
@if (profiles != null && settings != null)
|
||||||
{
|
{
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
@ -55,7 +56,7 @@ else
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="@photofileid.ToString()" HelpText="A photo of yourself" ResourceKey="Photo"></Label>
|
<Label Class="col-sm-3" For="@photofileid.ToString()" HelpText="A photo of yourself" ResourceKey="Photo"></Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<FileManager FileId="@photofileid" @ref="filemanager" />
|
<FileManager FileId="@photofileid" Filter="@Constants.ImageFiles" ShowFolders="false" ShowFiles="true" UploadMultiple="false" FolderId="@folderid" @ref="filemanager" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,8 +68,6 @@ else
|
||||||
<TabPanel Name="Profile" ResourceKey="Profile">
|
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||||
@if (profiles != null && settings != null)
|
@if (profiles != null && settings != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@foreach (Profile profile in profiles)
|
@foreach (Profile profile in profiles)
|
||||||
|
@ -210,6 +209,7 @@ else
|
||||||
private string email = string.Empty;
|
private string email = string.Empty;
|
||||||
private string displayname = string.Empty;
|
private string displayname = string.Empty;
|
||||||
private FileManager filemanager;
|
private FileManager filemanager;
|
||||||
|
private int folderid = -1;
|
||||||
private int photofileid = -1;
|
private int photofileid = -1;
|
||||||
private File photo = null;
|
private File photo = null;
|
||||||
private List<Profile> profiles;
|
private List<Profile> profiles;
|
||||||
|
@ -230,6 +230,13 @@ else
|
||||||
email = PageState.User.Email;
|
email = PageState.User.Email;
|
||||||
displayname = PageState.User.DisplayName;
|
displayname = PageState.User.DisplayName;
|
||||||
|
|
||||||
|
// get user folder
|
||||||
|
var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
|
||||||
|
if (folder != null)
|
||||||
|
{
|
||||||
|
folderid = folder.FolderId;
|
||||||
|
}
|
||||||
|
|
||||||
if (PageState.User.PhotoFileId != null)
|
if (PageState.User.PhotoFileId != null)
|
||||||
{
|
{
|
||||||
photofileid = PageState.User.PhotoFileId.Value;
|
photofileid = PageState.User.PhotoFileId.Value;
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@if (_image != string.Empty)
|
@if (_image != string.Empty && ShowImage)
|
||||||
{
|
{
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
@((MarkupString) _image)
|
@((MarkupString) _image)
|
||||||
|
@ -110,6 +110,9 @@
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
|
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool ShowImage { get; set; } = true; // optional - for indicating whether an image thumbnail should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int FileId { get; set; } = -1; // optional - for setting a specific file by default
|
public int FileId { get; set; } = -1; // optional - for setting a specific file by default
|
||||||
|
|
||||||
|
|
|
@ -2,45 +2,57 @@
|
||||||
@inherits ModuleControlBase
|
@inherits ModuleControlBase
|
||||||
@typeparam TableItem
|
@typeparam TableItem
|
||||||
|
|
||||||
<p>
|
@if (ItemList != null)
|
||||||
@if (Toolbar == "Top")
|
{
|
||||||
|
@if (Toolbar == "Top" && _pages > 0 && Items.Count() > _maxItems)
|
||||||
{
|
{
|
||||||
<div class="mx-auto text-center">
|
<ul class="pagination justify-content-center my-2">
|
||||||
@if (_endPage > 1)
|
<li class="page-item@((_page > 1) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="start" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
|
@if (_pages > _displayPages)
|
||||||
{
|
{
|
||||||
<button class="btn btn-secondary m-1" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="first" aria-hidden="true"></span></button>
|
<li class="page-item@((_page > _displayPages) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => SkipPages("back"))><span class="oi oi-media-skip-backward" title="skip back" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
@if (_page > _maxPages)
|
<li class="page-item@((_page > 1) ? "" : " disabled")">
|
||||||
{
|
<a class="page-link" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></a>
|
||||||
<button class="btn btn-secondary m-1" @onclick=@(async () => SetPagerSize("back"))><span class="oi oi-media-skip-backward" title="back" aria-hidden="true"></span></button>
|
</li>
|
||||||
}
|
|
||||||
@if (_endPage > 1)
|
|
||||||
{
|
|
||||||
<button class="btn btn-secondary m-1" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
|
|
||||||
@for (int i = _startPage; i <= _endPage; i++)
|
@for (int i = _startPage; i <= _endPage; i++)
|
||||||
{
|
{
|
||||||
var pager = i;
|
var pager = i;
|
||||||
<button class="btn @((pager == _page) ? "btn-primary" : "btn-link")" @onclick=@(async () => UpdateList(pager))>
|
if (pager == _page)
|
||||||
@pager
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
<button class="btn btn-secondary m-1" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></button>
|
|
||||||
}
|
|
||||||
@if (_endPage < _pages)
|
|
||||||
{
|
{
|
||||||
<button class="btn btn-secondary m-1" @onclick=@(async () => SetPagerSize("forward"))><span class="oi oi-media-skip-forward" title="forward" aria-hidden="true"></span></button>
|
<li class="page-item active">
|
||||||
|
<a class="page-link" @onclick=@(async () => UpdateList(pager))>@pager</a>
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
@if (_endPage > 1)
|
else
|
||||||
{
|
{
|
||||||
<button class="btn btn-secondary m-1" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="last" aria-hidden="true"></span></button>
|
<li class="page-item">
|
||||||
|
<a class="page-link" @onclick=@(async () => UpdateList(pager))>@pager</a>
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
@if (_endPage > 1)
|
}
|
||||||
|
<li class="page-item@((_page < _pages) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
|
@if (_pages > _displayPages)
|
||||||
{
|
{
|
||||||
<span class="btn btn-link disabled">Page @_page of @_pages</span>
|
<li class="page-item@((_endPage < _pages) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => SkipPages("forward"))><span class="oi oi-media-skip-forward" title="skip forward" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
</div>
|
<li class="page-item@((_page < _pages) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="end" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
|
<li class="page-item disabled">
|
||||||
|
<a class="page-link">Page @_page of @_pages</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
}
|
}
|
||||||
@if (Format == "Table")
|
@if (Format == "Table" && Row != null)
|
||||||
{
|
{
|
||||||
<table class="@Class">
|
<table class="@Class">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -58,90 +70,125 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
}
|
}
|
||||||
@if (Format == "Grid")
|
@if (Format == "Grid" && Row != null)
|
||||||
{
|
{
|
||||||
|
int count = 0;
|
||||||
|
if (ItemList != null)
|
||||||
|
{
|
||||||
|
count = (int)Math.Ceiling(ItemList.Count() / (decimal)_columns) * _columns;
|
||||||
|
}
|
||||||
<div class="@Class">
|
<div class="@Class">
|
||||||
<div class="row">@Header</div>
|
@if (Header != null)
|
||||||
@foreach (var item in ItemList)
|
|
||||||
{
|
{
|
||||||
<div class="row">@Row(item)</div>
|
<div class="row"><div class="col">@Header</div></div>
|
||||||
@if (Detail != null)
|
}
|
||||||
|
@for (int row = 0; row < (count / _columns); row++)
|
||||||
{
|
{
|
||||||
<div class="row">@Detail(item)</div>
|
<div class="row">
|
||||||
|
@for (int col = 0; col < _columns; col++)
|
||||||
|
{
|
||||||
|
int index = (row * _columns) + col;
|
||||||
|
if (index < ItemList.Count())
|
||||||
|
{
|
||||||
|
<div class="col">@Row(ItemList.ElementAt(index))</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="col"> </div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (Toolbar == "Bottom")
|
</div>
|
||||||
{
|
|
||||||
<div class="mx-auto text-center">
|
|
||||||
@if (_endPage > 1)
|
|
||||||
{
|
|
||||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="first" aria-hidden="true"></span></button>
|
|
||||||
}
|
}
|
||||||
@if (_page > _maxPages)
|
@if (Toolbar == "Bottom" && _pages > 0 && Items.Count() > _maxItems)
|
||||||
{
|
{
|
||||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => SetPagerSize("back"))><span class="oi oi-media-skip-backward" title="back" aria-hidden="true"></span></button>
|
<ul class="pagination justify-content-center my-2">
|
||||||
|
<li class="page-item@((_page > 1) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="start" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
|
@if (_pages > _displayPages)
|
||||||
|
{
|
||||||
|
<li class="page-item@((_page > _displayPages) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => SkipPages("back"))><span class="oi oi-media-skip-backward" title="skip back" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
@if (_endPage > 1)
|
<li class="page-item@((_page > 1) ? "" : " disabled")">
|
||||||
{
|
<a class="page-link" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></a>
|
||||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
|
</li>
|
||||||
@for (int i = _startPage; i <= _endPage; i++)
|
@for (int i = _startPage; i <= _endPage; i++)
|
||||||
{
|
{
|
||||||
var pager = i;
|
var pager = i;
|
||||||
<button class="btn @((pager == _page) ? "btn-primary" : "btn-link")" @onclick=@(async () => UpdateList(pager))>
|
if (pager == _page)
|
||||||
@pager
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></button>
|
|
||||||
}
|
|
||||||
@if (_endPage < _pages)
|
|
||||||
{
|
{
|
||||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => SetPagerSize("forward"))><span class="oi oi-media-skip-forward" title="forward" aria-hidden="true"></span></button>
|
<li class="page-item active">
|
||||||
|
<a class="page-link" @onclick=@(async () => UpdateList(pager))>@pager</a>
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
@if (_endPage > 1)
|
else
|
||||||
{
|
{
|
||||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="last" aria-hidden="true"></span></button>
|
<li class="page-item">
|
||||||
|
<a class="page-link" @onclick=@(async () => UpdateList(pager))>@pager</a>
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
@if (_endPage > 1)
|
}
|
||||||
|
<li class="page-item@((_page < _pages) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
|
@if (_pages > _displayPages)
|
||||||
{
|
{
|
||||||
<span class="btn btn-link disabled">Page @_page of @_pages</span>
|
<li class="page-item@((_endPage < _pages) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => SkipPages("forward"))><span class="oi oi-media-skip-forward" title="skip forward" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
}
|
}
|
||||||
</div>
|
<li class="page-item@((_page < _pages) ? "" : " disabled")">
|
||||||
|
<a class="page-link" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="end" aria-hidden="true"></span></a>
|
||||||
|
</li>
|
||||||
|
<li class="page-item disabled">
|
||||||
|
<a class="page-link">Page @_page of @_pages</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
}
|
}
|
||||||
</p>
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private int _pages = 0;
|
private int _pages = 0;
|
||||||
private int _page = 1;
|
private int _page = 1;
|
||||||
private int _maxItems = 10;
|
private int _maxItems = 10;
|
||||||
private int _maxPages = 5;
|
private int _displayPages = 5;
|
||||||
private int _startPage = 0;
|
private int _startPage = 0;
|
||||||
private int _endPage = 0;
|
private int _endPage = 0;
|
||||||
|
private int _columns = 1;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Format { get; set; }
|
public string Format { get; set; } // Table or Grid
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Toolbar { get; set; }
|
public string Toolbar { get; set; } // Top or Bottom
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public RenderFragment Header { get; set; }
|
public RenderFragment Header { get; set; } = null;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public RenderFragment<TableItem> Row { get; set; }
|
public RenderFragment<TableItem> Row { get; set; } = null;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public RenderFragment<TableItem> Detail { get; set; }
|
public RenderFragment<TableItem> Detail { get; set; } = null; // only applicable to Table layouts
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public IEnumerable<TableItem> Items { get; set; }
|
public IEnumerable<TableItem> Items { get; set; } // the IEnumerable data source
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string PageSize { get; set; }
|
public string PageSize { get; set; } // number of items to display on a page
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string DisplayPages { get; set; }
|
public string Columns { get; set; } // only applicable to Grid layouts
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string CurrentPage { get; set; } // optional property to set the initial page to display
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string DisplayPages { get; set; } // maximum number of page numbers to display for user selection
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Class { get; set; }
|
public string Class { get; set; }
|
||||||
|
@ -177,86 +224,89 @@
|
||||||
_maxItems = int.Parse(PageSize);
|
_maxItems = int.Parse(PageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(DisplayPages))
|
if (!string.IsNullOrEmpty(Columns))
|
||||||
{
|
{
|
||||||
_maxPages = int.Parse(DisplayPages);
|
_columns = int.Parse(Columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(DisplayPages))
|
||||||
|
{
|
||||||
|
_displayPages = int.Parse(DisplayPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(CurrentPage))
|
||||||
|
{
|
||||||
|
_page = int.Parse(CurrentPage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_page = 1;
|
_page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
_startPage = 0;
|
_startPage = 0;
|
||||||
_endPage = 0;
|
_endPage = 0;
|
||||||
|
|
||||||
if (Items != null)
|
if (Items != null)
|
||||||
{
|
{
|
||||||
ItemList = Items.Skip((_page - 1) * _maxItems).Take(_maxItems);
|
|
||||||
_pages = (int)Math.Ceiling(Items.Count() / (decimal)_maxItems);
|
_pages = (int)Math.Ceiling(Items.Count() / (decimal)_maxItems);
|
||||||
|
if (_page > _pages)
|
||||||
|
{
|
||||||
|
_page = _pages;
|
||||||
|
}
|
||||||
|
ItemList = Items.Skip((_page - 1) * _maxItems).Take(_maxItems);
|
||||||
|
SetPagerSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetPagerSize("forward");
|
public void SetPagerSize()
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateList(int currentPage)
|
|
||||||
{
|
{
|
||||||
ItemList = Items.Skip((currentPage - 1) * _maxItems).Take(_maxItems);
|
_startPage = ((_page - 1) / _displayPages) * _displayPages + 1;
|
||||||
_page = currentPage;
|
_endPage = _startPage + _displayPages - 1;
|
||||||
|
if (_endPage > _pages)
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetPagerSize(string direction)
|
|
||||||
{
|
|
||||||
if (direction == "forward")
|
|
||||||
{
|
|
||||||
if (_endPage + 1 < _pages)
|
|
||||||
{
|
|
||||||
_startPage = _endPage + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_startPage = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_endPage + _maxPages < _pages)
|
|
||||||
{
|
|
||||||
_endPage = _startPage + _maxPages - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
_endPage = _pages;
|
_endPage = _pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
else if (direction == "back")
|
|
||||||
|
public void UpdateList(int page)
|
||||||
{
|
{
|
||||||
_endPage = _startPage - 1;
|
ItemList = Items.Skip((page - 1) * _maxItems).Take(_maxItems);
|
||||||
_startPage = _startPage - _maxPages;
|
_page = page;
|
||||||
|
SetPagerSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SkipPages(string direction)
|
||||||
|
{
|
||||||
|
switch (direction)
|
||||||
|
{
|
||||||
|
case "forward":
|
||||||
|
_page = _endPage + 1;
|
||||||
|
break;
|
||||||
|
case "back":
|
||||||
|
_page = _startPage - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetPagerSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NavigateToPage(string direction)
|
public void NavigateToPage(string direction)
|
||||||
{
|
{
|
||||||
if (direction == "next")
|
switch (direction)
|
||||||
{
|
{
|
||||||
|
case "next":
|
||||||
if (_page < _pages)
|
if (_page < _pages)
|
||||||
{
|
{
|
||||||
if (_page == _endPage)
|
|
||||||
{
|
|
||||||
SetPagerSize("forward");
|
|
||||||
}
|
|
||||||
_page += 1;
|
_page += 1;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if (direction == "previous")
|
case "previous":
|
||||||
{
|
|
||||||
if (_page > 1)
|
if (_page > 1)
|
||||||
{
|
{
|
||||||
if (_page == _startPage)
|
|
||||||
{
|
|
||||||
SetPagerSize("back");
|
|
||||||
}
|
|
||||||
_page -= 1;
|
_page -= 1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateList(_page);
|
UpdateList(_page);
|
||||||
|
|
|
@ -134,6 +134,11 @@ namespace Oqtane.Modules
|
||||||
return Utilities.ContentUrl(PageState.Alias, fileid, asAttachment);
|
return Utilities.ContentUrl(PageState.Alias, fileid, asAttachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string ImageUrl(int fileid, string size, string mode)
|
||||||
|
{
|
||||||
|
return Utilities.ImageUrl(PageState.Alias, fileid, size, mode);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "")
|
public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "")
|
||||||
{
|
{
|
||||||
var urlParameters = new Dictionary<string, string>();
|
var urlParameters = new Dictionary<string, string>();
|
||||||
|
|
|
@ -144,4 +144,10 @@
|
||||||
<data name="Size.Text" xml:space="preserve">
|
<data name="Size.Text" xml:space="preserve">
|
||||||
<value>Size: </value>
|
<value>Size: </value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Description.HelpText" xml:space="preserve">
|
||||||
|
<value>A description of the file. This can be used as a caption for image files.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Description.Text" xml:space="preserve">
|
||||||
|
<value>Description:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -171,4 +171,16 @@
|
||||||
<data name="Type.Text" xml:space="preserve">
|
<data name="Type.Text" xml:space="preserve">
|
||||||
<value>Type:</value>
|
<value>Type:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Capacity.HelpText" xml:space="preserve">
|
||||||
|
<value>Enter the maximum folder capacity (in megabytes). Specify zero if the capacity is unlimited.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Capacity.Text" xml:space="preserve">
|
||||||
|
<value>Capacity:</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageSizes.HelpText" xml:space="preserve">
|
||||||
|
<value>Enter a list of image sizes which can be generated dynamically from uploaded images (ie. 200x200,x200,200x)</value>
|
||||||
|
</data>
|
||||||
|
<data name="ImageSizes.Text" xml:space="preserve">
|
||||||
|
<value>Image Sizes:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -228,4 +228,7 @@
|
||||||
<data name="Appearance.Name" xml:space="preserve">
|
<data name="Appearance.Name" xml:space="preserve">
|
||||||
<value>Appearance</value>
|
<value>Appearance</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.Page.Deleted" xml:space="preserve">
|
||||||
|
<value>A page with path {0} already exists for the selected parent page in the Recycle Bin. Either recover the page or remove from the Recycle Bin and create it again.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -300,4 +300,13 @@
|
||||||
<data name="Review License Terms" xml:space="preserve">
|
<data name="Review License Terms" xml:space="preserve">
|
||||||
<value>Review License Terms</value>
|
<value>Review License Terms</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Trial" xml:space="preserve">
|
||||||
|
<value>Day Trial</value>
|
||||||
|
</data>
|
||||||
|
<data name="Expires" xml:space="preserve">
|
||||||
|
<value>Expires</value>
|
||||||
|
</data>
|
||||||
|
<data name="Extend" xml:space="preserve">
|
||||||
|
<value>Extend</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -96,7 +96,7 @@ namespace Oqtane.Themes.Controls
|
||||||
{
|
{
|
||||||
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||||
|
|
||||||
string url = NavigateUrl();
|
string url = NavigateUrl(true);
|
||||||
|
|
||||||
if (action.Action != null)
|
if (action.Action != null)
|
||||||
{
|
{
|
||||||
|
@ -115,7 +115,7 @@ namespace Oqtane.Themes.Controls
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, oldPane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, oldPane);
|
||||||
return NavigateUrl(url, true);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> DeleteModule(string url, PageModule pagemodule)
|
private async Task<string> DeleteModule(string url, PageModule pagemodule)
|
||||||
|
@ -123,7 +123,7 @@ namespace Oqtane.Themes.Controls
|
||||||
pagemodule.IsDeleted = true;
|
pagemodule.IsDeleted = true;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return NavigateUrl(url, true);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> Settings(string url, PageModule pagemodule)
|
private async Task<string> Settings(string url, PageModule pagemodule)
|
||||||
|
@ -133,7 +133,7 @@ namespace Oqtane.Themes.Controls
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> Publish(string s, PageModule pagemodule)
|
private async Task<string> Publish(string url, PageModule pagemodule)
|
||||||
{
|
{
|
||||||
var permissions = UserSecurity.GetPermissionStrings(pagemodule.Module.Permissions);
|
var permissions = UserSecurity.GetPermissionStrings(pagemodule.Module.Permissions);
|
||||||
foreach (var permissionstring in permissions)
|
foreach (var permissionstring in permissions)
|
||||||
|
@ -148,10 +148,10 @@ namespace Oqtane.Themes.Controls
|
||||||
}
|
}
|
||||||
pagemodule.Module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
pagemodule.Module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
await ModuleService.UpdateModuleAsync(pagemodule.Module);
|
await ModuleService.UpdateModuleAsync(pagemodule.Module);
|
||||||
return NavigateUrl(s, true);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> Unpublish(string s, PageModule pagemodule)
|
private async Task<string> Unpublish(string url, PageModule pagemodule)
|
||||||
{
|
{
|
||||||
var permissions = UserSecurity.GetPermissionStrings(pagemodule.Module.Permissions);
|
var permissions = UserSecurity.GetPermissionStrings(pagemodule.Module.Permissions);
|
||||||
foreach (var permissionstring in permissions)
|
foreach (var permissionstring in permissions)
|
||||||
|
@ -166,39 +166,39 @@ namespace Oqtane.Themes.Controls
|
||||||
}
|
}
|
||||||
pagemodule.Module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
pagemodule.Module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
await ModuleService.UpdateModuleAsync(pagemodule.Module);
|
await ModuleService.UpdateModuleAsync(pagemodule.Module);
|
||||||
return NavigateUrl(s, true);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> MoveTop(string s, PageModule pagemodule)
|
private async Task<string> MoveTop(string url, PageModule pagemodule)
|
||||||
{
|
{
|
||||||
pagemodule.Order = 0;
|
pagemodule.Order = 0;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return NavigateUrl(s, true);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> MoveBottom(string s, PageModule pagemodule)
|
private async Task<string> MoveBottom(string url, PageModule pagemodule)
|
||||||
{
|
{
|
||||||
pagemodule.Order = int.MaxValue;
|
pagemodule.Order = int.MaxValue;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return NavigateUrl(s, true);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> MoveUp(string s, PageModule pagemodule)
|
private async Task<string> MoveUp(string url, PageModule pagemodule)
|
||||||
{
|
{
|
||||||
pagemodule.Order -= 3;
|
pagemodule.Order -= 3;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return NavigateUrl(s, true);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> MoveDown(string s, PageModule pagemodule)
|
private async Task<string> MoveDown(string url, PageModule pagemodule)
|
||||||
{
|
{
|
||||||
pagemodule.Order += 3;
|
pagemodule.Order += 3;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return NavigateUrl(s, true);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ActionViewModel
|
public class ActionViewModel
|
||||||
|
|
|
@ -400,17 +400,17 @@
|
||||||
await PageModuleService.AddPageModuleAsync(pageModule);
|
await PageModuleService.AddPageModuleAsync(pageModule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane);
|
||||||
|
|
||||||
Message = $"<br /><div class=\"alert alert-success\" role=\"alert\">{Localizer["Success.Page.ModuleAdd"]}</div>";
|
Message = $"<div class=\"alert alert-success mt-2 text-center\" role=\"alert\">{Localizer["Success.Page.ModuleAdd"]}</div>";
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Message = $"<br /><div class=\"alert alert-warning\" role=\"alert\">{Localizer["Message.Require.ModuleSelect"]}</div>";
|
Message = $"<div class=\"alert alert-warning mt-2 text-center\" role=\"alert\">{Localizer["Message.Require.ModuleSelect"]}</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Message = $"<br /><div class=\"alert alert-error\" role=\"alert\">{Localizer["Error.Authorize.No"]}</div>";
|
Message = $"<div class=\"alert alert-error mt-2 text-center\" role=\"alert\">{Localizer["Error.Authorize.No"]}</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,5 +103,10 @@ namespace Oqtane.Themes
|
||||||
{
|
{
|
||||||
return Utilities.ContentUrl(PageState.Alias, fileid, asAttachment);
|
return Utilities.ContentUrl(PageState.Alias, fileid, asAttachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string ImageUrl(int fileid, string size, string mode)
|
||||||
|
{
|
||||||
|
return Utilities.ImageUrl(PageState.Alias, fileid, size, mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
|
|
||||||
<CascadingValue Value="@ModuleState" IsFixed="true">
|
<CascadingValue Value="@ModuleState" IsFixed="@(!PageState.EditMode)">
|
||||||
@if (_useadminborder)
|
@if (_useadminborder)
|
||||||
{
|
{
|
||||||
<div class="app-pane-admin-border">
|
<div class="app-pane-admin-border">
|
||||||
|
|
|
@ -138,6 +138,7 @@
|
||||||
if (authState.User.Identity.IsAuthenticated)
|
if (authState.User.Identity.IsAuthenticated)
|
||||||
{
|
{
|
||||||
user = await UserService.GetUserAsync(authState.User.Identity.Name, site.SiteId);
|
user = await UserService.GetUserAsync(authState.User.Identity.Name, site.SiteId);
|
||||||
|
user.IsAuthenticated = authState.User.Identity.IsAuthenticated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -17,6 +17,9 @@ using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using SixLabors.ImageSharp.Formats.Png;
|
||||||
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
|
||||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||||
|
|
||||||
|
@ -71,7 +74,7 @@ namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
foreach (string file in Directory.GetFiles(folder))
|
foreach (string file in Directory.GetFiles(folder))
|
||||||
{
|
{
|
||||||
files.Add(new Models.File {Name = Path.GetFileName(file), Extension = Path.GetExtension(file)?.Replace(".", "")});
|
files.Add(new Models.File { Name = Path.GetFileName(file), Extension = Path.GetExtension(file)?.Replace(".", "") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +172,11 @@ namespace Oqtane.Controllers
|
||||||
string filepath = _files.GetFilePath(file);
|
string filepath = _files.GetFilePath(file);
|
||||||
if (System.IO.File.Exists(filepath))
|
if (System.IO.File.Exists(filepath))
|
||||||
{
|
{
|
||||||
System.IO.File.Delete(filepath);
|
// remove file and thumbnails
|
||||||
|
foreach(var f in Directory.GetFiles(Path.GetDirectoryName(filepath), Path.GetFileNameWithoutExtension(filepath) + ".*"))
|
||||||
|
{
|
||||||
|
System.IO.File.Delete(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "File Deleted {File}", file);
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "File Deleted {File}", file);
|
||||||
|
@ -226,7 +233,11 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
client.DownloadFile(url, targetPath);
|
client.DownloadFile(url, targetPath);
|
||||||
file = _files.AddFile(CreateFile(filename, folder.FolderId, targetPath));
|
file = CreateFile(filename, folder.FolderId, targetPath);
|
||||||
|
if (file != null)
|
||||||
|
{
|
||||||
|
file = _files.AddFile(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -235,7 +246,7 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Upload Attempt {FolderId} {Url}", folderid, url);
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Download Attempt {FolderId} {Url}", folderid, url);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,16 +255,16 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// POST api/<controller>/upload
|
// POST api/<controller>/upload
|
||||||
[HttpPost("upload")]
|
[HttpPost("upload")]
|
||||||
public async Task UploadFile(string folder, IFormFile file)
|
public async Task UploadFile(string folder, IFormFile formfile)
|
||||||
{
|
{
|
||||||
if (file.Length <= 0)
|
if (formfile.Length <= 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file.FileName.IsPathOrFileValid())
|
if (!formfile.FileName.IsPathOrFileValid())
|
||||||
{
|
{
|
||||||
HttpContext.Response.StatusCode = (int) HttpStatusCode.Conflict;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,20 +291,24 @@ namespace Oqtane.Controllers
|
||||||
if (!string.IsNullOrEmpty(folderPath))
|
if (!string.IsNullOrEmpty(folderPath))
|
||||||
{
|
{
|
||||||
CreateDirectory(folderPath);
|
CreateDirectory(folderPath);
|
||||||
using (var stream = new FileStream(Path.Combine(folderPath, file.FileName), FileMode.Create))
|
using (var stream = new FileStream(Path.Combine(folderPath, formfile.FileName), FileMode.Create))
|
||||||
{
|
{
|
||||||
await file.CopyToAsync(stream);
|
await formfile.CopyToAsync(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
string upload = await MergeFile(folderPath, file.FileName);
|
string upload = await MergeFile(folderPath, formfile.FileName);
|
||||||
if (upload != "" && FolderId != -1)
|
if (upload != "" && FolderId != -1)
|
||||||
{
|
{
|
||||||
_files.AddFile(CreateFile(upload, FolderId, Path.Combine(folderPath, upload)));
|
var file = CreateFile(upload, FolderId, Path.Combine(folderPath, upload));
|
||||||
|
if (file != null)
|
||||||
|
{
|
||||||
|
_files.AddFile(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Upload Attempt {Folder} {File}", folder, file);
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Upload Attempt {Folder} {File}", folder, formfile.FileName);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -479,6 +494,99 @@ namespace Oqtane.Controllers
|
||||||
return System.IO.File.Exists(errorPath) ? PhysicalFile(errorPath, MimeUtilities.GetMimeType(errorPath)) : null;
|
return System.IO.File.Exists(errorPath) ? PhysicalFile(errorPath, MimeUtilities.GetMimeType(errorPath)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("image/{id}/{size}/{mode?}")]
|
||||||
|
public IActionResult GetImage(int id, string size, string mode)
|
||||||
|
{
|
||||||
|
var file = _files.GetFile(id);
|
||||||
|
if (file != null && file.Folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.Permissions))
|
||||||
|
{
|
||||||
|
if (Constants.ImageFiles.Split(',').Contains(file.Extension.ToLower()))
|
||||||
|
{
|
||||||
|
var filepath = _files.GetFilePath(file);
|
||||||
|
if (System.IO.File.Exists(filepath))
|
||||||
|
{
|
||||||
|
size = size.ToLower();
|
||||||
|
mode = (string.IsNullOrEmpty(mode)) ? "crop" : mode;
|
||||||
|
if ((_userPermissions.IsAuthorized(User, PermissionNames.Edit, file.Folder.Permissions) ||
|
||||||
|
size.Contains("x") && !string.IsNullOrEmpty(file.Folder.ImageSizes) && file.Folder.ImageSizes.ToLower().Split(",").Contains(size))
|
||||||
|
&& Enum.TryParse(mode, true, out ResizeMode resizemode))
|
||||||
|
{
|
||||||
|
var imagepath = CreateImage(filepath, size, resizemode.ToString());
|
||||||
|
if (!string.IsNullOrEmpty(imagepath))
|
||||||
|
{
|
||||||
|
return PhysicalFile(imagepath, file.GetMimeType());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Create, "Error Creating Image For File {File} {Size}", file, size);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Invalid Image Size For Folder Or Invalid Mode Specification {Folder} {Size} {Mode}", file.Folder, size, mode);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Is Not An Image {File}", file);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Access Attempt {FileId}", id);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
string errorPath = Path.Combine(GetFolderPath("images"), "error.png");
|
||||||
|
return System.IO.File.Exists(errorPath) ? PhysicalFile(errorPath, MimeUtilities.GetMimeType(errorPath)) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string CreateImage(string filepath, string size, string mode)
|
||||||
|
{
|
||||||
|
string imagepath = filepath.Replace(Path.GetExtension(filepath), "." + size + "." + mode.ToLower() + ".png");
|
||||||
|
|
||||||
|
if (!System.IO.File.Exists(imagepath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
|
||||||
|
using (Image image = Image.Load(stream))
|
||||||
|
{
|
||||||
|
var parts = size.Split('x');
|
||||||
|
int width = (!string.IsNullOrEmpty(parts[0])) ? int.Parse(parts[0]) : 0;
|
||||||
|
int height = (!string.IsNullOrEmpty(parts[1])) ? int.Parse(parts[1]) : 0;
|
||||||
|
Enum.TryParse(mode, true, out ResizeMode resizemode);
|
||||||
|
|
||||||
|
image.Mutate(x =>
|
||||||
|
x.Resize(new ResizeOptions
|
||||||
|
{
|
||||||
|
Size = new Size(width, height),
|
||||||
|
Mode = resizemode
|
||||||
|
})
|
||||||
|
.BackgroundColor(new Rgba32(255, 255, 255, 0)));
|
||||||
|
|
||||||
|
image.Save(imagepath, new PngEncoder());
|
||||||
|
}
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
|
catch // error creating image
|
||||||
|
{
|
||||||
|
imagepath = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return imagepath;
|
||||||
|
}
|
||||||
|
|
||||||
private string GetFolderPath(string folder)
|
private string GetFolderPath(string folder)
|
||||||
{
|
{
|
||||||
return Utilities.PathCombine(_environment.ContentRootPath, folder);
|
return Utilities.PathCombine(_environment.ContentRootPath, folder);
|
||||||
|
@ -489,7 +597,7 @@ namespace Oqtane.Controllers
|
||||||
if (!Directory.Exists(folderpath))
|
if (!Directory.Exists(folderpath))
|
||||||
{
|
{
|
||||||
string path = "";
|
string path = "";
|
||||||
var separators = new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar};
|
var separators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
|
||||||
string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries);
|
string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries);
|
||||||
foreach (string folder in folders)
|
foreach (string folder in folders)
|
||||||
{
|
{
|
||||||
|
@ -504,17 +612,33 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
private Models.File CreateFile(string filename, int folderid, string filepath)
|
private Models.File CreateFile(string filename, int folderid, string filepath)
|
||||||
{
|
{
|
||||||
Models.File file = new Models.File();
|
Models.File file = null;
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
var folder = _folders.GetFolder(folderid);
|
||||||
|
if (folder.Capacity != 0)
|
||||||
|
{
|
||||||
|
foreach (var f in _files.GetFiles(folderid))
|
||||||
|
{
|
||||||
|
size += f.Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInfo fileinfo = new FileInfo(filepath);
|
||||||
|
if (folder.Capacity == 0 || ((size + fileinfo.Length) / 1000000) < folder.Capacity)
|
||||||
|
{
|
||||||
|
file = new Models.File();
|
||||||
file.Name = filename;
|
file.Name = filename;
|
||||||
file.FolderId = folderid;
|
file.FolderId = folderid;
|
||||||
|
|
||||||
FileInfo fileinfo = new FileInfo(filepath);
|
|
||||||
file.Extension = fileinfo.Extension.ToLower().Replace(".", "");
|
file.Extension = fileinfo.Extension.ToLower().Replace(".", "");
|
||||||
file.Size = (int) fileinfo.Length;
|
file.Size = (int)fileinfo.Length;
|
||||||
file.ImageHeight = 0;
|
file.ImageHeight = 0;
|
||||||
file.ImageWidth = 0;
|
file.ImageWidth = 0;
|
||||||
|
|
||||||
if (Constants.ImageFiles.Split(',').Contains(file.Extension.ToLower()))
|
if (Constants.ImageFiles.Split(',').Contains(file.Extension.ToLower()))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
|
FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
|
||||||
using (Image image = Image.Load(stream))
|
using (Image image = Image.Load(stream))
|
||||||
|
@ -524,6 +648,17 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
stream.Close();
|
stream.Close();
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// error opening image file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.IO.File.Delete(filepath);
|
||||||
|
_logger.Log(LogLevel.Warning, this, LogFunction.Create, "File Exceeds Folder Capacity {Folder} {File}", folder, filepath);
|
||||||
|
}
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,8 +187,10 @@ namespace Oqtane.Controllers
|
||||||
ParentId = folder.FolderId,
|
ParentId = folder.FolderId,
|
||||||
Name = "My Folder",
|
Name = "My Folder",
|
||||||
Type = FolderTypes.Private,
|
Type = FolderTypes.Private,
|
||||||
Path = Utilities.PathCombine(folder.Path, newUser.UserId.ToString(),Path.DirectorySeparatorChar.ToString()),
|
Path = Utilities.PathCombine(folder.Path, newUser.UserId.ToString(), Path.DirectorySeparatorChar.ToString()),
|
||||||
Order = 1,
|
Order = 1,
|
||||||
|
ImageSizes = "",
|
||||||
|
Capacity = Constants.UserFolderCapacity,
|
||||||
IsSystem = true,
|
IsSystem = true,
|
||||||
Permissions = new List<Permission>
|
Permissions = new List<Permission>
|
||||||
{
|
{
|
||||||
|
@ -196,7 +198,7 @@ namespace Oqtane.Controllers
|
||||||
new Permission(PermissionNames.View, RoleNames.Everyone, true),
|
new Permission(PermissionNames.View, RoleNames.Everyone, true),
|
||||||
new Permission(PermissionNames.Edit, newUser.UserId, true)
|
new Permission(PermissionNames.Edit, newUser.UserId, true)
|
||||||
}.EncodePermissions()
|
}.EncodePermissions()
|
||||||
});
|
}) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,6 +250,7 @@ namespace Oqtane.Infrastructure
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = ex.Message;
|
result.Message = ex.Message;
|
||||||
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -288,6 +289,7 @@ namespace Oqtane.Infrastructure
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = ex.Message;
|
result.Message = ex.Message;
|
||||||
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -328,6 +330,7 @@ namespace Oqtane.Infrastructure
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = ex.Message;
|
result.Message = ex.Message;
|
||||||
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -432,6 +435,7 @@ namespace Oqtane.Infrastructure
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = ex.Message;
|
result.Message = ex.Message;
|
||||||
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute any version specific upgrade logic
|
// execute any version specific upgrade logic
|
||||||
|
@ -539,6 +543,10 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
result.Success = true;
|
result.Success = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -548,6 +556,8 @@ namespace Oqtane.Infrastructure
|
||||||
var result = new Installation { Success = false, Message = string.Empty };
|
var result = new Installation { Success = false, Message = string.Empty };
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases) && !string.IsNullOrEmpty(install.SiteName))
|
if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases) && !string.IsNullOrEmpty(install.SiteName))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
using (var scope = _serviceScopeFactory.CreateScope())
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
|
@ -621,6 +631,8 @@ namespace Oqtane.Infrastructure
|
||||||
Type = FolderTypes.Private,
|
Type = FolderTypes.Private,
|
||||||
Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()),
|
Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()),
|
||||||
Order = 1,
|
Order = 1,
|
||||||
|
ImageSizes = "",
|
||||||
|
Capacity = Constants.UserFolderCapacity,
|
||||||
IsSystem = true,
|
IsSystem = true,
|
||||||
Permissions = new List<Permission>
|
Permissions = new List<Permission>
|
||||||
{
|
{
|
||||||
|
@ -634,7 +646,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
|
foreach (var aliasName in install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasName);
|
alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasName);
|
||||||
if (alias != null)
|
if (alias != null)
|
||||||
|
@ -651,8 +663,20 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.Message = "An Error Occurred Creating Site - " + ex.Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(result.Message))
|
||||||
|
{
|
||||||
result.Success = true;
|
result.Success = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace Oqtane.Infrastructure
|
||||||
var filepath = Path.Combine(folder, "error.log");
|
var filepath = Path.Combine(folder, "error.log");
|
||||||
|
|
||||||
// only retain an error log for the current day as it is intended for development purposes
|
// only retain an error log for the current day as it is intended for development purposes
|
||||||
if (File.GetCreationTime(filepath).ToUniversalTime().Date < DateTime.UtcNow.Date && File.Exists(filepath))
|
if (File.Exists(filepath) && File.GetLastWriteTimeUtc(filepath).Date < DateTime.UtcNow.Date)
|
||||||
{
|
{
|
||||||
File.Delete(filepath);
|
File.Delete(filepath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Databases.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.Tenant
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.03.00.01")]
|
||||||
|
public class AddFolderCapacity : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddFolderCapacity(IDatabase database) : base(database)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
folderEntityBuilder.AddIntegerColumn("Capacity", true);
|
||||||
|
folderEntityBuilder.UpdateColumn("Capacity", "0");
|
||||||
|
folderEntityBuilder.UpdateColumn("Capacity", Constants.UserFolderCapacity.ToString(), $"{ActiveDatabase.RewriteName("Name")} = 'My Folder'");
|
||||||
|
folderEntityBuilder.AddStringColumn("ImageSizes", 512, true, true);
|
||||||
|
|
||||||
|
var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
fileEntityBuilder.AddStringColumn("Description", 512, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
folderEntityBuilder.DropColumn("ImageSizes");
|
||||||
|
folderEntityBuilder.DropColumn("Capacity");
|
||||||
|
|
||||||
|
var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
fileEntityBuilder.DropColumn("Description");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -124,7 +124,7 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
Folder folder = _folderRepository.AddFolder(new Folder
|
Folder folder = _folderRepository.AddFolder(new Folder
|
||||||
{
|
{
|
||||||
SiteId = site.SiteId, ParentId = null, Name = "Root", Type = FolderTypes.Private, Path = "", Order = 1, IsSystem = true,
|
SiteId = site.SiteId, ParentId = null, Name = "Root", Type = FolderTypes.Private, Path = "", Order = 1, ImageSizes = "", Capacity = 0, IsSystem = true,
|
||||||
Permissions = new List<Permission>
|
Permissions = new List<Permission>
|
||||||
{
|
{
|
||||||
new Permission(PermissionNames.Browse, RoleNames.Admin, true),
|
new Permission(PermissionNames.Browse, RoleNames.Admin, true),
|
||||||
|
@ -132,7 +132,7 @@ namespace Oqtane.Repository
|
||||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
||||||
}.EncodePermissions()
|
}.EncodePermissions()
|
||||||
});
|
});
|
||||||
_folderRepository.AddFolder(new Folder { SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Public", Type = FolderTypes.Public, Path = Utilities.PathCombine("Public", Path.DirectorySeparatorChar.ToString()), Order = 1, IsSystem = false,
|
_folderRepository.AddFolder(new Folder { SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Public", Type = FolderTypes.Public, Path = Utilities.PathCombine("Public", Path.DirectorySeparatorChar.ToString()), Order = 1, ImageSizes = "", Capacity = 0, IsSystem = false,
|
||||||
Permissions = new List<Permission>
|
Permissions = new List<Permission>
|
||||||
{
|
{
|
||||||
new Permission(PermissionNames.Browse, RoleNames.Admin, true),
|
new Permission(PermissionNames.Browse, RoleNames.Admin, true),
|
||||||
|
@ -142,7 +142,7 @@ namespace Oqtane.Repository
|
||||||
});
|
});
|
||||||
_folderRepository.AddFolder(new Folder
|
_folderRepository.AddFolder(new Folder
|
||||||
{
|
{
|
||||||
SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Users", Type = FolderTypes.Private, Path = Utilities.PathCombine("Users",Path.DirectorySeparatorChar.ToString()), Order = 3, IsSystem = true,
|
SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Users", Type = FolderTypes.Private, Path = Utilities.PathCombine("Users",Path.DirectorySeparatorChar.ToString()), Order = 3, ImageSizes = "", Capacity = 0, IsSystem = true,
|
||||||
Permissions = new List<Permission>
|
Permissions = new List<Permission>
|
||||||
{
|
{
|
||||||
new Permission(PermissionNames.Browse, RoleNames.Admin, true),
|
new Permission(PermissionNames.Browse, RoleNames.Admin, true),
|
||||||
|
|
|
@ -333,7 +333,7 @@ Oqtane.Interop = {
|
||||||
|
|
||||||
var data = new FormData();
|
var data = new FormData();
|
||||||
data.append('folder', folder);
|
data.append('folder', folder);
|
||||||
data.append('file', Chunk, FileName);
|
data.append('formfile', Chunk, FileName);
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
request.open('POST', posturl, true);
|
request.open('POST', posturl, true);
|
||||||
request.upload.onloadstart = function (e) {
|
request.upload.onloadstart = function (e) {
|
||||||
|
|
|
@ -50,6 +50,11 @@ namespace Oqtane.Models
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ImageWidth { get; set; }
|
public int ImageWidth { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of a file
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
#region IAuditable Properties
|
#region IAuditable Properties
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
|
@ -45,7 +45,17 @@ namespace Oqtane.Models
|
||||||
public int Order { get; set; }
|
public int Order { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TODO: unclear what this is for
|
/// List of image sizes which can be generated dynamically from uploaded images (ie. 200x200,x200,200x)
|
||||||
|
/// </summary>
|
||||||
|
public string ImageSizes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum folder capacity (in bytes)
|
||||||
|
/// </summary>
|
||||||
|
public int Capacity { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Folder is a dependency of the framework and cannot be modified or removed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsSystem { get; set; }
|
public bool IsSystem { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -67,14 +67,28 @@ namespace Oqtane.Models
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Vulnerabilities { get; set; }
|
public int Vulnerabilities { get; set; }
|
||||||
|
|
||||||
|
#region Commercial Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The price of the package
|
/// The price of the package
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal Price { get; set; }
|
public decimal? Price { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Url for purchasing the package ( if commercial )
|
/// The Url for purchasing the package
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string PaymentUrl { get; set; }
|
public string PaymentUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The trial period in days
|
||||||
|
/// </summary>
|
||||||
|
public int TrialPeriod { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The expiry date of the package
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? ExpiryDate { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,5 +88,14 @@ namespace Oqtane.Models
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public bool IsAuthenticated { get; set; }
|
public bool IsAuthenticated { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path name of the user's personal folder
|
||||||
|
/// </summary>
|
||||||
|
[NotMapped]
|
||||||
|
public string FolderPath
|
||||||
|
{
|
||||||
|
get => "Users\\" + UserId.ToString() + "\\";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace Oqtane.Shared {
|
||||||
public const string DefaultSiteTemplate = "Oqtane.SiteTemplates.DefaultSiteTemplate, Oqtane.Server";
|
public const string DefaultSiteTemplate = "Oqtane.SiteTemplates.DefaultSiteTemplate, Oqtane.Server";
|
||||||
|
|
||||||
public const string ContentUrl = "/api/file/download/";
|
public const string ContentUrl = "/api/file/download/";
|
||||||
|
public const string ImageUrl = "/api/file/image/";
|
||||||
|
public const int UserFolderCapacity = 20; // megabytes
|
||||||
|
|
||||||
[Obsolete("Use UserNames.Host instead.")]
|
[Obsolete("Use UserNames.Host instead.")]
|
||||||
public const string HostUser = UserNames.Host;
|
public const string HostUser = UserNames.Host;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -60,13 +61,16 @@ namespace Oqtane.Shared
|
||||||
string urlparameters;
|
string urlparameters;
|
||||||
string querystring;
|
string querystring;
|
||||||
string anchor;
|
string anchor;
|
||||||
(urlparameters, querystring, anchor) = ParseParameters(parameters);
|
|
||||||
|
|
||||||
|
// parse parameters
|
||||||
|
(urlparameters, querystring, anchor) = ParseParameters(parameters);
|
||||||
if (!string.IsNullOrEmpty(urlparameters))
|
if (!string.IsNullOrEmpty(urlparameters))
|
||||||
{
|
{
|
||||||
if (urlparameters.StartsWith("/")) urlparameters = urlparameters.Remove(0, 1);
|
if (urlparameters.StartsWith("/")) urlparameters = urlparameters.Remove(0, 1);
|
||||||
path += $"/{Constants.UrlParametersDelimiter}/{urlparameters}";
|
path += $"/{Constants.UrlParametersDelimiter}/{urlparameters}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build url
|
||||||
var uriBuilder = new UriBuilder
|
var uriBuilder = new UriBuilder
|
||||||
{
|
{
|
||||||
Path = !string.IsNullOrEmpty(alias)
|
Path = !string.IsNullOrEmpty(alias)
|
||||||
|
@ -76,9 +80,9 @@ namespace Oqtane.Shared
|
||||||
: $"{path}",
|
: $"{path}",
|
||||||
Query = querystring,
|
Query = querystring,
|
||||||
};
|
};
|
||||||
|
|
||||||
anchor = string.IsNullOrEmpty(anchor) ? "" : "#" + anchor;
|
anchor = string.IsNullOrEmpty(anchor) ? "" : "#" + anchor;
|
||||||
var navigateUrl = uriBuilder.Uri.PathAndQuery + anchor;
|
return uriBuilder.Uri.PathAndQuery + anchor;
|
||||||
return navigateUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string EditUrl(string alias, string path, int moduleid, string action, string parameters)
|
public static string EditUrl(string alias, string path, int moduleid, string action, string parameters)
|
||||||
|
@ -108,6 +112,12 @@ namespace Oqtane.Shared
|
||||||
return $"{aliasUrl}{Constants.ContentUrl}{fileId}{method}";
|
return $"{aliasUrl}{Constants.ContentUrl}{fileId}{method}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ImageUrl(Alias alias, int fileId, string size, string mode)
|
||||||
|
{
|
||||||
|
var aliasUrl = (alias != null && !string.IsNullOrEmpty(alias.Path)) ? "/" + alias.Path : "";
|
||||||
|
return $"{aliasUrl}{Constants.ImageUrl}{fileId}/{size}/{mode}";
|
||||||
|
}
|
||||||
|
|
||||||
public static string TenantUrl(Alias alias, string url)
|
public static string TenantUrl(Alias alias, string url)
|
||||||
{
|
{
|
||||||
url = (!url.StartsWith("/")) ? "/" + url : url;
|
url = (!url.StartsWith("/")) ? "/" + url : url;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user