Compare commits
100 Commits
Author | SHA1 | Date | |
---|---|---|---|
6bcb769fe5 | |||
90110a653c | |||
3c561cc413 | |||
73f9622ba2 | |||
cf198ff781 | |||
648fc56495 | |||
ea6dc6b983 | |||
c0e8d09ce1 | |||
a471784cf3 | |||
1d2a4bf484 | |||
3fa620f3bc | |||
35f186b532 | |||
5cf35fd70a | |||
1eef08eaeb | |||
1750f28a9f | |||
41edbc5e22 | |||
04257f75e7 | |||
5fb602f733 | |||
94f0bdcce9 | |||
0ba24f9a3a | |||
aac7d6b97a | |||
bcc33af52b | |||
24fd42636a | |||
8d539d058c | |||
abda377f6f | |||
51bf822392 | |||
d3f135a9c7 | |||
07ba99cc41 | |||
336550c571 | |||
679cc04178 | |||
75fe4e7c89 | |||
410f8c74e5 | |||
05f67d6a2a | |||
3a6cde0e24 | |||
fe1de2b243 | |||
62a6b5f28a | |||
d648fa0f02 | |||
e706e8cf1f | |||
9eb8a7e65c | |||
11c610edf0 | |||
a65cdbd7ad | |||
97c56ba142 | |||
9fe72a1c98 | |||
7b40725534 | |||
5e1671afe3 | |||
50d74cbcee | |||
bc73e5e3d0 | |||
b02bdee8cb | |||
9db4985b14 | |||
6f281c256b | |||
807252c9e5 | |||
23e7f66188 | |||
57c500f4bc | |||
fe302aa9e4 | |||
f14f927df7 | |||
c3f74a5217 | |||
457d1bb563 | |||
25918056cb | |||
86517dd793 | |||
00ce083a2c | |||
bce262cd8e | |||
b5db62ef6a | |||
3703d87d50 | |||
f515def414 | |||
4bdf20822f | |||
49f4e64cb4 | |||
e615263706 | |||
2a7e256116 | |||
a083405b48 | |||
3ea280c82a | |||
192433f02d | |||
56a2e9dcea | |||
921cced1c8 | |||
b17f679f38 | |||
8e43fcab21 | |||
73c5092e46 | |||
56537e4785 | |||
3bd7d7196d | |||
7b5a192b82 | |||
d4be058d07 | |||
6c20fea46a | |||
2e7cfefb2e | |||
038894cf64 | |||
954e30d89f | |||
93d9c4534d | |||
468ca8c6a9 | |||
e7a4c08dea | |||
69d639ee42 | |||
a780569a6f | |||
568c283efd | |||
fccdd07a08 | |||
5e816ea912 | |||
cb2d529689 | |||
c5037e7084 | |||
fdc39d57fb | |||
4960e2c668 | |||
66cc3a1392 | |||
6e7c8e7b05 | |||
727b943fa3 | |||
a4a0334ec0 |
2
.deployment
Normal file
2
.deployment
Normal file
@ -0,0 +1,2 @@
|
||||
[config]
|
||||
project = Oqtane.Server/Oqtane.Server.csproj
|
@ -63,10 +63,18 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="retention-log" HelpText="What items do you want in the retention log">Retention Log (Items): </Label>
|
||||
<Label For="retention" HelpText="Number of log entries to retain for this job">Retention Log (Items): </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="retention-log" class="form-control" @bind="@_retentionHistory" />
|
||||
<input id="retention" class="form-control" @bind="@_retentionHistory" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="next" HelpText="Next execution for this job.">Next Execution: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="next" class="form-control" @bind="@_nextExecution" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -83,6 +91,7 @@
|
||||
private string _startDate = string.Empty;
|
||||
private string _endDate = string.Empty;
|
||||
private string _retentionHistory = string.Empty;
|
||||
private string _nextExecution = string.Empty;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
|
||||
@ -102,6 +111,7 @@
|
||||
_startDate = (job.StartDate != null) ? job.StartDate.ToString() : string.Empty;
|
||||
_endDate = (job.EndDate != null) ? job.EndDate.ToString() : string.Empty;
|
||||
_retentionHistory = job.RetentionHistory.ToString();
|
||||
_nextExecution = job.NextExecution.ToString();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -140,6 +150,15 @@
|
||||
job.EndDate = DateTime.Parse(_endDate);
|
||||
}
|
||||
|
||||
if (_nextExecution == string.Empty)
|
||||
{
|
||||
job.NextExecution = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
job.NextExecution = DateTime.Parse(_nextExecution);
|
||||
}
|
||||
|
||||
job.RetentionHistory = int.Parse(_retentionHistory);
|
||||
|
||||
try
|
||||
|
@ -22,7 +22,7 @@ else
|
||||
<td>@context.FinishDate</td>
|
||||
</Row>
|
||||
<Detail>
|
||||
<td colspan="4">@context.Notes</td>
|
||||
<td colspan="4">@((MarkupString)context.Notes)</td>
|
||||
</Detail>
|
||||
</Pager>
|
||||
}
|
||||
|
@ -79,7 +79,7 @@
|
||||
{
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -75,12 +75,20 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="license" HelpText="The license of the module">License: </Label>
|
||||
<Label For="license" HelpText="The module license terms">License: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="runtimes" HelpText="The Blazor runtimes which this module supports">Runtimes: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="runtimes" class="form-control" @bind="@_runtimes" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Section>
|
||||
</TabPanel>
|
||||
@ -110,6 +118,7 @@
|
||||
private string _url = "";
|
||||
private string _contact = "";
|
||||
private string _license = "";
|
||||
private string _runtimes = "";
|
||||
private string _permissions;
|
||||
private string _createdby;
|
||||
private DateTime _createdon;
|
||||
@ -139,6 +148,7 @@
|
||||
_url = moduleDefinition.Url;
|
||||
_contact = moduleDefinition.Contact;
|
||||
_license = moduleDefinition.License;
|
||||
_runtimes = moduleDefinition.Runtimes;
|
||||
_permissions = moduleDefinition.Permissions;
|
||||
_createdby = moduleDefinition.CreatedBy;
|
||||
_createdon = moduleDefinition.CreatedOn;
|
||||
|
@ -86,7 +86,7 @@ else
|
||||
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", moduledefinitionname, version);
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -102,7 +102,7 @@ else
|
||||
{
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -31,9 +31,15 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
await ModuleService.ImportModuleAsync(ModuleState.ModuleId, _content);
|
||||
StateHasChanged();
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
bool success = await ModuleService.ImportModuleAsync(ModuleState.ModuleId, _content);
|
||||
if (success)
|
||||
{
|
||||
AddModuleMessage("Content Imported Successfully", MessageType.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("A Problem Was Encountered Importing Content. Please Ensure The Content Is Formatted Correctly For The Module.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -162,17 +162,6 @@
|
||||
<input id="Icon" class="form-control" @bind="@_icon" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Default-Mode" HelpText="Select the default administration mode you want for this page">Default Mode? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Default-Mode" class="form-control" @bind="@_mode">
|
||||
<option value="view">View Mode</option>
|
||||
<option value="edit">Edit Mode</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content">Personalizable? </Label>
|
||||
@ -217,7 +206,6 @@
|
||||
private string _isnavigation = "True";
|
||||
private string _url;
|
||||
private string _ispersonalizable = "False";
|
||||
private string _mode = "view";
|
||||
private string _themetype = "-";
|
||||
private string _layouttype = "-";
|
||||
private string _containertype = "-";
|
||||
@ -346,6 +334,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
|
||||
{
|
||||
AddModuleMessage($"A page with path {_path} already exists for the selected parent page. The page path needs to be unique for the selected parent.", MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
Page child;
|
||||
switch (_insert)
|
||||
{
|
||||
@ -367,7 +361,6 @@
|
||||
|
||||
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
||||
page.Url = _url;
|
||||
page.EditMode = (_mode == "edit" ? true : false);
|
||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
@ -407,4 +400,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
private static bool PagePathIsUnique(string pagePath, int siteId, List<Page> existingPages)
|
||||
{
|
||||
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath);
|
||||
}
|
||||
}
|
||||
|
@ -173,17 +173,6 @@
|
||||
<input id="Icon" class="form-control" @bind="@_icon" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Default-Mode" HelpText="Select the default administration mode you want for this page">Default Mode? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Default-Mode" class="form-control" @bind="@_mode">
|
||||
<option value="view">View Mode</option>
|
||||
<option value="edit">Edit Mode</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content">Personalizable? </Label>
|
||||
@ -235,7 +224,6 @@
|
||||
private string _isnavigation;
|
||||
private string _url;
|
||||
private string _ispersonalizable;
|
||||
private string _mode;
|
||||
private string _themetype = "-";
|
||||
private string _layouttype = "-";
|
||||
private string _containertype = "-";
|
||||
@ -290,7 +278,6 @@
|
||||
_isnavigation = page.IsNavigation.ToString();
|
||||
_url = page.Url;
|
||||
_ispersonalizable = page.IsPersonalizable.ToString();
|
||||
_mode = (page.EditMode) ? "edit" : "view";
|
||||
_themetype = page.ThemeType;
|
||||
if (_themetype == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
@ -333,7 +320,7 @@
|
||||
_children = new List<Page>();
|
||||
if (_parentid == "-1")
|
||||
{
|
||||
foreach(Page p in PageState.Pages.Where(item => item.ParentId == null))
|
||||
foreach (Page p in PageState.Pages.Where(item => item.ParentId == null))
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
|
||||
{
|
||||
@ -433,6 +420,13 @@
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList))
|
||||
{
|
||||
AddModuleMessage($"A page with path {_path} already exists for the selected parent page. The page path needs to be unique for the selected parent.", MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_insert != "=")
|
||||
{
|
||||
Page child;
|
||||
@ -456,7 +450,6 @@
|
||||
}
|
||||
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
|
||||
page.Url = _url;
|
||||
page.EditMode = (_mode == "edit");
|
||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
@ -512,4 +505,9 @@
|
||||
AddModuleMessage("Error Saving Page", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool PagePathIsUnique(string pagePath, int siteId, int pageId, List<Page> existingPages)
|
||||
{
|
||||
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath && page.PageId != pageId);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
@inject IThemeService ThemeService
|
||||
@inject ISettingService SettingService
|
||||
|
||||
@if (_themes != null)
|
||||
@if (_initialized)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
@ -211,6 +211,7 @@
|
||||
}
|
||||
|
||||
@code {
|
||||
private bool _initialized = false;
|
||||
private List<Theme> _themeList;
|
||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||
private List<ThemeControl> _layouts = new List<ThemeControl>();
|
||||
@ -318,6 +319,8 @@
|
||||
_deletedby = site.DeletedBy;
|
||||
_deletedon = site.DeletedOn;
|
||||
_isdeleted = site.IsDeleted.ToString();
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -6,7 +6,7 @@
|
||||
@inject IAliasService AliasService
|
||||
@inject IThemeService ThemeService
|
||||
|
||||
@if (_themes != null)
|
||||
@if (_initialized)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
@ -106,6 +106,7 @@
|
||||
}
|
||||
|
||||
@code {
|
||||
private bool _initialized = false;
|
||||
private List<Theme> _themeList;
|
||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||
private List<ThemeControl> _layouts = new List<ThemeControl>();
|
||||
@ -163,6 +164,8 @@
|
||||
_deletedby = site.DeletedBy;
|
||||
_deletedon = site.DeletedOn;
|
||||
_isdeleted = site.IsDeleted.ToString();
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -79,7 +79,7 @@
|
||||
{
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await ThemeService.InstallThemesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -87,7 +87,7 @@ else
|
||||
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", themename, version);
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await ThemeService.InstallThemesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -103,7 +103,7 @@ else
|
||||
{
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -12,7 +12,7 @@
|
||||
@if (_upgradeavailable)
|
||||
{
|
||||
<ModuleMessage Type="MessageType.Info" Message="Select The Upgrade Button To Install a New Framework Version"></ModuleMessage>
|
||||
@("Framework") @_package.Version <button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, Constants.Version))>Upgrade</button>
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, @_package.Version))>Upgrade To @_package.Version</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -26,7 +26,7 @@
|
||||
<Label HelpText="Upload a framework package and select Install to complete the installation">Framework: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager Filter="nupkg" Folder="Framework" />
|
||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Framework" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -71,7 +71,7 @@
|
||||
{
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await InstallationService.Upgrade();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -88,7 +88,7 @@
|
||||
await PackageService.DownloadPackageAsync(packageid, version, "Framework");
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await InstallationService.Upgrade();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -1,6 +1,6 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
|
||||
@if (_visible)
|
||||
{
|
||||
<div class="app-admin-modal">
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
@code {
|
||||
private bool _visible = false;
|
||||
private bool _editmode = true;
|
||||
private bool _editmode = false;
|
||||
private bool _authorized = false;
|
||||
private string _iconSpan = string.Empty;
|
||||
|
||||
@ -66,7 +66,7 @@
|
||||
public bool Disabled { get; set; } // optional
|
||||
|
||||
[Parameter]
|
||||
public string EditMode { get; set; } // optional - specifies if a user must be in edit mode to see the action - default is true
|
||||
public string EditMode { get; set; } // optional - specifies if an authorized user must be in edit mode to see the action - default is false
|
||||
|
||||
[Parameter]
|
||||
public Action OnClick { get; set; } // required if an Action is specified - executes a method in the calling component
|
||||
@ -84,6 +84,7 @@
|
||||
{
|
||||
Class = "btn btn-success";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(EditMode))
|
||||
{
|
||||
_editmode = bool.Parse(EditMode);
|
||||
|
@ -1,6 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
@inject IUserService UserService
|
||||
|
||||
@if (_authorized)
|
||||
@ -21,7 +20,7 @@
|
||||
private string _parameters = string.Empty;
|
||||
private string _classname = "btn btn-primary";
|
||||
private string _style = string.Empty;
|
||||
private bool _editmode = true;
|
||||
private bool _editmode = false;
|
||||
private bool _authorized = false;
|
||||
private string _iconSpan = string.Empty;
|
||||
|
||||
@ -47,11 +46,11 @@
|
||||
public bool Disabled { get; set; } // optional
|
||||
|
||||
[Parameter]
|
||||
public string EditMode { get; set; } // optional - specifies if a user must be in edit mode to see the action - default is true
|
||||
public string EditMode { get; set; } // optional - specifies if an authorized user must be in edit mode to see the action - default is false.
|
||||
|
||||
[Parameter]
|
||||
public string IconName { get; set; } // optional - specifies an icon for the link - default is no icon
|
||||
|
||||
|
||||
[Parameter]
|
||||
public bool IconOnly { get; set; } // optional - specifies only icon in link
|
||||
|
||||
@ -90,8 +89,8 @@
|
||||
|
||||
if (!string.IsNullOrEmpty(IconName))
|
||||
{
|
||||
_iconSpan = $"<span class=\"oi oi-{IconName}\"></span>{(IconOnly?"":" ")}";
|
||||
|
||||
_iconSpan = $"<span class=\"oi oi-{IconName}\"></span>{(IconOnly ? "" : " ")}";
|
||||
|
||||
}
|
||||
|
||||
_url = EditUrl(Action, _parameters);
|
||||
@ -123,7 +122,7 @@
|
||||
{
|
||||
security = Security.Value;
|
||||
}
|
||||
|
||||
|
||||
switch (security)
|
||||
{
|
||||
case SecurityAccessLevel.Anonymous:
|
||||
@ -143,7 +142,7 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return authorized;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
|
||||
@if (_text != string.Empty)
|
||||
{
|
||||
@ -8,7 +7,7 @@
|
||||
}
|
||||
|
||||
@code {
|
||||
|
||||
|
||||
private string _text = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
@ -22,7 +21,7 @@
|
||||
|
||||
[Parameter]
|
||||
public DateTime ModifiedOn { get; set; }
|
||||
|
||||
|
||||
[Parameter]
|
||||
public string DeletedBy { get; set; }
|
||||
|
||||
@ -41,51 +40,51 @@
|
||||
if (!String.IsNullOrEmpty(CreatedBy) || CreatedOn != null)
|
||||
{
|
||||
_text += "<p style=\"" + Style + "\">Created ";
|
||||
|
||||
|
||||
if (!String.IsNullOrEmpty(CreatedBy))
|
||||
{
|
||||
_text += " by <b>" + CreatedBy + "</b>";
|
||||
}
|
||||
|
||||
|
||||
if (CreatedOn != null)
|
||||
{
|
||||
_text += " on <b>" + CreatedOn.ToString("MMM dd yyyy HH:mm:ss") + "</b>";
|
||||
}
|
||||
|
||||
|
||||
_text += "</p>";
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(ModifiedBy) || ModifiedOn != null)
|
||||
{
|
||||
_text += "<p style=\"" + Style + "\">Last modified ";
|
||||
|
||||
|
||||
if (!String.IsNullOrEmpty(ModifiedBy))
|
||||
{
|
||||
_text += " by <b>" + ModifiedBy + "</b>";
|
||||
}
|
||||
|
||||
|
||||
if (ModifiedOn != null)
|
||||
{
|
||||
_text += " on <b>" + ModifiedOn.ToString("MMM dd yyyy HH:mm:ss") + "</b>";
|
||||
}
|
||||
|
||||
|
||||
_text += "</p>";
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(DeletedBy) || DeletedOn.HasValue)
|
||||
{
|
||||
_text += "<p style=\"" + Style + "\">Deleted ";
|
||||
|
||||
|
||||
if (!String.IsNullOrEmpty(DeletedBy))
|
||||
{
|
||||
_text += " by <b>" + DeletedBy + "</b>";
|
||||
}
|
||||
|
||||
|
||||
if (DeletedOn != null)
|
||||
{
|
||||
_text += " on <b>" + DeletedOn.Value.ToString("MMM dd yyyy HH:mm:ss") + "</b>";
|
||||
}
|
||||
|
||||
|
||||
_text += "</p>";
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
@inject IFolderService FolderService
|
||||
@inject IFileService FileService
|
||||
|
||||
@ -56,16 +54,16 @@
|
||||
<div>
|
||||
@if (UploadMultiple)
|
||||
{
|
||||
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple/>
|
||||
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="file" id="@_fileinputid" name="file" accept="@_filter"/>
|
||||
<input type="file" id="@_fileinputid" name="file" accept="@_filter" />
|
||||
}
|
||||
<span id="@_progressinfoid"></span><progress id="@_progressbarid" style="width: 150px; visibility: hidden;"></progress>
|
||||
<span class="float-right">
|
||||
<button type="button" class="btn btn-success" @onclick="UploadFile">Upload</button>
|
||||
@if (_showfiles && GetFileId() != -1)
|
||||
@if (ShowFiles && GetFileId() != -1)
|
||||
{
|
||||
<button type="button" class="btn btn-danger" @onclick="DeleteFile">Delete</button>
|
||||
}
|
||||
@ -88,7 +86,6 @@
|
||||
private string _id;
|
||||
private List<Folder> _folders;
|
||||
private List<File> _files = new List<File>();
|
||||
private bool _showfiles = true;
|
||||
private string _fileinputid = string.Empty;
|
||||
private string _progressinfoid = string.Empty;
|
||||
private string _progressbarid = string.Empty;
|
||||
@ -134,7 +131,7 @@
|
||||
|
||||
if (!string.IsNullOrEmpty(Folder))
|
||||
{
|
||||
_folders = new List<Folder> {new Folder {FolderId = -1, Name = Folder}};
|
||||
_folders = new List<Folder> { new Folder { FolderId = -1, Name = Folder } };
|
||||
FolderId = -1;
|
||||
}
|
||||
else
|
||||
@ -163,7 +160,7 @@
|
||||
|
||||
await GetFiles();
|
||||
|
||||
// create unique id for component
|
||||
// create unique id for component
|
||||
_guid = Guid.NewGuid().ToString("N");
|
||||
_fileinputid = _guid + "FileInput";
|
||||
_progressinfoid = _guid + "ProgressInfo";
|
||||
@ -211,7 +208,7 @@
|
||||
_message = string.Empty;
|
||||
try
|
||||
{
|
||||
FolderId = int.Parse((string) e.Value);
|
||||
FolderId = int.Parse((string)e.Value);
|
||||
await GetFiles();
|
||||
FileId = -1;
|
||||
_image = string.Empty;
|
||||
@ -227,7 +224,7 @@
|
||||
private async Task FileChanged(ChangeEventArgs e)
|
||||
{
|
||||
_message = string.Empty;
|
||||
FileId = int.Parse((string) e.Value);
|
||||
FileId = int.Parse((string)e.Value);
|
||||
|
||||
await SetImage();
|
||||
StateHasChanged();
|
||||
@ -244,8 +241,8 @@
|
||||
var maxwidth = 200;
|
||||
var maxheight = 200;
|
||||
|
||||
var ratioX = (double) maxwidth / (double) file.ImageWidth;
|
||||
var ratioY = (double) maxheight / (double) file.ImageHeight;
|
||||
var ratioX = (double)maxwidth / (double)file.ImageWidth;
|
||||
var ratioY = (double)maxheight / (double)file.ImageHeight;
|
||||
var ratio = ratioX < ratioY ? ratioX : ratioY;
|
||||
|
||||
_image = "<img src=\"" + ContentUrl(FileId) + "\" alt=\"" + file.Name +
|
||||
|
@ -1,6 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
|
||||
@if (!string.IsNullOrEmpty(HelpText))
|
||||
{
|
||||
@ -16,7 +15,7 @@ else
|
||||
private string _closeLabel = "</label>";
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string For { get; set; } // optional - the id of the associated input control for accessibility
|
||||
@ -34,12 +33,12 @@ else
|
||||
{
|
||||
_openLabel += " for=\"" + For + "\"";
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(Class))
|
||||
{
|
||||
_openLabel += " class=\"" + Class + "\"";
|
||||
}
|
||||
|
||||
|
||||
_openLabel += ">";
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,16 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@if (!string.IsNullOrEmpty(_message))
|
||||
{
|
||||
<div class="@_classname" role="alert">@_message</div>
|
||||
<div class="@_classname" role="alert">
|
||||
@_message
|
||||
@if (Type == MessageType.Error && UserSecurity.IsAuthorized(PageState.User, Constants.HostRole))
|
||||
{
|
||||
@((MarkupString)" ")<NavLink href="@NavigateUrl("admin/log")">View Details</NavLink>
|
||||
}
|
||||
</div>
|
||||
<br />
|
||||
}
|
||||
|
||||
@ -52,7 +58,7 @@
|
||||
classname = "alert alert-danger";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return classname;
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +1,39 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@typeparam TableItem
|
||||
|
||||
@inherits ModuleControlBase
|
||||
@typeparam TableItem
|
||||
|
||||
<p>
|
||||
@if(Format == "Table")
|
||||
@if (Format == "Table")
|
||||
{
|
||||
<table class="@Class">
|
||||
<thead>
|
||||
<tr>@Header</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<table class="@Class">
|
||||
<thead>
|
||||
<tr>@Header</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in ItemList)
|
||||
{
|
||||
<tr>@Row(item)</tr>
|
||||
@if (Detail != null)
|
||||
{
|
||||
<tr>@Detail(item)</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
@if (Format == "Grid")
|
||||
{
|
||||
<div class="@Class">
|
||||
<div class="row">@Header</div>
|
||||
@foreach (var item in ItemList)
|
||||
{
|
||||
<tr>@Row(item)</tr>
|
||||
<div class="row">@Row(item)</div>
|
||||
@if (Detail != null)
|
||||
{
|
||||
<tr>@Detail(item)</tr>
|
||||
<div class="row">@Detail(item)</div>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
@if(Format == "Grid")
|
||||
{
|
||||
<div class="@Class">
|
||||
<div class="row">@Header</div>
|
||||
@foreach (var item in ItemList)
|
||||
{
|
||||
<div class="row">@Row(item)</div>
|
||||
@if (Detail != null)
|
||||
{
|
||||
<div class="row">@Detail(item)</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="mx-auto text-center">
|
||||
@if (_page > _maxPages)
|
||||
@ -44,7 +42,7 @@
|
||||
}
|
||||
@if (_endPage > 1)
|
||||
{
|
||||
<button class="btn btn-secondary" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
|
||||
<button class="btn btn-secondary" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
|
||||
@for (int i = _startPage; i <= _endPage; i++)
|
||||
{
|
||||
var pager = i;
|
||||
@ -105,7 +103,7 @@
|
||||
{
|
||||
Format = "Table";
|
||||
}
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(Class))
|
||||
{
|
||||
if (Format == "Table")
|
||||
@ -117,7 +115,7 @@
|
||||
Class = "container";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(PageSize))
|
||||
{
|
||||
_maxItems = 10;
|
||||
@ -126,7 +124,7 @@
|
||||
{
|
||||
_maxItems = int.Parse(PageSize);
|
||||
}
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(DisplayPages))
|
||||
{
|
||||
_maxPages = 5;
|
||||
@ -149,7 +147,7 @@
|
||||
{
|
||||
ItemList = Items.Skip((currentPage - 1) * _maxItems).Take(_maxItems);
|
||||
_page = currentPage;
|
||||
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
@ -174,7 +172,7 @@
|
||||
{
|
||||
_endPage = _pages;
|
||||
}
|
||||
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
else if (direction == "back")
|
||||
@ -208,7 +206,7 @@
|
||||
_page -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UpdateList(_page);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
@inject IRoleService RoleService
|
||||
@inject IUserService UserService
|
||||
|
||||
@ -39,7 +38,7 @@
|
||||
<th scope="col">User</th>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
<th style="text-align: center; width: 1px;">@permission.PermissionName</th>
|
||||
<th style="text-align: center; width: 1px;">@permission.PermissionName</th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
@ -48,7 +47,7 @@
|
||||
{
|
||||
string userid = "[" + user.UserId.ToString() + "]";
|
||||
<tr>
|
||||
<td >@user.DisplayName</td>
|
||||
<td>@user.DisplayName</td>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
var p = permission;
|
||||
@ -107,13 +106,13 @@
|
||||
_roles.Insert(0, new Role { Name = Constants.AllUsersRole });
|
||||
|
||||
_permissions = new List<PermissionString>();
|
||||
|
||||
|
||||
foreach (string permissionname in _permissionnames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
// initialize with admin role
|
||||
_permissions.Add(new PermissionString { PermissionName = permissionname, Permissions = Constants.AdminRole });
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(Permissions))
|
||||
{
|
||||
// populate permissions
|
||||
@ -123,7 +122,7 @@
|
||||
{
|
||||
_permissions[_permissions.FindIndex(item => item.PermissionName == permissionstring.PermissionName)].Permissions = permissionstring.Permissions;
|
||||
}
|
||||
|
||||
|
||||
if (permissionstring.Permissions.Contains("["))
|
||||
{
|
||||
foreach (string user in permissionstring.Permissions.Split(new char[] { '[' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
@ -183,7 +182,7 @@
|
||||
_message = "Username Does Not Exist";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_username = string.Empty;
|
||||
}
|
||||
|
||||
@ -209,7 +208,7 @@
|
||||
case null:
|
||||
break; // permission not specified
|
||||
}
|
||||
|
||||
|
||||
_permissions[_permissions.FindIndex(item => item.PermissionName == permissionName)].Permissions = string.Join(";", ids.ToArray());
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
|
||||
<div class="row" style="margin-bottom: 50px;">
|
||||
<div class="col">
|
||||
@ -108,12 +107,12 @@
|
||||
public string DebugLevel { get; set; } = "info";
|
||||
|
||||
public override List<Resource> Resources => new List<Resource>()
|
||||
{
|
||||
{
|
||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill1.3.6.min.js" },
|
||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" },
|
||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" }
|
||||
};
|
||||
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_content = Content; // raw HTML
|
||||
|
@ -1,6 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
|
@ -1,6 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
|
||||
@if (Name == Parent.ActiveTab)
|
||||
{
|
||||
|
@ -1,6 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@attribute [OqtaneIgnore]
|
||||
@inherits ModuleControlBase
|
||||
|
||||
<CascadingValue Value="this">
|
||||
<div class="container-fluid">
|
||||
|
@ -1,4 +1,5 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleControlBase
|
||||
|
||||
<img src="@_src" title="@_title" @onclick="SetValue" />
|
||||
|
||||
@ -38,7 +39,7 @@
|
||||
_value = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
SetImage();
|
||||
OnChange(_value);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
@if (PageState.EditMode)
|
||||
{
|
||||
<br /><ActionLink Action="Edit" /><br /><br />
|
||||
<br /><ActionLink Action="Edit" EditMode="true" /><br /><br />
|
||||
}
|
||||
|
||||
@code {
|
||||
|
@ -21,23 +21,23 @@ namespace Oqtane.Modules.HtmlText.Services
|
||||
|
||||
public async Task<HtmlTextInfo> GetHtmlTextAsync(int moduleId)
|
||||
{
|
||||
var htmltext = await GetJsonAsync<List<HtmlTextInfo>>($"{ApiUrl}/{moduleId}?entityid={moduleId}");
|
||||
var htmltext = await GetJsonAsync<List<HtmlTextInfo>>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
|
||||
return htmltext.FirstOrDefault();
|
||||
}
|
||||
|
||||
public async Task AddHtmlTextAsync(HtmlTextInfo htmlText)
|
||||
{
|
||||
await PostJsonAsync($"{ApiUrl}?entityid={htmlText.ModuleId}", htmlText);
|
||||
await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", htmlText.ModuleId), htmlText);
|
||||
}
|
||||
|
||||
public async Task UpdateHtmlTextAsync(HtmlTextInfo htmlText)
|
||||
{
|
||||
await PutJsonAsync($"{ApiUrl}/{htmlText.HtmlTextId}?entityid={htmlText.ModuleId}", htmlText);
|
||||
await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", htmlText.ModuleId), htmlText);
|
||||
}
|
||||
|
||||
public async Task DeleteHtmlTextAsync(int moduleId)
|
||||
{
|
||||
await DeleteAsync($"{ApiUrl}/{moduleId}?entityid={moduleId}");
|
||||
await DeleteAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace Oqtane.Modules
|
||||
private Logger _logger;
|
||||
|
||||
protected Logger logger => _logger ?? (_logger = new Logger(this));
|
||||
|
||||
|
||||
[Inject]
|
||||
protected ILogService LoggingService { get; set; }
|
||||
|
||||
@ -30,7 +30,7 @@ namespace Oqtane.Modules
|
||||
[CascadingParameter]
|
||||
protected Module ModuleState { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
[CascadingParameter]
|
||||
protected ModuleInstance ModuleInstance { get; set; }
|
||||
|
||||
// optional interface properties
|
||||
@ -62,7 +62,7 @@ namespace Oqtane.Modules
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// path method
|
||||
|
||||
public string ModulePath()
|
||||
@ -116,6 +116,54 @@ namespace Oqtane.Modules
|
||||
return Utilities.ContentUrl(PageState.Alias, fileid);
|
||||
}
|
||||
|
||||
public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "")
|
||||
{
|
||||
var urlParameters = new Dictionary<string, string>();
|
||||
string[] templateSegments;
|
||||
var parameters = PageState.UrlParameters.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||
var parameterId = 0;
|
||||
|
||||
if (string.IsNullOrEmpty(parametersTemplate))
|
||||
{
|
||||
for (int i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
urlParameters.TryAdd("parameter" + i, parameters[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
templateSegments = parametersTemplate.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (parameters.Length == templateSegments.Length)
|
||||
{
|
||||
for (int i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
if (parameters.Length > i)
|
||||
{
|
||||
if (templateSegments[i] == parameters[i])
|
||||
{
|
||||
urlParameters.TryAdd("parameter" + parameterId, parameters[i]);
|
||||
parameterId++;
|
||||
}
|
||||
else if (templateSegments[i].StartsWith("{") && templateSegments[i].EndsWith("}"))
|
||||
{
|
||||
var key = templateSegments[i].Replace("{", "");
|
||||
key = key.Replace("}", "");
|
||||
urlParameters.TryAdd(key, parameters[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = parameters.Length;
|
||||
urlParameters.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return urlParameters;
|
||||
}
|
||||
|
||||
// user feedback methods
|
||||
public void AddModuleMessage(string message, MessageType type)
|
||||
{
|
||||
@ -154,12 +202,15 @@ namespace Oqtane.Modules
|
||||
case "add":
|
||||
logFunction = LogFunction.Create;
|
||||
break;
|
||||
|
||||
case "edit":
|
||||
logFunction = LogFunction.Update;
|
||||
break;
|
||||
|
||||
case "delete":
|
||||
logFunction = LogFunction.Delete;
|
||||
break;
|
||||
|
||||
default:
|
||||
logFunction = LogFunction.Read;
|
||||
break;
|
||||
@ -241,4 +292,4 @@ namespace Oqtane.Modules
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
10
Oqtane.Client/Modules/ModuleControlBase.cs
Normal file
10
Oqtane.Client/Modules/ModuleControlBase.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Modules
|
||||
{
|
||||
[OqtaneIgnore]
|
||||
public abstract class ModuleControlBase : ModuleBase
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -15,7 +15,7 @@
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
@ -170,6 +170,19 @@ namespace Oqtane.Services
|
||||
// can be used to override the default alias
|
||||
public Alias Alias { get; set; }
|
||||
|
||||
// add entityid parameter to url for custom authorization policy
|
||||
public string CreateAuthorizationPolicyUrl(string url, int entityId)
|
||||
{
|
||||
if (url.Contains("?"))
|
||||
{
|
||||
return url + "&entityid=" + entityId.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return url + "?entityid=" + entityId.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("This method is obsolete. Use CreateApiUrl(Alias alias, string serviceName) instead.", false)]
|
||||
public string CreateApiUrl(Alias alias, string absoluteUri, string serviceName)
|
||||
{
|
||||
|
@ -127,7 +127,10 @@
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.Permissions))
|
||||
{
|
||||
<option value="@moduledefinition.ModuleDefinitionName">@moduledefinition.Name</option>
|
||||
if (moduledefinition.Runtimes == "" || moduledefinition.Runtimes.Contains(PageState.Runtime.ToString()))
|
||||
{
|
||||
<option value="@moduledefinition.ModuleDefinitionName">@moduledefinition.Name</option>
|
||||
}
|
||||
}
|
||||
}
|
||||
</select>
|
||||
@ -196,26 +199,17 @@
|
||||
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) || (PageState.Page.IsPersonalizable && PageState.User != null))
|
||||
{
|
||||
@if (PageState.Page.EditMode)
|
||||
if (PageState.EditMode)
|
||||
{
|
||||
<button type="button" class="btn @ButtonClass active" aria-pressed="true" autocomplete="off">
|
||||
<button type="button" class="btn @ButtonClass active" data-toggle="button" aria-pressed="true" autocomplete="off" @onclick="(async () => await ToggleEditMode(PageState.EditMode))">
|
||||
<span class="oi oi-pencil"></span>
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PageState.EditMode)
|
||||
{
|
||||
<button type="button" class="btn @ButtonClass active" data-toggle="button" aria-pressed="true" autocomplete="off" @onclick="(async () => await ToggleEditMode(PageState.EditMode))">
|
||||
<span class="oi oi-pencil"></span>
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn @ButtonClass" data-toggle="button" aria-pressed="false" autocomplete="off" @onclick="(async () => await ToggleEditMode(PageState.EditMode))">
|
||||
<span class="oi oi-pencil"></span>
|
||||
</button>
|
||||
}
|
||||
<button type="button" class="btn @ButtonClass" data-toggle="button" aria-pressed="false" autocomplete="off" @onclick="(async () => await ToggleEditMode(PageState.EditMode))">
|
||||
<span class="oi oi-pencil"></span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
@inherits ModuleActionsBase
|
||||
@attribute [OqtaneIgnore]
|
||||
|
||||
@if (PageState.EditMode && !PageState.Page.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions))
|
||||
@if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions))
|
||||
{
|
||||
<div class="app-moduleactions">
|
||||
<a class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a>
|
||||
@ -15,9 +15,20 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">@action.Name</a>
|
||||
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">
|
||||
@if (string.IsNullOrEmpty(action.Icon))
|
||||
{
|
||||
@((MarkupString) " ");
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="oi oi-@action.Icon" aria-hidden="true"></span>
|
||||
}
|
||||
|
||||
@action.Name
|
||||
</a>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace Oqtane.Themes.Controls
|
||||
[Inject] public IPageModuleService PageModuleService { get; set; }
|
||||
[Inject] public IModuleService ModuleService { get; set; }
|
||||
|
||||
protected List<ActionViewModel> Actions;
|
||||
public List<ActionViewModel> Actions;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
@ -31,51 +31,52 @@ namespace Oqtane.Themes.Controls
|
||||
var actionList = new List<ActionViewModel>();
|
||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)});
|
||||
actionList.Add(new ActionViewModel {Icon = Icons.Cog, Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)});
|
||||
|
||||
if (UserSecurity.GetPermissionStrings(ModuleState.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(Constants.AllUsersRole))
|
||||
{
|
||||
actionList.Add(new ActionViewModel { Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) });
|
||||
actionList.Add(new ActionViewModel {Icon=Icons.CircleX, Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) });
|
||||
}
|
||||
else
|
||||
{
|
||||
actionList.Add(new ActionViewModel { Name = "Publish Module", Action = async (s, m) => await Publish(s, m) });
|
||||
actionList.Add(new ActionViewModel {Icon=Icons.CircleCheck, Name = "Publish Module", Action = async (s, m) => await Publish(s, m) });
|
||||
}
|
||||
actionList.Add(new ActionViewModel { Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) });
|
||||
actionList.Add(new ActionViewModel {Icon=Icons.Trash, Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) });
|
||||
|
||||
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
|
||||
{
|
||||
actionList.Add(new ActionViewModel { Name = "" });
|
||||
actionList.Add(new ActionViewModel {Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")});
|
||||
actionList.Add(new ActionViewModel {Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")});
|
||||
actionList.Add(new ActionViewModel {Icon=Icons.CloudUpload, Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")});
|
||||
actionList.Add(new ActionViewModel {Icon = Icons.CloudDownload, Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")});
|
||||
}
|
||||
|
||||
actionList.Add(new ActionViewModel {Name = ""});
|
||||
|
||||
if (ModuleState.PaneModuleIndex > 0)
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m)});
|
||||
actionList.Add(new ActionViewModel {Icon = Icons.DataTransferUpload ,Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m)});
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex > 0)
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move Up", Action = async (s, m) => await MoveUp(s, m)});
|
||||
actionList.Add(new ActionViewModel {Icon = Icons.ArrowThickTop, Name = "Move Up", Action = async (s, m) => await MoveUp(s, m)});
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move Down", Action = async (s, m) => await MoveDown(s, m)});
|
||||
actionList.Add(new ActionViewModel {Icon = Icons.ArrowThickBottom, Name = "Move Down", Action = async (s, m) => await MoveDown(s, m)});
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
|
||||
actionList.Add(new ActionViewModel {Icon = Icons.DataTransferDownload, Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
|
||||
}
|
||||
|
||||
foreach (string pane in PageState.Page.Panes)
|
||||
{
|
||||
if (pane != ModuleState.Pane)
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move To " + pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)});
|
||||
actionList.Add(new ActionViewModel {Icon = Icons.AccountLogin, Name = "Move To " + pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,8 +203,8 @@ namespace Oqtane.Themes.Controls
|
||||
|
||||
public class ActionViewModel
|
||||
{
|
||||
public string Icon { get; set; }
|
||||
public string Name { set; get; }
|
||||
|
||||
public Func<string, PageModule, Task<string>> Action { set; get; }
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
{
|
||||
_moduleState = Module; // passed in from Pane component
|
||||
string container = _moduleState.ContainerType;
|
||||
if (PageState.ModuleId != -1 && PageState.Action != "" && _moduleState.UseAdminContainer)
|
||||
if (PageState.ModuleId != -1 && _moduleState.UseAdminContainer)
|
||||
{
|
||||
container = Constants.DefaultAdminContainer;
|
||||
}
|
||||
|
@ -14,10 +14,11 @@ namespace Oqtane.UI
|
||||
public List<Module> Modules { get; set; }
|
||||
public Uri Uri { get; set; }
|
||||
public Dictionary<string, string> QueryString { get; set; }
|
||||
public string UrlParameters { get; set; }
|
||||
public int ModuleId { get; set; }
|
||||
public string Action { get; set; }
|
||||
public bool EditMode { get; set; }
|
||||
public DateTime LastSyncDate { get; set; }
|
||||
public Runtime Runtime { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
@namespace Oqtane.UI
|
||||
@using Microsoft.AspNetCore.Components.Rendering
|
||||
@namespace Oqtane.UI
|
||||
@inject IUserService UserService
|
||||
@inject IModuleService ModuleService
|
||||
@inject IModuleDefinitionService ModuleDefinitionService
|
||||
@ -25,7 +26,7 @@
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if (PageState.EditMode && !PageState.Page.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions) && Name != Constants.AdminPane)
|
||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions) && Name != Constants.AdminPane)
|
||||
{
|
||||
_paneadminborder = "app-pane-admin-border";
|
||||
_panetitle = "<div class=\"app-pane-admin-title\">" + Name + " Pane</div>";
|
||||
@ -38,12 +39,12 @@
|
||||
|
||||
DynamicComponent = builder =>
|
||||
{
|
||||
if (PageState.ModuleId != -1 && PageState.Action != "")
|
||||
if (PageState.ModuleId != -1 && PageState.Action != Constants.DefaultAction)
|
||||
{
|
||||
if (Name.ToLower() == Constants.AdminPane.ToLower())
|
||||
{
|
||||
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
|
||||
if (module != null)
|
||||
if (module != null && !module.IsDeleted)
|
||||
{
|
||||
var typename = module.ModuleType;
|
||||
// check for core module actions component
|
||||
@ -51,7 +52,7 @@
|
||||
{
|
||||
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, PageState.Action);
|
||||
}
|
||||
|
||||
|
||||
var moduleType = Type.GetType(typename);
|
||||
if (moduleType != null)
|
||||
{
|
||||
@ -88,10 +89,7 @@
|
||||
{
|
||||
module.Title = module.ControlTitle;
|
||||
}
|
||||
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
builder.CloseComponent();
|
||||
CreateComponent(builder, module);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -106,14 +104,12 @@
|
||||
if (PageState.ModuleId != -1)
|
||||
{
|
||||
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
|
||||
if (module != null && module.Pane.ToLower() == Name.ToLower())
|
||||
if (module != null && module.Pane.ToLower() == Name.ToLower() && !module.IsDeleted)
|
||||
{
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions))
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
builder.CloseComponent();
|
||||
CreateComponent(builder, module);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,14 +120,19 @@
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions))
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
builder.SetKey(module.PageModuleId);
|
||||
builder.CloseComponent();
|
||||
CreateComponent(builder, module);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void CreateComponent(RenderTreeBuilder builder, Module module)
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
builder.SetKey(module.PageModuleId);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,8 @@
|
||||
User user = null;
|
||||
List<Module> modules;
|
||||
var moduleid = -1;
|
||||
var action = "";
|
||||
var action = string.Empty;
|
||||
var urlparameters = string.Empty;
|
||||
var editmode = false;
|
||||
var reload = Reload.None;
|
||||
var lastsyncdate = DateTime.UtcNow;
|
||||
@ -179,21 +180,60 @@
|
||||
// extract admin route elements from path
|
||||
var segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int result;
|
||||
// check if path has moduleid and action specification ie. pagename/moduleid/action/
|
||||
if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result))
|
||||
|
||||
int modIdPos = 0;
|
||||
int actionPos = 0;
|
||||
int urlParametersPos = 0;
|
||||
|
||||
for (int i = 0; i < segments.Length; i++)
|
||||
{
|
||||
action = segments[segments.Length - 1];
|
||||
moduleid = result;
|
||||
path = path.Replace(moduleid.ToString() + "/" + action + "/", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if path has moduleid specification ie. pagename/moduleid/
|
||||
if (segments.Length >= 1 && int.TryParse(segments[segments.Length - 1], out result))
|
||||
|
||||
if (segments[i] == Constants.UrlParametersDelimiter)
|
||||
{
|
||||
moduleid = result;
|
||||
path = path.Replace(moduleid.ToString() + "/", "");
|
||||
urlParametersPos = i + 1;
|
||||
}
|
||||
|
||||
if (i >= urlParametersPos && urlParametersPos != 0)
|
||||
{
|
||||
urlparameters += "/" + segments[i];
|
||||
}
|
||||
|
||||
if (segments[i] == Constants.ModuleDelimiter)
|
||||
{
|
||||
modIdPos = i + 1;
|
||||
actionPos = modIdPos + 1;
|
||||
if (actionPos > segments.Length - 1)
|
||||
{
|
||||
action = Constants.DefaultAction;
|
||||
}
|
||||
else
|
||||
{
|
||||
action = segments[actionPos];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check if path has moduleid and action specification ie. pagename/moduleid/action/
|
||||
if (modIdPos > 0)
|
||||
{
|
||||
int.TryParse(segments[modIdPos], out result);
|
||||
moduleid = result;
|
||||
if (actionPos > segments.Length - 1)
|
||||
{
|
||||
path = path.Replace(segments[modIdPos - 1] + "/" + segments[modIdPos] + "/", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
path = path.Replace(segments[modIdPos - 1] + "/" + segments[modIdPos] + "/" + segments[actionPos] + "/", "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (urlParametersPos > 0)
|
||||
{
|
||||
path = path.Replace(segments[urlParametersPos - 1] + urlparameters + "/", "");
|
||||
}
|
||||
|
||||
// remove trailing slash so it can be used as a key for Pages
|
||||
@ -220,17 +260,14 @@
|
||||
{
|
||||
page = pages.Where(item => item.Path == path).FirstOrDefault();
|
||||
reload = Reload.Page;
|
||||
if (page != null)
|
||||
{
|
||||
editmode = page.EditMode;
|
||||
}
|
||||
editmode = false;
|
||||
}
|
||||
|
||||
if (page != null)
|
||||
{
|
||||
if (PageState == null)
|
||||
{
|
||||
editmode = page.EditMode;
|
||||
editmode = false;
|
||||
}
|
||||
|
||||
// check if user is authorized to view page
|
||||
@ -263,6 +300,7 @@
|
||||
Modules = modules,
|
||||
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
||||
QueryString = querystring,
|
||||
UrlParameters = urlparameters,
|
||||
ModuleId = moduleid,
|
||||
Action = action,
|
||||
EditMode = editmode,
|
||||
@ -360,6 +398,13 @@
|
||||
|
||||
string panes = "";
|
||||
Type themetype = Type.GetType(page.ThemeType);
|
||||
if (themetype == null)
|
||||
{
|
||||
// fallback
|
||||
page.ThemeType = Constants.DefaultTheme;
|
||||
page.LayoutType = Constants.DefaultLayout;
|
||||
themetype = Type.GetType(Constants.DefaultTheme);
|
||||
}
|
||||
if (themetype != null)
|
||||
{
|
||||
var themeobject = Activator.CreateInstance(themetype) as IThemeControl;
|
||||
@ -401,7 +446,7 @@
|
||||
if (module.PageId == page.PageId || module.ModuleId == moduleid)
|
||||
{
|
||||
var typename = string.Empty;
|
||||
if (module.ModuleDefinition != null)
|
||||
if (module.ModuleDefinition != null && (module.ModuleDefinition.Runtimes == "" || module.ModuleDefinition.Runtimes.Contains(GetRuntime().ToString())))
|
||||
{
|
||||
typename = module.ModuleDefinition.ControlTypeTemplate;
|
||||
}
|
||||
@ -512,4 +557,4 @@
|
||||
=> RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER"))
|
||||
? Runtime.WebAssembly
|
||||
: Runtime.Server;
|
||||
}
|
||||
}
|
@ -54,11 +54,6 @@
|
||||
DynamicComponent = builder =>
|
||||
{
|
||||
var themeType = Type.GetType(PageState.Page.ThemeType);
|
||||
if (themeType == null)
|
||||
{
|
||||
// fallback
|
||||
themeType = Type.GetType(Constants.DefaultTheme);
|
||||
}
|
||||
builder.OpenComponent(0, themeType);
|
||||
builder.CloseComponent();
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Client</id>
|
||||
<version>1.0.1</version>
|
||||
<version>1.0.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -13,7 +13,7 @@
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||
<tags>oqtane</tags>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</releaseNotes>
|
||||
<summary>A modular application framework for Blazor</summary>
|
||||
</metadata>
|
||||
<files>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Framework</id>
|
||||
<version>1.0.1</version>
|
||||
<version>1.0.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -13,16 +13,11 @@
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||
<tags>oqtane framework</tags>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</releaseNotes>
|
||||
<summary>A modular application framework for Blazor</summary>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.dll" target="lib\netcoreapp3.1" />
|
||||
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.pdb" target="lib\netcoreapp3.1" />
|
||||
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.dll" target="lib\netcoreapp3.1" />
|
||||
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.pdb" target="lib\netcoreapp3.1" />
|
||||
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.dll" target="lib\netcoreapp3.1" />
|
||||
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.pdb" target="lib\netcoreapp3.1" />
|
||||
<file src="..\Oqtane.Server\wwwroot\**\*.*" target="wwwroot" />
|
||||
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\*.*" target="lib\netcoreapp3.1" />
|
||||
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\wwwroot\**\*.*" target="wwwroot" />
|
||||
</files>
|
||||
</package>
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Server</id>
|
||||
<version>1.0.1</version>
|
||||
<version>1.0.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -13,7 +13,7 @@
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||
<tags>oqtane</tags>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</releaseNotes>
|
||||
<summary>A modular application framework for Blazor</summary>
|
||||
</metadata>
|
||||
<files>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Shared</id>
|
||||
<version>1.0.1</version>
|
||||
<version>1.0.3</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@ -13,7 +13,7 @@
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||
<tags>oqtane</tags>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</releaseNotes>
|
||||
<summary>A modular application framework for Blazor</summary>
|
||||
</metadata>
|
||||
<files>
|
||||
|
1
Oqtane.Package/install.ps1
Normal file
1
Oqtane.Package/install.ps1
Normal file
@ -0,0 +1 @@
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\*" -DestinationPath "..\Oqtane.Server\bin\Release\Oqtane.Framework.1.0.3.Install.zip" -Force
|
Binary file not shown.
@ -1,5 +1,18 @@
|
||||
DEL "*.nupkg"
|
||||
del "*.nupkg"
|
||||
dotnet clean -c Release ..\Oqtane.sln
|
||||
dotnet build -c Release ..\Oqtane.sln
|
||||
dotnet pack -o .\ -c Release ..\Oqtane.sln
|
||||
nuget.exe pack Oqtane.Framework.nuspec
|
||||
nuget.exe pack Oqtane.Client.nuspec
|
||||
nuget.exe pack Oqtane.Server.nuspec
|
||||
nuget.exe pack Oqtane.Shared.nuspec
|
||||
del /F/Q/S "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish" > NUL
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish"
|
||||
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
|
||||
del "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\appsettings.json"
|
||||
ren "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\appsettings.release.json" "appsettings.json"
|
||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
|
||||
del "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\appsettings.json"
|
||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\upgrade.ps1"
|
||||
del "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\Oqtane.Upgrade.*"
|
||||
nuget.exe pack Oqtane.Framework.nuspec
|
||||
|
||||
|
||||
|
1
Oqtane.Package/upgrade.ps1
Normal file
1
Oqtane.Package/upgrade.ps1
Normal file
@ -0,0 +1 @@
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\netcoreapp3.1\publish\*" -DestinationPath "..\Oqtane.Server\bin\Release\Oqtane.Framework.1.0.3.Upgrade.zip" -Force
|
@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -483,7 +483,7 @@ namespace Oqtane.Controllers
|
||||
string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (string folder in folders)
|
||||
{
|
||||
path = Utilities.PathCombine(path, folder, "\\");
|
||||
path = Utilities.PathCombine(path, folder, Path.DirectorySeparatorChar.ToString());
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Models;
|
||||
@ -112,7 +113,7 @@ namespace Oqtane.Controllers
|
||||
Folder parent = _folders.GetFolder(folder.ParentId.Value);
|
||||
folder.Path = Utilities.PathCombine(parent.Path, folder.Name);
|
||||
}
|
||||
folder.Path = Utilities.PathCombine(folder.Path, "\\");
|
||||
folder.Path = Utilities.PathCombine(folder.Path, Path.DirectorySeparatorChar.ToString());
|
||||
folder = _folders.AddFolder(folder);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", folder);
|
||||
}
|
||||
@ -147,7 +148,7 @@ namespace Oqtane.Controllers
|
||||
Folder parent = _folders.GetFolder(folder.ParentId.Value);
|
||||
folder.Path = Utilities.PathCombine(parent.Path, folder.Name);
|
||||
}
|
||||
folder.Path = Utilities.PathCombine(folder.Path, "\\");
|
||||
folder.Path = Utilities.PathCombine(folder.Path, Path.DirectorySeparatorChar.ToString());
|
||||
folder = _folders.UpdateFolder(folder);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", folder);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ namespace Oqtane.Controllers
|
||||
var pages = _pages.GetPages(module.SiteId).ToList();
|
||||
foreach (Page page in pages)
|
||||
{
|
||||
if (page.PageId != pageModule.PageId && !page.EditMode)
|
||||
if (page.PageId != pageModule.PageId && !page.Path.StartsWith("admin/"))
|
||||
{
|
||||
_pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType });
|
||||
}
|
||||
|
21
Oqtane.Server/Controllers/ModuleControllerBase.cs
Normal file
21
Oqtane.Server/Controllers/ModuleControllerBase.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Infrastructure;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
public class ModuleControllerBase : Controller
|
||||
{
|
||||
protected readonly ILogManager _logger;
|
||||
protected int _entityId = -1; // passed as a querystring parameter for policy authorization and used for validation
|
||||
|
||||
public ModuleControllerBase(ILogManager logger, IHttpContextAccessor accessor)
|
||||
{
|
||||
_logger = logger;
|
||||
if (accessor.HttpContext.Request.Query.ContainsKey("entityid"))
|
||||
{
|
||||
_entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -94,8 +94,8 @@ namespace Oqtane.Controllers
|
||||
[Authorize(Roles = Constants.HostRole)]
|
||||
public void InstallModules()
|
||||
{
|
||||
_installationManager.InstallPackages("Modules", true);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Modules Installed");
|
||||
_installationManager.InstallPackages("Modules", true);
|
||||
}
|
||||
|
||||
// DELETE api/<controller>/5?siteid=x
|
||||
@ -170,17 +170,17 @@ namespace Oqtane.Controllers
|
||||
{
|
||||
string rootPath;
|
||||
DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath);
|
||||
string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", moduleDefinition.Template,"\\");
|
||||
string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", moduleDefinition.Template,Path.DirectorySeparatorChar.ToString());
|
||||
|
||||
if (moduleDefinition.Template == "internal")
|
||||
{
|
||||
rootPath = Utilities.PathCombine(rootFolder.FullName,"\\");
|
||||
rootPath = Utilities.PathCombine(rootFolder.FullName,Path.DirectorySeparatorChar.ToString());
|
||||
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, Oqtane.Client";
|
||||
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
|
||||
}
|
||||
else
|
||||
{
|
||||
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name + "s","\\");
|
||||
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name + "s",Path.DirectorySeparatorChar.ToString());
|
||||
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Client.Oqtane";
|
||||
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Server.Oqtane";
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ namespace Oqtane.Controllers
|
||||
_syncManager.AddSyncEvent(_tenants.GetTenant().TenantId, EntityNames.Site, page.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Page Added {Page}", page);
|
||||
|
||||
if (!page.EditMode)
|
||||
if (!page.Path.StartsWith("admin/"))
|
||||
{
|
||||
var modules = _modules.GetModules(page.SiteId).Where(item => item.AllPages).ToList();
|
||||
foreach (Module module in modules)
|
||||
@ -163,7 +163,6 @@ namespace Oqtane.Controllers
|
||||
page.Order = 0;
|
||||
page.IsNavigation = false;
|
||||
page.Url = "";
|
||||
page.EditMode = false;
|
||||
page.ThemeType = parent.ThemeType;
|
||||
page.LayoutType = parent.LayoutType;
|
||||
page.DefaultContainerType = parent.DefaultContainerType;
|
||||
|
@ -43,8 +43,8 @@ namespace Oqtane.Controllers
|
||||
[Authorize(Roles = Constants.HostRole)]
|
||||
public void InstallThemes()
|
||||
{
|
||||
_installationManager.InstallPackages("Themes", true);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Themes Installed");
|
||||
_installationManager.InstallPackages("Themes", true);
|
||||
}
|
||||
|
||||
// DELETE api/<controller>/xxx
|
||||
|
@ -9,6 +9,7 @@ using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using Oqtane.Shared;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Oqtane.Enums;
|
||||
using Oqtane.Infrastructure;
|
||||
@ -174,7 +175,7 @@ namespace Oqtane.Controllers
|
||||
}
|
||||
|
||||
// add folder for user
|
||||
Folder folder = _folders.GetFolder(user.SiteId, Utilities.PathCombine("Users","\\"));
|
||||
Folder folder = _folders.GetFolder(user.SiteId, Utilities.PathCombine("Users",Path.DirectorySeparatorChar.ToString()));
|
||||
if (folder != null)
|
||||
{
|
||||
_folders.AddFolder(new Folder
|
||||
@ -182,7 +183,7 @@ namespace Oqtane.Controllers
|
||||
SiteId = folder.SiteId,
|
||||
ParentId = folder.FolderId,
|
||||
Name = "My Folder",
|
||||
Path = Utilities.PathCombine(folder.Path, newUser.UserId.ToString(),"\\"),
|
||||
Path = Utilities.PathCombine(folder.Path, newUser.UserId.ToString(),Path.DirectorySeparatorChar.ToString()),
|
||||
Order = 1,
|
||||
IsSystem = true,
|
||||
Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"[" + newUser.UserId.ToString() + "]\"},{\"PermissionName\":\"View\",\"Permissions\":\"All Users\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"[" +
|
||||
|
@ -461,7 +461,7 @@ namespace Oqtane.Infrastructure
|
||||
userroles.AddUserRole(userRole);
|
||||
|
||||
// add user folder
|
||||
var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", "\\"));
|
||||
var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString()));
|
||||
if (folder != null)
|
||||
{
|
||||
folders.AddFolder(new Folder
|
||||
@ -469,7 +469,7 @@ namespace Oqtane.Infrastructure
|
||||
SiteId = folder.SiteId,
|
||||
ParentId = folder.FolderId,
|
||||
Name = "My Folder",
|
||||
Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), "\\"),
|
||||
Path = Utilities.PathCombine(folder.Path, user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()),
|
||||
Order = 1,
|
||||
IsSystem = true,
|
||||
Permissions = new List<Permission>
|
||||
|
@ -1,13 +1,13 @@
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using Oqtane.Shared;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Infrastructure
|
||||
{
|
||||
@ -27,7 +27,7 @@ namespace Oqtane.Infrastructure
|
||||
public void InstallPackages(string folders, bool restart)
|
||||
{
|
||||
var webRootPath = _environment.WebRootPath;
|
||||
|
||||
|
||||
var install = InstallPackages(folders, webRootPath);
|
||||
|
||||
if (install && restart)
|
||||
@ -88,7 +88,7 @@ namespace Oqtane.Infrastructure
|
||||
// deploy to appropriate locations
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
string foldername = Path.GetDirectoryName(entry.FullName).Split('\\')[0];
|
||||
string foldername = Path.GetDirectoryName(entry.FullName).Split(Path.DirectorySeparatorChar)[0];
|
||||
string filename = Path.GetFileName(entry.FullName);
|
||||
|
||||
switch (foldername)
|
||||
@ -98,7 +98,12 @@ namespace Oqtane.Infrastructure
|
||||
ExtractFile(entry, filename);
|
||||
break;
|
||||
case "wwwroot":
|
||||
filename = Path.Combine(webRootPath, Utilities.PathCombine(entry.FullName.Replace("wwwroot/", "").Split('/')));
|
||||
filename = Path.Combine(webRootPath.Replace(Path.DirectorySeparatorChar + "wwwroot", ""), Utilities.PathCombine(entry.FullName.Split('/')));
|
||||
ExtractFile(entry, filename);
|
||||
break;
|
||||
case "runtimes":
|
||||
var destSubFolder = Path.GetDirectoryName(entry.FullName);
|
||||
filename = Path.Combine(binFolder, destSubFolder, filename);
|
||||
ExtractFile(entry, filename);
|
||||
break;
|
||||
}
|
||||
@ -121,7 +126,15 @@ namespace Oqtane.Infrastructure
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(filename));
|
||||
}
|
||||
entry.ExtractToFile(filename, true);
|
||||
|
||||
try
|
||||
{
|
||||
entry.ExtractToFile(filename, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// an error occurred extracting the file
|
||||
}
|
||||
}
|
||||
|
||||
public void UpgradeFramework()
|
||||
@ -131,7 +144,7 @@ namespace Oqtane.Infrastructure
|
||||
{
|
||||
// get package with highest version and clean up any others
|
||||
string packagename = "";
|
||||
foreach(string package in Directory.GetFiles(folder, "Oqtane.Framework.*.nupkg"))
|
||||
foreach (string package in Directory.GetFiles(folder, "Oqtane.Framework.*.nupkg"))
|
||||
{
|
||||
if (packagename != "")
|
||||
{
|
||||
@ -163,12 +176,13 @@ namespace Oqtane.Infrastructure
|
||||
packageversion = node.InnerText;
|
||||
}
|
||||
reader.Close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure package version is higher than current framework version
|
||||
if (packageversion != "" && Version.Parse(Constants.Version).CompareTo(Version.Parse(packageversion)) < 0)
|
||||
// ensure package version is greater than or equal to current framework version
|
||||
if (packageversion != "" && Version.Parse(Constants.Version).CompareTo(Version.Parse(packageversion)) <= 0)
|
||||
{
|
||||
FinishUpgrade();
|
||||
}
|
||||
@ -179,28 +193,26 @@ namespace Oqtane.Infrastructure
|
||||
private void FinishUpgrade()
|
||||
{
|
||||
// check if upgrade application exists
|
||||
string Upgrader = "Oqtane.Upgrade.dll";
|
||||
string folder = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
||||
if (folder == null || !File.Exists(Path.Combine(folder, "Oqtane.Upgrade.exe"))) return;
|
||||
if (folder == null || !File.Exists(Path.Combine(folder, Upgrader))) return;
|
||||
|
||||
// run upgrade application
|
||||
var process = new Process
|
||||
using (var process = new Process())
|
||||
{
|
||||
StartInfo =
|
||||
process.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = Path.Combine(folder, "Oqtane.Upgrade.exe"),
|
||||
Arguments = "\"" + _environment.ContentRootPath + "\" \"" + _environment.WebRootPath + "\"",
|
||||
ErrorDialog = false,
|
||||
WorkingDirectory = folder,
|
||||
FileName = "dotnet",
|
||||
Arguments = Path.Combine(folder, Upgrader) + " \"" + _environment.ContentRootPath + "\" \"" + _environment.WebRootPath + "\"",
|
||||
UseShellExecute = false,
|
||||
ErrorDialog = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = false,
|
||||
RedirectStandardError = false
|
||||
}
|
||||
};
|
||||
process.Start();
|
||||
};
|
||||
process.Start();
|
||||
process.Dispose();
|
||||
|
||||
// stop application so upgrade application can proceed
|
||||
RestartApplication();
|
||||
}
|
||||
|
||||
public void RestartApplication()
|
||||
|
@ -27,8 +27,10 @@ namespace Oqtane.Infrastructure
|
||||
|
||||
protected async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
await Task.Yield(); // required so that this method does not block startup
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
@ -41,21 +43,26 @@ namespace Oqtane.Infrastructure
|
||||
Job job = jobs.GetJobs().Where(item => item.JobType == jobType).FirstOrDefault();
|
||||
if (job != null && job.IsEnabled && !job.IsExecuting)
|
||||
{
|
||||
// set next execution date
|
||||
// get next execution date
|
||||
DateTime NextExecution;
|
||||
if (job.NextExecution == null)
|
||||
{
|
||||
if (job.StartDate != null)
|
||||
{
|
||||
job.NextExecution = job.StartDate;
|
||||
NextExecution = job.StartDate.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
job.NextExecution = DateTime.UtcNow;
|
||||
NextExecution = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NextExecution = job.NextExecution.Value;
|
||||
}
|
||||
|
||||
// determine if the job should be run
|
||||
if (job.NextExecution <= DateTime.UtcNow && (job.EndDate == null || job.EndDate >= DateTime.UtcNow))
|
||||
if (NextExecution <= DateTime.UtcNow && (job.EndDate == null || job.EndDate >= DateTime.UtcNow))
|
||||
{
|
||||
IJobLogRepository jobLogs = scope.ServiceProvider.GetRequiredService<IJobLogRepository>();
|
||||
|
||||
@ -89,7 +96,7 @@ namespace Oqtane.Infrastructure
|
||||
jobLogs.UpdateJobLog(log);
|
||||
|
||||
// update the job
|
||||
job.NextExecution = CalculateNextExecution(job.NextExecution.Value, job.Frequency, job.Interval);
|
||||
job.NextExecution = CalculateNextExecution(NextExecution, job.Frequency, job.Interval);
|
||||
job.IsExecuting = false;
|
||||
jobs.UpdateJob(job);
|
||||
|
||||
|
@ -20,11 +20,15 @@ namespace Oqtane.Infrastructure
|
||||
{
|
||||
string log = "";
|
||||
|
||||
// iterate through aliases in this installation
|
||||
// iterate through tenants in this installation
|
||||
List<int> tenants = new List<int>();
|
||||
var aliasRepository = provider.GetRequiredService<IAliasRepository>();
|
||||
List<Alias> aliases = aliasRepository.GetAliases().ToList();
|
||||
foreach (Alias alias in aliases)
|
||||
{
|
||||
if (tenants.Contains(alias.TenantId)) continue;
|
||||
tenants.Add(alias.TenantId);
|
||||
|
||||
// use the SiteState to set the Alias explicitly so the tenant can be resolved
|
||||
var siteState = provider.GetRequiredService<SiteState>();
|
||||
siteState.Alias = alias;
|
||||
@ -34,11 +38,11 @@ namespace Oqtane.Infrastructure
|
||||
var settingRepository = provider.GetRequiredService<ISettingRepository>();
|
||||
var notificationRepository = provider.GetRequiredService<INotificationRepository>();
|
||||
|
||||
// iterate through sites
|
||||
// iterate through sites for this tenant
|
||||
List<Site> sites = siteRepository.GetSites().ToList();
|
||||
foreach (Site site in sites)
|
||||
{
|
||||
log += "Processing Notifications For Site: " + site.Name + "\n\n";
|
||||
log += "Processing Notifications For Site: " + site.Name + "<br />";
|
||||
|
||||
// get site settings
|
||||
List<Setting> sitesettings = settingRepository.GetSettings(EntityNames.Site, site.SiteId).ToList();
|
||||
@ -101,14 +105,14 @@ namespace Oqtane.Infrastructure
|
||||
catch (Exception ex)
|
||||
{
|
||||
// error
|
||||
log += ex.Message + "\n\n";
|
||||
log += ex.Message + "<br />";
|
||||
}
|
||||
}
|
||||
log += "Notifications Delivered: " + sent + "\n\n";
|
||||
log += "Notifications Delivered: " + sent + "<br />";
|
||||
}
|
||||
else
|
||||
{
|
||||
log += "SMTP Not Configured" + "\n\n";
|
||||
log += "SMTP Not Configured" + "<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,7 +120,6 @@ namespace Oqtane.Infrastructure
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
private Dictionary<string, string> GetSettings(List<Setting> settings)
|
||||
{
|
||||
Dictionary<string, string> dictionary = new Dictionary<string, string>();
|
||||
|
@ -42,7 +42,6 @@ namespace Oqtane.SiteTemplates
|
||||
Icon = "home",
|
||||
IsNavigation = true,
|
||||
IsPersonalizable = false,
|
||||
EditMode = false,
|
||||
PagePermissions = new List<Permission> {
|
||||
new Permission(PermissionNames.View, Constants.AllUsersRole, true),
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -89,7 +88,6 @@ namespace Oqtane.SiteTemplates
|
||||
Icon = "lock-locked",
|
||||
IsNavigation = true,
|
||||
IsPersonalizable = false,
|
||||
EditMode = false,
|
||||
PagePermissions = new List<Permission> {
|
||||
new Permission(PermissionNames.View, Constants.RegisteredRole, true),
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -114,7 +112,6 @@ namespace Oqtane.SiteTemplates
|
||||
Icon = "target",
|
||||
IsNavigation = true,
|
||||
IsPersonalizable = true,
|
||||
EditMode = false,
|
||||
PagePermissions = new List<Permission> {
|
||||
new Permission(PermissionNames.View, Constants.AllUsersRole, true),
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -134,7 +131,7 @@ namespace Oqtane.SiteTemplates
|
||||
|
||||
if (System.IO.File.Exists(Path.Combine(_environment.WebRootPath, "images", "logo-white.png")))
|
||||
{
|
||||
string folderpath = Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", site.TenantId.ToString(), "Sites", site.SiteId.ToString(),"\\");
|
||||
string folderpath = Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", site.TenantId.ToString(), "Sites", site.SiteId.ToString(), Path.DirectorySeparatorChar.ToString());
|
||||
System.IO.Directory.CreateDirectory(folderpath);
|
||||
if (!System.IO.File.Exists(Path.Combine(folderpath, "logo-white.png")))
|
||||
{
|
||||
|
@ -30,7 +30,6 @@ namespace Oqtane.SiteTemplates
|
||||
Icon = "home",
|
||||
IsNavigation = true,
|
||||
IsPersonalizable = false,
|
||||
EditMode = false,
|
||||
PagePermissions = new List<Permission> {
|
||||
new Permission(PermissionNames.View, Constants.AllUsersRole, true),
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
|
@ -8,24 +8,18 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Enums;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Controllers;
|
||||
|
||||
namespace Oqtane.Modules.HtmlText.Controllers
|
||||
{
|
||||
[Route("{alias}/api/[controller]")]
|
||||
public class HtmlTextController : Controller
|
||||
public class HtmlTextController : ModuleControllerBase
|
||||
{
|
||||
private readonly IHtmlTextRepository _htmlText;
|
||||
private readonly ILogManager _logger;
|
||||
private int _entityId = -1; // passed as a querystring parameter for authorization and used for validation
|
||||
|
||||
public HtmlTextController(IHtmlTextRepository htmlText, ILogManager logger, IHttpContextAccessor httpContextAccessor)
|
||||
public HtmlTextController(IHtmlTextRepository htmlText, ILogManager logger, IHttpContextAccessor accessor) : base(logger, accessor)
|
||||
{
|
||||
_htmlText = htmlText;
|
||||
_logger = logger;
|
||||
if (httpContextAccessor.HttpContext.Request.Query.ContainsKey("entityid"))
|
||||
{
|
||||
_entityId = int.Parse(httpContextAccessor.HttpContext.Request.Query["entityid"]);
|
||||
}
|
||||
}
|
||||
|
||||
// GET api/<controller>/5
|
||||
|
@ -4,7 +4,7 @@
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -13,7 +13,7 @@
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
@ -32,6 +32,7 @@
|
||||
<EmbeddedResource Include="Scripts\Tenant.00.09.02.00.sql" />
|
||||
<EmbeddedResource Include="Scripts\Tenant.01.00.01.00.sql" />
|
||||
<EmbeddedResource Include="Scripts\Tenant.01.00.01.01.sql" />
|
||||
<EmbeddedResource Include="Scripts\Tenant.01.00.02.01.sql" />
|
||||
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.1.0.0.sql" />
|
||||
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.Uninstall.sql" />
|
||||
</ItemGroup>
|
||||
@ -49,4 +50,14 @@
|
||||
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
|
||||
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<UpgradeFiles Include="$(ProjectDir)bin\Release\netcoreapp3.1\Oqtane.Upgrade.deps.json" />
|
||||
<UpgradeFiles Include="$(ProjectDir)bin\Release\netcoreapp3.1\Oqtane.Upgrade.dll" />
|
||||
<UpgradeFiles Include="$(ProjectDir)bin\Release\netcoreapp3.1\Oqtane.Upgrade.pdb" />
|
||||
<UpgradeFiles Include="$(ProjectDir)bin\Release\netcoreapp3.1\Oqtane.Upgrade.runtimeconfig.json" />
|
||||
<TemplateFiles Include="$(ProjectDir)wwwroot\Modules\Templates\**\*.*" />
|
||||
</ItemGroup>
|
||||
<Target Name="AddPayloadsFolder" AfterTargets="Publish">
|
||||
<Copy SourceFiles="@(UpgradeFiles)" DestinationFiles="@(UpgradeFiles->'$(PublishDir)%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
|
||||
<Copy SourceFiles="@(TemplateFiles)" DestinationFiles="@(TemplateFiles->'$(PublishDir)wwwroot\Modules\Templates\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
|
||||
</Target></Project>
|
||||
|
@ -123,7 +123,7 @@ namespace Oqtane.Repository
|
||||
ModuleDefinition moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault();
|
||||
if (moduledefinition != null)
|
||||
{
|
||||
ModuleContent modulecontent = JsonSerializer.Deserialize<ModuleContent>(content);
|
||||
ModuleContent modulecontent = JsonSerializer.Deserialize<ModuleContent>(content.Replace("\n", ""));
|
||||
if (modulecontent.ModuleDefinitionName == moduledefinition.ModuleDefinitionName)
|
||||
{
|
||||
if (moduledefinition.ServerManagerType != "")
|
||||
@ -147,9 +147,10 @@ namespace Oqtane.Repository
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
// error occurred during import
|
||||
string error = ex.Message;
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -21,7 +21,7 @@ namespace Oqtane.Repository
|
||||
return _db.Notification
|
||||
.Where(item => item.SiteId == siteId)
|
||||
.Where(item => item.IsDelivered == false)
|
||||
.Where(item => item.SendOn < System.DateTime.UtcNow)
|
||||
.Where(item => item.SendOn == null || item.SendOn < System.DateTime.UtcNow)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.LockLocked,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -88,7 +87,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.Person,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -119,7 +117,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.Person,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -149,7 +146,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.Person,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -175,7 +171,7 @@ namespace Oqtane.Repository
|
||||
// admin pages
|
||||
pageTemplates.Add(new PageTemplate
|
||||
{
|
||||
Name = "Admin", Parent = "", Path = "admin", Icon = "", IsNavigation = false, IsPersonalizable = false, EditMode = true,
|
||||
Name = "Admin", Parent = "", Path = "admin", Icon = "", IsNavigation = false, IsPersonalizable = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -203,7 +199,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.Home,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -231,7 +226,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.Layers,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -259,7 +253,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.People,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -287,7 +280,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.Person,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -315,7 +307,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.LockLocked,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -343,7 +334,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.File,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -371,7 +361,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.Trash,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
@ -401,7 +390,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.MagnifyingGlass,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -428,7 +416,6 @@ namespace Oqtane.Repository
|
||||
Icon = Icons.List,
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -450,7 +437,7 @@ namespace Oqtane.Repository
|
||||
});
|
||||
pageTemplates.Add(new PageTemplate
|
||||
{
|
||||
Name = "Site Management", Parent = "Admin", Path = "admin/sites", Icon = Icons.Globe, IsNavigation = false, IsPersonalizable = false, EditMode = true,
|
||||
Name = "Site Management", Parent = "Admin", Path = "admin/sites", Icon = Icons.Globe, IsNavigation = false, IsPersonalizable = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -472,7 +459,7 @@ namespace Oqtane.Repository
|
||||
});
|
||||
pageTemplates.Add(new PageTemplate
|
||||
{
|
||||
Name = "Module Management", Parent = "Admin", Path = "admin/modules", Icon = Icons.Browser, IsNavigation = false, IsPersonalizable = false, EditMode = true,
|
||||
Name = "Module Management", Parent = "Admin", Path = "admin/modules", Icon = Icons.Browser, IsNavigation = false, IsPersonalizable = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -494,7 +481,7 @@ namespace Oqtane.Repository
|
||||
});
|
||||
pageTemplates.Add(new PageTemplate
|
||||
{
|
||||
Name = "Theme Management", Parent = "Admin", Path = "admin/themes", Icon = Icons.Brush, IsNavigation = false, IsPersonalizable = false, EditMode = true,
|
||||
Name = "Theme Management", Parent = "Admin", Path = "admin/themes", Icon = Icons.Brush, IsNavigation = false, IsPersonalizable = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -516,7 +503,7 @@ namespace Oqtane.Repository
|
||||
});
|
||||
pageTemplates.Add(new PageTemplate
|
||||
{
|
||||
Name = "Scheduled Jobs", Parent = "Admin", Path = "admin/jobs", Icon = Icons.Timer, IsNavigation = false, IsPersonalizable = false, EditMode = true,
|
||||
Name = "Scheduled Jobs", Parent = "Admin", Path = "admin/jobs", Icon = Icons.Timer, IsNavigation = false, IsPersonalizable = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -544,7 +531,6 @@ namespace Oqtane.Repository
|
||||
Icon = "spreadsheet",
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -572,7 +558,6 @@ namespace Oqtane.Repository
|
||||
Icon = "medical-cross",
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -594,7 +579,7 @@ namespace Oqtane.Repository
|
||||
});
|
||||
pageTemplates.Add(new PageTemplate
|
||||
{
|
||||
Name = "System Update", Parent = "Admin", Path = "admin/update", Icon = Icons.Aperture, IsNavigation = false, IsPersonalizable = false, EditMode = true,
|
||||
Name = "System Update", Parent = "Admin", Path = "admin/update", Icon = Icons.Aperture, IsNavigation = false, IsPersonalizable = false,
|
||||
PagePermissions = new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.HostRole, true),
|
||||
@ -692,7 +677,7 @@ namespace Oqtane.Repository
|
||||
});
|
||||
_folderRepository.AddFolder(new Folder
|
||||
{
|
||||
SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Users", Path = Utilities.PathCombine("Users","\\"), Order = 1, IsSystem = true,
|
||||
SiteId = site.SiteId, ParentId = folder.FolderId, Name = "Users", Path = Utilities.PathCombine("Users",Path.DirectorySeparatorChar.ToString()), Order = 1, IsSystem = true,
|
||||
Permissions = "[{\"PermissionName\":\"Browse\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]"
|
||||
});
|
||||
|
||||
@ -754,7 +739,6 @@ namespace Oqtane.Repository
|
||||
Order = 1,
|
||||
Url = "",
|
||||
IsNavigation = pagetemplate.IsNavigation,
|
||||
EditMode = pagetemplate.EditMode,
|
||||
ThemeType = "",
|
||||
LayoutType = "",
|
||||
DefaultContainerType = "",
|
||||
|
9
Oqtane.Server/Scripts/Tenant.01.00.02.01.sql
Normal file
9
Oqtane.Server/Scripts/Tenant.01.00.02.01.sql
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
|
||||
Version 1.0.2.1 migration script
|
||||
|
||||
*/
|
||||
|
||||
ALTER TABLE [dbo].[Page]
|
||||
DROP COLUMN EditMode
|
||||
GO
|
@ -72,7 +72,7 @@ namespace Oqtane
|
||||
});
|
||||
}
|
||||
|
||||
// register authorization services
|
||||
// register custom authorization policies
|
||||
services.AddAuthorizationCore(options =>
|
||||
{
|
||||
options.AddPolicy("ViewPage", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View)));
|
||||
|
15
Oqtane.Server/appsettings.release.json
Normal file
15
Oqtane.Server/appsettings.release.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"Runtime": "Server",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": ""
|
||||
},
|
||||
"Installation": {
|
||||
"DefaultAlias": "",
|
||||
"HostPassword": "",
|
||||
"HostEmail": "",
|
||||
"SiteTemplate": "",
|
||||
"DefaultTheme": "",
|
||||
"DefaultLayout": "",
|
||||
"DefaultContainer": ""
|
||||
}
|
||||
}
|
@ -50,7 +50,7 @@
|
||||
if (PageState.Action == "Edit")
|
||||
{
|
||||
_id = Int32.Parse(PageState.QueryString["id"]);
|
||||
[Module] [Module] = await [Module]Service.Get[Module]Async(_id);
|
||||
[Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
|
||||
if ([Module] != null)
|
||||
{
|
||||
_name = [Module].Name;
|
||||
@ -82,7 +82,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
[Module] [Module] = await [Module]Service.Get[Module]Async(_id);
|
||||
[Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
|
||||
[Module].Name = _name;
|
||||
await [Module]Service.Update[Module]Async([Module]);
|
||||
await logger.LogInformation("[Module] Updated {[Module]}", [Module]);
|
||||
|
@ -95,7 +95,7 @@ else
|
||||
{
|
||||
try
|
||||
{
|
||||
await [Module]Service.Delete[Module]Async([Module].[Module]Id);
|
||||
await [Module]Service.Delete[Module]Async([Module].[Module]Id, ModuleState.ModuleId);
|
||||
await logger.LogInformation("[Module] Deleted {[Module]}", [Module]);
|
||||
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
|
||||
StateHasChanged();
|
||||
|
@ -8,12 +8,12 @@ namespace [Owner].[Module]s.Services
|
||||
{
|
||||
Task<List<[Module]>> Get[Module]sAsync(int ModuleId);
|
||||
|
||||
Task<[Module]> Get[Module]Async(int [Module]Id);
|
||||
Task<[Module]> Get[Module]Async(int [Module]Id, int ModuleId);
|
||||
|
||||
Task<[Module]> Add[Module]Async([Module] [Module]);
|
||||
|
||||
Task<[Module]> Update[Module]Async([Module] [Module]);
|
||||
|
||||
Task Delete[Module]Async(int [Module]Id);
|
||||
Task Delete[Module]Async(int [Module]Id, int ModuleId);
|
||||
}
|
||||
}
|
||||
|
@ -18,32 +18,44 @@ namespace [Owner].[Module]s.Services
|
||||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl=> CreateApiUrl(_siteState.Alias, "[Module]");
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "[Module]");
|
||||
|
||||
public async Task<List<[Module]>> Get[Module]sAsync(int ModuleId)
|
||||
{
|
||||
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>($"{Apiurl}?moduleid={ModuleId}");
|
||||
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>(CreateAuthPolicyUrl($"{Apiurl}?moduleid={ModuleId}", ModuleId));
|
||||
return [Module]s.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
|
||||
public async Task<[Module]> Get[Module]Async(int [Module]Id)
|
||||
public async Task<[Module]> Get[Module]Async(int [Module]Id, int ModuleId)
|
||||
{
|
||||
return await GetJsonAsync<[Module]>($"{Apiurl}/{[Module]Id}");
|
||||
return await GetJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
|
||||
}
|
||||
|
||||
public async Task<[Module]> Add[Module]Async([Module] [Module])
|
||||
{
|
||||
return await PostJsonAsync<[Module]>($"{Apiurl}?entityid={[Module].ModuleId}", [Module]);
|
||||
return await PostJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}", [Module].ModuleId), [Module]);
|
||||
}
|
||||
|
||||
public async Task<[Module]> Update[Module]Async([Module] [Module])
|
||||
{
|
||||
return await PutJsonAsync<[Module]>($"{Apiurl}/{[Module].[Module]Id}?entityid={[Module].ModuleId}", [Module]);
|
||||
return await PutJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}/{[Module].[Module]Id}", [Module].ModuleId), [Module]);
|
||||
}
|
||||
|
||||
public async Task Delete[Module]Async(int [Module]Id)
|
||||
public async Task Delete[Module]Async(int [Module]Id, int ModuleId)
|
||||
{
|
||||
await DeleteAsync($"{Apiurl}/{[Module]Id}");
|
||||
await DeleteAsync(CreateAuthPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
|
||||
}
|
||||
|
||||
private string CreateAuthPolicyUrl(string Url, int ModuleId)
|
||||
{
|
||||
if (Url.Contains("?"))
|
||||
{
|
||||
return Url + "&entityid=" + ModuleId.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Url + "?entityid=" + ModuleId.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Oqtane.Client" Version="1.0.1" />
|
||||
<PackageReference Include="Oqtane.Shared" Version="1.0.1" />
|
||||
<PackageReference Include="Oqtane.Client" Version="1.0.3" />
|
||||
<PackageReference Include="Oqtane.Shared" Version="1.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Enums;
|
||||
using Oqtane.Infrastructure;
|
||||
@ -9,21 +10,27 @@ using [Owner].[Module]s.Repository;
|
||||
|
||||
namespace [Owner].[Module]s.Controllers
|
||||
{
|
||||
[Route("{site}/api/[controller]")]
|
||||
[Route("{alias}/api/[controller]")]
|
||||
public class [Module]Controller : Controller
|
||||
{
|
||||
private readonly I[Module]Repository _[Module]s;
|
||||
private readonly ILogManager _logger;
|
||||
protected int _entityId = -1;
|
||||
|
||||
public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger)
|
||||
public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger, IHttpContextAccessor accessor)
|
||||
{
|
||||
_[Module]s = [Module]s;
|
||||
_logger = logger;
|
||||
|
||||
if (accessor.HttpContext.Request.Query.ContainsKey("entityid"))
|
||||
{
|
||||
_entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]);
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/<controller>?moduleid=x
|
||||
[HttpGet]
|
||||
[Authorize(Roles = Constants.RegisteredRole)]
|
||||
[Authorize(Policy = "ViewModule")]
|
||||
public IEnumerable<[Module]> Get(string moduleid)
|
||||
{
|
||||
return _[Module]s.Get[Module]s(int.Parse(moduleid));
|
||||
@ -31,18 +38,23 @@ namespace [Owner].[Module]s.Controllers
|
||||
|
||||
// GET api/<controller>/5
|
||||
[HttpGet("{id}")]
|
||||
[Authorize(Roles = Constants.RegisteredRole)]
|
||||
[Authorize(Policy = "ViewModule")]
|
||||
public [Module] Get(int id)
|
||||
{
|
||||
return _[Module]s.Get[Module](id);
|
||||
[Module] [Module] = _[Module]s.Get[Module](id);
|
||||
if ([Module] != null && [Module].ModuleId != _entityId)
|
||||
{
|
||||
[Module] = null;
|
||||
}
|
||||
return [Module];
|
||||
}
|
||||
|
||||
// POST api/<controller>
|
||||
[HttpPost]
|
||||
[Authorize(Roles = Constants.AdminRole)]
|
||||
[Authorize(Policy = "EditModule")]
|
||||
public [Module] Post([FromBody] [Module] [Module])
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
if (ModelState.IsValid && [Module].ModuleId == _entityId)
|
||||
{
|
||||
[Module] = _[Module]s.Add[Module]([Module]);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]);
|
||||
@ -52,10 +64,10 @@ namespace [Owner].[Module]s.Controllers
|
||||
|
||||
// PUT api/<controller>/5
|
||||
[HttpPut("{id}")]
|
||||
[Authorize(Roles = Constants.AdminRole)]
|
||||
[Authorize(Policy = "EditModule")]
|
||||
public [Module] Put(int id, [FromBody] [Module] [Module])
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
if (ModelState.IsValid && [Module].ModuleId == _entityId)
|
||||
{
|
||||
[Module] = _[Module]s.Update[Module]([Module]);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]);
|
||||
@ -65,11 +77,15 @@ namespace [Owner].[Module]s.Controllers
|
||||
|
||||
// DELETE api/<controller>/5
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize(Roles = Constants.AdminRole)]
|
||||
[Authorize(Policy = "EditModule")]
|
||||
public void Delete(int id)
|
||||
{
|
||||
_[Module]s.Delete[Module](id);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id);
|
||||
[Module] [Module] = _[Module]s.Get[Module](id);
|
||||
if ([Module] != null && [Module].ModuleId == _entityId)
|
||||
{
|
||||
_[Module]s.Delete[Module](id);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Oqtane.Server" Version="1.0.1" />
|
||||
<PackageReference Include="Oqtane.Shared" Version="1.0.1" />
|
||||
<PackageReference Include="Oqtane.Server" Version="1.0.3" />
|
||||
<PackageReference Include="Oqtane.Shared" Version="1.0.3" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1 +0,0 @@
|
||||
This is the location where static resources such as images, style sheets, or scripts for this module will be located. Static assets can be organized in subfolders. When the module package is deployed the assets will be extracted under the web root in a folder that matches the module namespace.
|
@ -17,7 +17,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Oqtane.Shared" Version="1.0.1" />
|
||||
<PackageReference Include="Oqtane.Shared" Version="1.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -28,8 +28,14 @@
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||
|
||||
public override string Actions => "Add,Edit";
|
||||
|
||||
public override List<Resource> Resources => new List<Resource>()
|
||||
{
|
||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
||||
};
|
||||
|
||||
int _id;
|
||||
string _name;
|
||||
string _createdby;
|
||||
@ -44,7 +50,7 @@
|
||||
if (PageState.Action == "Edit")
|
||||
{
|
||||
_id = Int32.Parse(PageState.QueryString["id"]);
|
||||
[Module] [Module] = await [Module]Service.Get[Module]Async(_id);
|
||||
[Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
|
||||
if ([Module] != null)
|
||||
{
|
||||
_name = [Module].Name;
|
||||
@ -76,7 +82,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
[Module] [Module] = await [Module]Service.Get[Module]Async(_id);
|
||||
[Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
|
||||
[Module].Name = _name;
|
||||
await [Module]Service.Update[Module]Async([Module]);
|
||||
await logger.LogInformation("[Module] Updated {[Module]}", [Module]);
|
||||
|
@ -61,6 +61,11 @@ else
|
||||
<!-- The content above is for informational purposes only and can be safely removed -->
|
||||
|
||||
@code {
|
||||
public override List<Resource> Resources => new List<Resource>()
|
||||
{
|
||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
||||
};
|
||||
|
||||
List<[Module]> _[Module]s;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
@ -80,7 +85,7 @@ else
|
||||
{
|
||||
try
|
||||
{
|
||||
await [Module]Service.Delete[Module]Async([Module].[Module]Id);
|
||||
await [Module]Service.Delete[Module]Async([Module].[Module]Id, ModuleState.ModuleId);
|
||||
await logger.LogInformation("[Module] Deleted {[Module]}", [Module]);
|
||||
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
|
||||
StateHasChanged();
|
||||
|
@ -8,12 +8,12 @@ namespace [Owner].[Module]s.Services
|
||||
{
|
||||
Task<List<[Module]>> Get[Module]sAsync(int ModuleId);
|
||||
|
||||
Task<[Module]> Get[Module]Async(int [Module]Id);
|
||||
Task<[Module]> Get[Module]Async(int [Module]Id, int ModuleId);
|
||||
|
||||
Task<[Module]> Add[Module]Async([Module] [Module]);
|
||||
|
||||
Task<[Module]> Update[Module]Async([Module] [Module]);
|
||||
|
||||
Task Delete[Module]Async(int [Module]Id);
|
||||
Task Delete[Module]Async(int [Module]Id, int ModuleId);
|
||||
}
|
||||
}
|
||||
|
@ -18,32 +18,44 @@ namespace [Owner].[Module]s.Services
|
||||
_siteState = siteState;
|
||||
}
|
||||
|
||||
private string Apiurl=> CreateApiUrl(_siteState.Alias, "[Module]");
|
||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "[Module]");
|
||||
|
||||
public async Task<List<[Module]>> Get[Module]sAsync(int ModuleId)
|
||||
{
|
||||
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>($"{Apiurl}?moduleid={ModuleId}");
|
||||
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>(CreateAuthPolicyUrl($"{Apiurl}?moduleid={ModuleId}", ModuleId));
|
||||
return [Module]s.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
|
||||
public async Task<[Module]> Get[Module]Async(int [Module]Id)
|
||||
public async Task<[Module]> Get[Module]Async(int [Module]Id, int ModuleId)
|
||||
{
|
||||
return await GetJsonAsync<[Module]>($"{Apiurl}/{[Module]Id}");
|
||||
return await GetJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
|
||||
}
|
||||
|
||||
public async Task<[Module]> Add[Module]Async([Module] [Module])
|
||||
{
|
||||
return await PostJsonAsync<[Module]>($"{Apiurl}?entityid={[Module].ModuleId}", [Module]);
|
||||
return await PostJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}?entityid={[Module].ModuleId}", [Module].ModuleId), [Module]);
|
||||
}
|
||||
|
||||
public async Task<[Module]> Update[Module]Async([Module] [Module])
|
||||
{
|
||||
return await PutJsonAsync<[Module]>($"{Apiurl}/{[Module].[Module]Id}?entityid={[Module].ModuleId}", [Module]);
|
||||
return await PutJsonAsync<[Module]>(CreateAuthPolicyUrl($"{Apiurl}/{[Module].[Module]Id}", [Module].ModuleId), [Module]);
|
||||
}
|
||||
|
||||
public async Task Delete[Module]Async(int [Module]Id)
|
||||
public async Task Delete[Module]Async(int [Module]Id, int ModuleId)
|
||||
{
|
||||
await DeleteAsync($"{Apiurl}/{[Module]Id}");
|
||||
await DeleteAsync(CreateAuthPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
|
||||
}
|
||||
|
||||
private string CreateAuthPolicyUrl(string Url, int ModuleId)
|
||||
{
|
||||
if (Url.Contains("?"))
|
||||
{
|
||||
return Url + "&entityid=" + ModuleId.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Url + "?entityid=" + ModuleId.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Enums;
|
||||
using Oqtane.Infrastructure;
|
||||
@ -9,21 +10,27 @@ using [Owner].[Module]s.Repository;
|
||||
|
||||
namespace [Owner].[Module]s.Controllers
|
||||
{
|
||||
[Route("{site}/api/[controller]")]
|
||||
[Route("{alias}/api/[controller]")]
|
||||
public class [Module]Controller : Controller
|
||||
{
|
||||
private readonly I[Module]Repository _[Module]s;
|
||||
private readonly ILogManager _logger;
|
||||
protected int _entityId = -1;
|
||||
|
||||
public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger)
|
||||
public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger, IHttpContextAccessor accessor)
|
||||
{
|
||||
_[Module]s = [Module]s;
|
||||
_logger = logger;
|
||||
|
||||
if (accessor.HttpContext.Request.Query.ContainsKey("entityid"))
|
||||
{
|
||||
_entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]);
|
||||
}
|
||||
}
|
||||
|
||||
// GET: api/<controller>?moduleid=x
|
||||
[HttpGet]
|
||||
[Authorize(Roles = Constants.RegisteredRole)]
|
||||
[Authorize(Policy = "ViewModule")]
|
||||
public IEnumerable<[Module]> Get(string moduleid)
|
||||
{
|
||||
return _[Module]s.Get[Module]s(int.Parse(moduleid));
|
||||
@ -31,18 +38,23 @@ namespace [Owner].[Module]s.Controllers
|
||||
|
||||
// GET api/<controller>/5
|
||||
[HttpGet("{id}")]
|
||||
[Authorize(Roles = Constants.RegisteredRole)]
|
||||
[Authorize(Policy = "ViewModule")]
|
||||
public [Module] Get(int id)
|
||||
{
|
||||
return _[Module]s.Get[Module](id);
|
||||
[Module] [Module] = _[Module]s.Get[Module](id);
|
||||
if ([Module] != null && [Module].ModuleId != _entityId)
|
||||
{
|
||||
[Module] = null;
|
||||
}
|
||||
return [Module];
|
||||
}
|
||||
|
||||
// POST api/<controller>
|
||||
[HttpPost]
|
||||
[Authorize(Roles = Constants.AdminRole)]
|
||||
[Authorize(Policy = "EditModule")]
|
||||
public [Module] Post([FromBody] [Module] [Module])
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
if (ModelState.IsValid && [Module].ModuleId == _entityId)
|
||||
{
|
||||
[Module] = _[Module]s.Add[Module]([Module]);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]);
|
||||
@ -52,10 +64,10 @@ namespace [Owner].[Module]s.Controllers
|
||||
|
||||
// PUT api/<controller>/5
|
||||
[HttpPut("{id}")]
|
||||
[Authorize(Roles = Constants.AdminRole)]
|
||||
[Authorize(Policy = "EditModule")]
|
||||
public [Module] Put(int id, [FromBody] [Module] [Module])
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
if (ModelState.IsValid && [Module].ModuleId == _entityId)
|
||||
{
|
||||
[Module] = _[Module]s.Update[Module]([Module]);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]);
|
||||
@ -65,11 +77,15 @@ namespace [Owner].[Module]s.Controllers
|
||||
|
||||
// DELETE api/<controller>/5
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize(Roles = Constants.AdminRole)]
|
||||
[Authorize(Policy = "EditModule")]
|
||||
public void Delete(int id)
|
||||
{
|
||||
_[Module]s.Delete[Module](id);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id);
|
||||
[Module] [Module] = _[Module]s.Get[Module](id);
|
||||
if ([Module] != null && [Module].ModuleId == _entityId)
|
||||
{
|
||||
_[Module]s.Delete[Module](id);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
This is the location where static resources such as images, style sheets, or scripts for this module will be located. Static assets can be organized in subfolders. When the module package is deployed the assets will be extracted under the web root in a folder that matches the module namespace.
|
@ -9,8 +9,8 @@
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<br /><br /><h1 align="center">Please Wait... Upgrade In Progress....</h1>
|
||||
<img src="https://www.oqtane.org/Portals/0/oqtane-black.png" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);" />
|
||||
<br /><br />
|
||||
<h1 align="center">Please Wait... Upgrade In Progress....</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -327,7 +327,7 @@ Oqtane.Interop = {
|
||||
|
||||
while (Chunk = FileChunk.shift()) {
|
||||
PartCount++;
|
||||
var FileName = file.name + ".part_" + PartCount + "_" + TotalParts;
|
||||
var FileName = file.name + ".part_" + PartCount.toString().padStart(3, '0') + "_" + TotalParts.toString().padStart(3, '0');
|
||||
|
||||
var data = new FormData();
|
||||
data.append('folder', folder);
|
||||
|
@ -20,6 +20,7 @@ namespace Oqtane.Models
|
||||
ServerManagerType = "";
|
||||
ControlTypeRoutes = "";
|
||||
ReleaseVersions = "";
|
||||
Runtimes = "";
|
||||
Template = "";
|
||||
}
|
||||
|
||||
@ -45,6 +46,8 @@ namespace Oqtane.Models
|
||||
[NotMapped]
|
||||
public string License { get; set; }
|
||||
[NotMapped]
|
||||
public string Runtimes { get; set; }
|
||||
[NotMapped]
|
||||
public string Dependencies { get; set; }
|
||||
[NotMapped]
|
||||
public string PermissionNames { get; set; }
|
||||
|
@ -19,7 +19,6 @@ namespace Oqtane.Models
|
||||
public string DefaultContainerType { get; set; }
|
||||
public string Icon { get; set; }
|
||||
public bool IsNavigation { get; set; }
|
||||
public bool EditMode { get; set; }
|
||||
public int? UserId { get; set; }
|
||||
public bool IsPersonalizable { get; set; }
|
||||
|
||||
@ -41,5 +40,9 @@ namespace Oqtane.Models
|
||||
public int Level { get; set; }
|
||||
[NotMapped]
|
||||
public bool HasChildren { get; set; }
|
||||
|
||||
[Obsolete("This property is obsolete", false)]
|
||||
[NotMapped]
|
||||
public bool EditMode { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Oqtane.Models
|
||||
{
|
||||
@ -16,9 +17,11 @@ namespace Oqtane.Models
|
||||
public string Icon { get; set; }
|
||||
public bool IsNavigation { get; set; }
|
||||
public bool IsPersonalizable { get; set; }
|
||||
public bool EditMode { get; set; }
|
||||
public string PagePermissions { get; set; }
|
||||
public List<PageTemplateModule> PageTemplateModules { get; set; }
|
||||
|
||||
[Obsolete("This property is obsolete", false)]
|
||||
public bool EditMode { get; set; }
|
||||
}
|
||||
|
||||
public class PageTemplateModule
|
||||
|
@ -4,7 +4,7 @@
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -13,7 +13,7 @@
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
@ -5,8 +5,8 @@ namespace Oqtane.Shared
|
||||
public class Constants
|
||||
{
|
||||
public const string PackageId = "Oqtane.Framework";
|
||||
public const string Version = "1.0.1";
|
||||
public const string ReleaseVersions = "0.9.0,0.9.1,0.9.2,1.0.0,1.0.1";
|
||||
public const string Version = "1.0.3";
|
||||
public const string ReleaseVersions = "0.9.0,0.9.1,0.9.2,1.0.0,1.0.1,1.0.2,1.0.3";
|
||||
|
||||
public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client";
|
||||
public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client";
|
||||
@ -19,6 +19,8 @@ namespace Oqtane.Shared
|
||||
public const string ActionToken = "{Action}";
|
||||
public const string DefaultAction = "Index";
|
||||
public const string AdminPane = "Admin";
|
||||
public const string ModuleDelimiter = "*";
|
||||
public const string UrlParametersDelimiter = "!";
|
||||
|
||||
// Default Module Actions are reserved and should not be used by modules
|
||||
public static readonly string[] DefaultModuleActions = new[] { "Settings", "Import", "Export" };
|
||||
@ -46,6 +48,7 @@ namespace Oqtane.Shared
|
||||
public const string ImageFiles = "jpg,jpeg,jpe,gif,bmp,png";
|
||||
public const string UploadableFiles = "jpg,jpeg,jpe,gif,bmp,png,mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg";
|
||||
public const string ReservedDevices = "CON,NUL,PRN,COM0,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,LPT0,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9,CONIN$,CONOUT$";
|
||||
|
||||
public static readonly char[] InvalidFileNameChars =
|
||||
{
|
||||
'\"', '<', '>', '|', '\0', (Char) 1, (Char) 2, (Char) 3, (Char) 4, (Char) 5, (Char) 6, (Char) 7, (Char) 8,
|
||||
@ -55,4 +58,4 @@ namespace Oqtane.Shared
|
||||
};
|
||||
public static readonly string[] InvalidFileNameEndingChars = { ".", " " };
|
||||
}
|
||||
}
|
||||
}
|
@ -20,8 +20,53 @@ namespace Oqtane.Shared
|
||||
return $"{type.Namespace}, {assemblyName}";
|
||||
}
|
||||
|
||||
public static (string UrlParameters, string Querystring, string Anchor) ParseParameters(string parameters)
|
||||
{
|
||||
// /urlparameters /urlparameters?Id=1 /urlparameters#5 /urlparameters?Id=1#5 /urlparameters?reload#5
|
||||
|
||||
// Id=1 Id=1#5 reload#5 reload
|
||||
|
||||
// #5
|
||||
|
||||
var urlparameters = string.Empty;
|
||||
var querystring = string.Empty;
|
||||
var anchor = string.Empty;
|
||||
|
||||
if (parameters.Contains('#'))
|
||||
{
|
||||
anchor = parameters.Split('#').Last();
|
||||
parameters = parameters.Replace("#" + anchor, "");
|
||||
}
|
||||
|
||||
if (parameters.Contains('?'))
|
||||
{
|
||||
urlparameters = parameters.Split('?').First();
|
||||
querystring = parameters.Replace(urlparameters + "?", "");
|
||||
}
|
||||
else if (parameters.Contains('/'))
|
||||
{
|
||||
urlparameters = parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
querystring = parameters;
|
||||
}
|
||||
|
||||
return (urlparameters, querystring, anchor);
|
||||
}
|
||||
|
||||
public static string NavigateUrl(string alias, string path, string parameters)
|
||||
{
|
||||
string urlparameters;
|
||||
string querystring;
|
||||
string anchor;
|
||||
(urlparameters, querystring, anchor) = ParseParameters(parameters);
|
||||
|
||||
if (!string.IsNullOrEmpty(urlparameters))
|
||||
{
|
||||
if (urlparameters.StartsWith("/")) urlparameters = urlparameters.Remove(0, 1);
|
||||
path += $"/{Constants.UrlParametersDelimiter}/{urlparameters}";
|
||||
}
|
||||
var uriBuilder = new UriBuilder
|
||||
{
|
||||
Path = !string.IsNullOrEmpty(alias)
|
||||
@ -29,17 +74,18 @@ namespace Oqtane.Shared
|
||||
? $"{alias}/{path}"
|
||||
: $"{alias}"
|
||||
: $"{path}",
|
||||
Query = parameters
|
||||
Query = querystring,
|
||||
};
|
||||
|
||||
return uriBuilder.Uri.PathAndQuery;
|
||||
anchor = string.IsNullOrEmpty(anchor) ? "" : "#" + anchor;
|
||||
var navigateUrl = uriBuilder.Uri.PathAndQuery + anchor;
|
||||
return navigateUrl;
|
||||
}
|
||||
|
||||
public static string EditUrl(string alias, string path, int moduleid, string action, string parameters)
|
||||
{
|
||||
if (moduleid != -1)
|
||||
{
|
||||
path += $"/{moduleid}";
|
||||
path += $"/{Constants.ModuleDelimiter}/{moduleid}";
|
||||
if (!string.IsNullOrEmpty(action))
|
||||
{
|
||||
path += $"/{action}";
|
||||
@ -136,6 +182,7 @@ namespace Oqtane.Shared
|
||||
stringBuilder.Append(RemapInternationalCharToAscii(c));
|
||||
prevdash = false;
|
||||
break;
|
||||
|
||||
case UnicodeCategory.SpaceSeparator:
|
||||
case UnicodeCategory.ConnectorPunctuation:
|
||||
case UnicodeCategory.DashPunctuation:
|
||||
@ -250,7 +297,7 @@ namespace Oqtane.Shared
|
||||
|
||||
public static string PathCombine(params string[] segments)
|
||||
{
|
||||
var separators = new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar};
|
||||
var separators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
|
||||
|
||||
for (int i = 1; i < segments.Length; i++)
|
||||
{
|
||||
@ -284,7 +331,6 @@ namespace Oqtane.Shared
|
||||
!Constants.ReservedDevices.Split(',').Contains(name.ToUpper().Split('.')[0]));
|
||||
}
|
||||
|
||||
|
||||
public static bool TryGetQueryValue(
|
||||
this Uri uri,
|
||||
string key,
|
||||
@ -304,7 +350,7 @@ namespace Oqtane.Shared
|
||||
{
|
||||
value = defaultValue;
|
||||
string s;
|
||||
return uri.TryGetQueryValue(key, out s, (string) null) && int.TryParse(s, out value);
|
||||
return uri.TryGetQueryValue(key, out s, (string)null) && int.TryParse(s, out value);
|
||||
}
|
||||
|
||||
public static Dictionary<string, string> ParseQueryString(string query)
|
||||
@ -314,7 +360,7 @@ namespace Oqtane.Shared
|
||||
{
|
||||
query = query.Substring(1);
|
||||
string str = query;
|
||||
char[] separator = new char[1] {'&'};
|
||||
char[] separator = new char[1] { '&' };
|
||||
foreach (string key in str.Split(separator, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (key != "")
|
||||
@ -333,4 +379,4 @@ namespace Oqtane.Shared
|
||||
return dictionary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -13,7 +13,7 @@
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.3</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@ -13,7 +13,7 @@
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.3</PackageReleaseNotes>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
@ -11,12 +11,13 @@ namespace Oqtane.Upgrade
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// requires 2 arguments - the ContentRootPath and the WebRootPath of the site
|
||||
|
||||
// for testing purposes set Oqtane.Upgrade as startup project and modify values below
|
||||
//Array.Resize(ref args, 2);
|
||||
//args[0] = @"C:\yourpath\oqtane.framework\Oqtane.Server";
|
||||
//args[1] = @"C:\yourpath\oqtane.framework\Oqtane.Server\wwwroot";
|
||||
|
||||
// requires 2 arguments - the contentrootpath and the webrootpath of the site
|
||||
if (args.Length == 2)
|
||||
{
|
||||
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||
@ -47,14 +48,19 @@ namespace Oqtane.Upgrade
|
||||
{
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
switch (Path.GetDirectoryName(entry.FullName).Split('\\')[0])
|
||||
string filename = Path.GetFileName(entry.FullName);
|
||||
if (!string.IsNullOrEmpty(filename))
|
||||
{
|
||||
case "lib":
|
||||
files.Add(Path.Combine(binfolder, Path.GetFileName(entry.FullName)));
|
||||
break;
|
||||
case "wwwroot":
|
||||
files.Add(Path.Combine(webrootfolder, entry.FullName.Replace("wwwroot/", "").Replace("/","\\")));
|
||||
break;
|
||||
// use top level folder to determine location to extract files
|
||||
switch (Path.GetDirectoryName(entry.FullName).Split(Path.DirectorySeparatorChar)[0])
|
||||
{
|
||||
case "lib":
|
||||
files.Add(Path.Combine(binfolder, filename));
|
||||
break;
|
||||
case "wwwroot":
|
||||
files.Add(Path.Combine(webrootfolder.Replace(Path.DirectorySeparatorChar + "wwwroot", ""), entry.FullName.Replace('/', Path.DirectorySeparatorChar)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,74 +68,100 @@ namespace Oqtane.Upgrade
|
||||
// ensure files are not locked
|
||||
if (CanAccessFiles(files))
|
||||
{
|
||||
// create backup
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (File.Exists(file + ".bak"))
|
||||
{
|
||||
File.Delete(file + ".bak");
|
||||
}
|
||||
File.Move(file, file + ".bak");
|
||||
}
|
||||
|
||||
// extract files
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
using (ZipArchive archive = ZipFile.OpenRead(packagename))
|
||||
{
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
string filename = "";
|
||||
switch (Path.GetDirectoryName(entry.FullName).Split('\\')[0])
|
||||
{
|
||||
case "lib":
|
||||
filename = Path.Combine(binfolder, Path.GetFileName(entry.FullName));
|
||||
break;
|
||||
case "wwwroot":
|
||||
filename = Path.Combine(webrootfolder, entry.FullName.Replace("wwwroot/", "").Replace("/", "\\"));
|
||||
break;
|
||||
}
|
||||
if (files.Contains(filename))
|
||||
{
|
||||
entry.ExtractToFile(filename, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
// an error occurred extracting a file
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
// clean up backup
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (File.Exists(file + ".bak"))
|
||||
{
|
||||
File.Delete(file + ".bak");
|
||||
}
|
||||
}
|
||||
|
||||
// delete package
|
||||
File.Delete(packagename);
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore on failure
|
||||
// create backup
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (File.Exists(file))
|
||||
{
|
||||
File.Delete(file);
|
||||
// remove previous backup if it exists
|
||||
if (File.Exists(file + ".bak"))
|
||||
{
|
||||
File.Delete(file + ".bak");
|
||||
}
|
||||
File.Move(file, file + ".bak");
|
||||
}
|
||||
}
|
||||
|
||||
// extract files
|
||||
bool success = true;
|
||||
try
|
||||
{
|
||||
using (ZipArchive archive = ZipFile.OpenRead(packagename))
|
||||
{
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
string filename = Path.GetFileName(entry.FullName);
|
||||
if (!string.IsNullOrEmpty(filename))
|
||||
{
|
||||
// use top level folder to determine location to extract files
|
||||
switch (Path.GetDirectoryName(entry.FullName).Split(Path.DirectorySeparatorChar)[0])
|
||||
{
|
||||
case "lib":
|
||||
filename = Path.Combine(binfolder, filename);
|
||||
break;
|
||||
case "wwwroot":
|
||||
filename = Path.Combine(webrootfolder.Replace(Path.DirectorySeparatorChar + "wwwroot", ""), entry.FullName.Replace('/', Path.DirectorySeparatorChar));
|
||||
break;
|
||||
}
|
||||
if (files.Contains(filename))
|
||||
{
|
||||
if (!Directory.Exists(Path.GetDirectoryName(filename)))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(filename));
|
||||
}
|
||||
entry.ExtractToFile(filename, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// an error occurred extracting a file
|
||||
success = false;
|
||||
Console.WriteLine("Update Not Successful: Error Extracting Files From Package - " + ex.Message);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
// clean up backup
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (File.Exists(file + ".bak"))
|
||||
{
|
||||
File.Delete(file + ".bak");
|
||||
}
|
||||
}
|
||||
|
||||
// delete package
|
||||
File.Delete(packagename);
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore on failure
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (File.Exists(file))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
if (File.Exists(file + ".bak"))
|
||||
{
|
||||
File.Move(file + ".bak", file);
|
||||
}
|
||||
}
|
||||
File.Move(file + ".bak", file);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Update Not Successful: " + ex.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Upgrade Not Successful: Some Files Are Locked");
|
||||
}
|
||||
|
||||
// bring the app back online
|
||||
@ -138,7 +170,19 @@ namespace Oqtane.Upgrade
|
||||
File.Delete(Path.Combine(contentrootfolder, "app_offline.htm"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Framework Upgrade Package Not Found");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Framework Upgrade Folder " + deployfolder + " Does Not Exist");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Missing ContentRootPath and WebRootPath Parameters");
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,8 +202,15 @@ namespace Oqtane.Upgrade
|
||||
{
|
||||
try
|
||||
{
|
||||
stream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.None);
|
||||
locked = false;
|
||||
if (File.Exists(filepath))
|
||||
{
|
||||
stream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.None);
|
||||
locked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
catch // file is locked by another process
|
||||
{
|
||||
|
30
README.md
30
README.md
@ -1,23 +1,35 @@
|
||||
# Oqtane Framework
|
||||
Oqtane is a Modular Application Framework for Blazor
|
||||
|
||||
[](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Foqtane%2Foqtane.framework%2Fmaster%2Fazuredeploy.json)
|
||||
|
||||

|
||||
|
||||
Oqtane uses Blazor, an open source and cross-platform web UI framework for building single-page apps using .NET and C# instead of JavaScript. Blazor apps are composed of reusable web UI components implemented using C#, HTML, and CSS. Both client and server code is written in C#, allowing you to share code and libraries.
|
||||
|
||||
Oqtane is being developed based on some fundamental principles which are outlined in the [Oqtane Philosophy](https://www.oqtane.org/Resources/Blog/PostId/538/oqtane-philosophy).
|
||||
|
||||
Please note that this project is owned by the .NET Foundation and is governed by the **[.NET Foundation Contributor Covenant Code of Conduct](https://dotnetfoundation.org/code-of-conduct)**
|
||||
|
||||
**To get started with Oqtane:**
|
||||
# Getting Started
|
||||
|
||||
1. Install **[.NET Core 3.1 SDK (v3.1.300)](https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.300-windows-x64-installer)**.
|
||||
|
||||
2. Install the Preview edition of [Visual Studio 2019](https://visualstudio.microsoft.com/vs/preview/) (version 16.6 or higher) with the **ASP.NET and web development** workload enabled. Oqtane works with all editions of Visual Studio from Community to Enterprise. If you do not have a SQL Server installation available already and you wish to use LocalDB for development, you must also install the **.NET desktop development workload**.
|
||||
**Using the latest code:**
|
||||
|
||||
3. Download or Clone the Oqtane source code to your local system. Open the **Oqtane.sln** solution file and Build the solution.
|
||||
- Install **[.NET Core 3.1 SDK (v3.1.300)](https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.300-windows-x64-installer)**.
|
||||
|
||||
NOTE: If you have already installed a previous version of Oqtane and you wish to do a clean database install, simply reset the DefaultConnection value in the Oqtane.Server\appsettings.json file to "". This will trigger a re-install when you run the application which will execute the database installation scripts.
|
||||
- Install the Preview edition of [Visual Studio 2019](https://visualstudio.microsoft.com/vs/preview/) (Community, Professional, and Enterprise Editions are all supported) with the **ASP.NET and web development** workload enabled. Oqtane works with all editions of Visual Studio from Community to Enterprise. If you do not have a SQL Server installation available already and you wish to use LocalDB for development, you must also install the **.NET desktop development workload**.
|
||||
|
||||
- Download or Clone the Oqtane source code to your local system. Open the **Oqtane.sln** solution file and Build the solution.
|
||||
|
||||
**Using an official release:**
|
||||
|
||||
- A detailed set of instructions for installing Oqtane on IIS is located here: [Installing Oqtane on IIS](https://www.oqtane.org/Resources/Blog/PostId/542/installing-oqtane-on-iis)
|
||||
|
||||
**Additional Instructions**
|
||||
|
||||
- If you have already installed a previous version of Oqtane and you wish to do a clean database install, simply reset the DefaultConnection value in the Oqtane.Server\appsettings.json file to "". This will trigger a re-install when you run the application which will execute the database installation scripts.
|
||||
|
||||
NOTE: If you want to submit pull requests make sure you install the [Github Extension For Visual Studio](https://visualstudio.github.com/). It is recommended you ignore any local changes you have made to the appsettings.json file before you submit a pull request. To automate this activity, open a command prompt and navigate to the /Oqtane.Server/ folder and enter the command "git update-index --skip-worktree appsettings.json"
|
||||
- If you want to submit pull requests make sure you install the [Github Extension For Visual Studio](https://visualstudio.github.com/). It is recommended you ignore any local changes you have made to the appsettings.json file before you submit a pull request. To automate this activity, open a command prompt and navigate to the /Oqtane.Server/ folder and enter the command "git update-index --skip-worktree appsettings.json"
|
||||
|
||||
# Roadmap
|
||||
This project is a work in progress and the schedule for implementing enhancements is dependent upon the availability of community members who are willing/able to assist.
|
||||
@ -53,6 +65,8 @@ Oqtane was created by [Shaun Walker](https://www.linkedin.com/in/shaunbrucewalke
|
||||
|
||||
# Release Announcements
|
||||
|
||||
[Oqtane 1.0.1](https://www.oqtane.org/Resources/Blog/PostId/541/oqtane-builds-momentum-with-101-release)
|
||||
|
||||
[Oqtane 1.0](https://www.oqtane.org/Resources/Blog/PostId/540/announcing-oqtane-10-a-modular-application-framework-for-blazor)
|
||||
|
||||
[Oqtane POC](https://www.oqtane.org/Resources/Blog/PostId/520/announcing-oqtane-a-modular-application-framework-for-blazor)
|
||||
@ -87,7 +101,7 @@ Control panel for adding, editing, and deleting pages as well as adding new modu
|
||||
|
||||

|
||||
|
||||
Admin dashboard for accessing the variuous administrative features of the framework:
|
||||
Admin dashboard for accessing the various administrative features of the framework:
|
||||
|
||||

|
||||
|
||||
|
197
azuredeploy.json
Normal file
197
azuredeploy.json
Normal file
@ -0,0 +1,197 @@
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.1",
|
||||
"parameters": {
|
||||
"sqlServerName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the sql server. It has to be unique."
|
||||
}
|
||||
},
|
||||
"databaseName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the sql databaseName. It has to be unique."
|
||||
}
|
||||
},
|
||||
"sqlAdministratorLogin": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The admin user of the SQL Server"
|
||||
}
|
||||
},
|
||||
"sqlAdministratorLoginPassword": {
|
||||
"type": "securestring",
|
||||
"metadata": {
|
||||
"description": "The password of the admin user of the SQL Server"
|
||||
}
|
||||
},
|
||||
"BlazorWebsiteName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "The name of the website. It has to be unique."
|
||||
}
|
||||
},
|
||||
"BlazorSKU": {
|
||||
"type": "string",
|
||||
"allowedValues": [
|
||||
"Free",
|
||||
"Shared",
|
||||
"Basic",
|
||||
"Standard"
|
||||
],
|
||||
"defaultValue": "Standard"
|
||||
},
|
||||
"BlazorWorkerSize": {
|
||||
"type": "string",
|
||||
"allowedValues": [
|
||||
"0",
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"defaultValue": "0"
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"defaultValue": "[resourceGroup().location]",
|
||||
"metadata": {
|
||||
"description": "Location for all resources."
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"hostingPlanName": "[concat('Oqtane-hostingplan-', uniqueString(resourceGroup().id))]",
|
||||
"databaseEdition": "Standard",
|
||||
"databaseCollation": "SQL_Latin1_General_CP1_CI_AS",
|
||||
"databaseServiceObjectiveName": "Standard"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"name": "[parameters('sqlServerName')]",
|
||||
"type": "Microsoft.Sql/servers",
|
||||
"apiVersion": "2014-04-01",
|
||||
"location": "[resourceGroup().location]",
|
||||
"tags": {
|
||||
"displayName": "SqlServer"
|
||||
},
|
||||
"properties": {
|
||||
"administratorLogin": "[parameters('sqlAdministratorLogin')]",
|
||||
"administratorLoginPassword": "[parameters('sqlAdministratorLoginPassword')]",
|
||||
"version": "12.0"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"name": "[parameters('databaseName')]",
|
||||
"type": "databases",
|
||||
"apiVersion": "2015-01-01",
|
||||
"location": "[resourceGroup().location]",
|
||||
"tags": {
|
||||
"displayName": "Database"
|
||||
},
|
||||
"properties": {
|
||||
"edition": "[variables('databaseEdition')]",
|
||||
"collation": "[variables('databaseCollation')]",
|
||||
"requestedServiceObjectiveName": "[variables('databaseServiceObjectiveName')]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[parameters('sqlServerName')]"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"comments": "Transparent Data Encryption",
|
||||
"name": "current",
|
||||
"type": "transparentDataEncryption",
|
||||
"apiVersion": "2014-04-01-preview",
|
||||
"properties": {
|
||||
"status": "Enabled"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[parameters('databaseName')]"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "AllowAllMicrosoftAzureIps",
|
||||
"type": "firewallrules",
|
||||
"apiVersion": "2014-04-01",
|
||||
"location": "[resourceGroup().location]",
|
||||
"properties": {
|
||||
"endIpAddress": "0.0.0.0",
|
||||
"startIpAddress": "0.0.0.0"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[parameters('sqlServerName')]"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "[variables('hostingPlanName')]",
|
||||
"type": "Microsoft.Web/serverfarms",
|
||||
"location": "[resourceGroup().location]",
|
||||
"apiVersion": "2014-06-01",
|
||||
"dependsOn": [],
|
||||
"tags": {
|
||||
"displayName": "Blazor"
|
||||
},
|
||||
"properties": {
|
||||
"name": "[variables('hostingPlanName')]",
|
||||
"sku": "[parameters('BlazorSKU')]",
|
||||
"workerSize": "[parameters('BlazorWorkerSize')]",
|
||||
"numberOfWorkers": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2018-02-01",
|
||||
"name": "[parameters('BlazorWebsiteName')]",
|
||||
"type": "Microsoft.Web/sites",
|
||||
"location": "[parameters('location')]",
|
||||
"dependsOn": [
|
||||
"[variables('hostingPlanName')]"
|
||||
],
|
||||
"tags": {
|
||||
"[concat('hidden-related:', resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName')))]": "empty",
|
||||
"displayName": "Website"
|
||||
},
|
||||
"properties": {
|
||||
"name": "[parameters('BlazorWebsiteName')]",
|
||||
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
|
||||
"siteConfig": {
|
||||
"webSocketsEnabled": true
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"type": "sourcecontrols",
|
||||
"apiVersion": "2018-02-01",
|
||||
"name": "web",
|
||||
"location": "[parameters('location')]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/sites', parameters('BlazorWebsiteName'))]",
|
||||
"[resourceId('Microsoft.Web/Sites/config', parameters('BlazorWebsiteName'), 'connectionstrings')]"
|
||||
],
|
||||
"properties": {
|
||||
"RepoUrl": "https://github.com/oqtane/oqtane.framework.git",
|
||||
"branch": "master",
|
||||
"IsManualIntegration": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "2018-02-01",
|
||||
"type": "config",
|
||||
"name": "connectionstrings",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/sites', parameters('BlazorWebsiteName'))]"
|
||||
],
|
||||
"properties": {
|
||||
"DefaultConnection": {
|
||||
"value": "[concat('Data Source=tcp:', reference(concat('Microsoft.Sql/servers/', parameters('sqlserverName'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('databaseName'), ';User Id=', parameters('sqlAdministratorLogin'), '@', reference(concat('Microsoft.Sql/servers/', parameters('sqlserverName'))).fullyQualifiedDomainName, ';Password=', parameters('sqlAdministratorLoginPassword'), ';')]",
|
||||
"type": "SQLAzure"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user