modified all admin UIs to position action buttons on the left side of grids and implemented ActionDialog throughout rather than dedicated delete components

This commit is contained in:
Shaun Walker 2019-11-04 23:29:35 -05:00
parent 156f5b5f94
commit ab564f7244
32 changed files with 737 additions and 732 deletions

View File

@ -17,7 +17,7 @@ else
<th>Name</th>
</Header>
<Row>
<td><ActionDialog Header="Delete File" Message="@("Are You Sure You Wish To Delete " + context + "?")" Action="Delete" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" /></td>
<td><ActionDialog Header="Delete File" Message="@("Are You Sure You Wish To Delete " + context + "?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" /></td>
<td><a href="@(uri.Scheme + "://" + uri.Authority + "/" + PageState.Site.SiteRootPath + context)" target="_new">@context</a></td>
</Row>
</Pager>

View File

@ -10,26 +10,26 @@
}
else
{
<ActionLink Action="Add" Text="Install Module" Style="float: right; margin: 10px;" />
<ActionLink Action="Add" Text="Install Module" />
<Pager Items="@moduledefinitions">
<Header>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>Name</th>
<th>Version</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</Header>
<Row>
<td>@context.Name</td>
<td>@context.Version</td>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" /></td>
<td>
@if (context.AssemblyName != "Oqtane.Client")
{
<button type="button" class="btn btn-danger" @onclick=@(async () => await DeleteModule(context.ModuleDefinitionId, context.SiteId))>Delete</button>
<ActionDialog Header="Delete Module" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Module?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" />
}
</td>
<td>@context.Name</td>
<td>@context.Version</td>
<td>
@if (UpgradeAvailable(context.ModuleDefinitionName, context.Version))
{
@ -47,10 +47,18 @@ else
List<Package> packages;
protected override async Task OnInitializedAsync()
{
try
{
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
packages = await PackageService.GetPackagesAsync("module");
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Modules {Error}", ex.Message);
AddModuleMessage("Error Loading Modules", MessageType.Error);
}
}
private bool UpgradeAvailable(string moduledefinitionname, string version)
{
@ -64,15 +72,33 @@ else
}
private async Task DownloadModule(string moduledefinitionname, string version)
{
try
{
await PackageService.DownloadPackageAsync(moduledefinitionname, version, "Modules");
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", moduledefinitionname, version);
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version} {Error}", moduledefinitionname, version, ex.Message);
AddModuleMessage("Error Downloading Module", MessageType.Error);
}
}
private async Task DeleteModule(int moduledefinitionid, int siteid)
private async Task DeleteModule(ModuleDefinition ModuleDefinition)
{
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduledefinitionid, siteid);
try
{
await ModuleDefinitionService.DeleteModuleDefinitionAsync(ModuleDefinition.ModuleDefinitionId, ModuleDefinition.SiteId);
await logger.LogInformation("Module Deleted {ModuleDefinition}", ModuleDefinition);
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Module {ModuleDefinition} {Error}", ModuleDefinition, ex.Message);
AddModuleMessage("Error Deleting Module", MessageType.Error);
}
}
}

View File

@ -1,181 +0,0 @@
@namespace Oqtane.Modules.Admin.Pages
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IPageService PageService
@inject IThemeService ThemeService
<table class="table table-borderless">
<tr>
<td>
<label for="Name" class="control-label">Name: </label>
</td>
<td>
<input class="form-control" @bind="@name" disabled />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Path: </label>
</td>
<td>
<input class="form-control" @bind="@path" disabled />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Parent: </label>
</td>
<td>
<select class="form-control" @bind="@parentid" disabled>
<option value="">&lt;Select Parent&gt;</option>
@foreach (Page p in PageState.Pages)
{
<option value="@p.PageId">@p.Name</option>
}
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Navigation? </label>
</td>
<td>
<select class="form-control" @bind="@isnavigation" disabled>
<option value="True">Yes</option>
<option value="False">No</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Default Mode? </label>
</td>
<td>
<select class="form-control" @bind="@mode" disabled>
<option value="view">View Mode</option>
<option value="edit">Edit Mode</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Theme: </label>
</td>
<td>
<select class="form-control" @bind="@themetype" disabled>
<option value="">&lt;Select Theme&gt;</option>
@foreach (KeyValuePair<string, string> item in themes)
{
if (item.Key == themetype)
{
<option value="@item.Key" selected>@item.Value</option>
}
else
{
<option value="@item.Key">@item.Value</option>
}
}
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Layout: </label>
</td>
<td>
<select class="form-control" @bind="@layouttype" disabled>
<option value="">&lt;Select Layout&gt;</option>
@foreach (KeyValuePair<string, string> panelayout in panelayouts)
{
<option value="@panelayout.Key">@panelayout.Value</option>
}
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Icon: </label>
</td>
<td>
<input class="form-control" @bind="@icon" disabled />
</td>
</tr>
</table>
<button type="button" class="btn btn-danger" @onclick="DeletePage">Delete</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
@code {
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
Dictionary<string, string> themes = new Dictionary<string, string>();
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
int PageId;
string name;
string path;
string parentid = "";
string isnavigation;
string mode;
string themetype;
string layouttype;
string icon;
string permissions;
string createdby;
DateTime createdon;
string modifiedby;
DateTime modifiedon;
string deletedby;
DateTime? deletedon;
protected override async Task OnInitializedAsync()
{
try
{
themes = ThemeService.GetThemeTypes(PageState.Themes);
PageId = Int32.Parse(PageState.QueryString["id"]);
Page page = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault();
if (page != null)
{
name = page.Name;
path = page.Path;
isnavigation = page.IsNavigation.ToString();
mode = (page.EditMode) ? "edit" : "view";
themetype = page.ThemeType;
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
layouttype = page.LayoutType;
icon = page.Icon;
permissions = page.Permissions;
createdby = page.CreatedBy;
createdon = page.CreatedOn;
modifiedby = page.ModifiedBy;
modifiedon = page.ModifiedOn;
deletedby = page.DeletedBy;
deletedon = page.DeletedOn;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Page {PageId} {Error}", PageId, ex.Message);
AddModuleMessage("Error Loading Page", MessageType.Error);
}
}
private async Task DeletePage()
{
try
{
await PageService.DeletePageAsync(PageId);
await logger.LogInformation("Page Deleted {PageId}", PageId);
NavigationManager.NavigateTo(NavigateUrl("", Reload.Site)); // redirect to home page
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Page {PageId} {Error}", PageId, ex.Message);
AddModuleMessage("Error Deleting Page", MessageType.Error);
}
}
}

View File

@ -5,18 +5,18 @@
@if (PageState.Pages != null)
{
<ActionLink Action="Add" Text="Add Page" Style="float: right; margin: 10px;" />
<ActionLink Action="Add" Text="Add Page" />
<Pager Items="@PageState.Pages.Where(item => !item.IsDeleted)">
<Header>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>Name</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</Header>
<Row>
<td>@(new string('-', context.Level * 2))@(context.Name)</td>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.PageId.ToString())" /></td>
<td><button @onclick="@(() => Delete(context))" class="btn btn-danger">Delete</button></td>
<td><ActionDialog Header="Delete Page" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Page?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" /></td>
<td>@(new string('-', context.Level * 2))@(context.Name)</td>
</Row>
</Pager>
}
@ -24,18 +24,19 @@
@code {
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
private async Task Delete(Page Page)
private async Task DeletePage(Page Page)
{
try
{
Page.IsDeleted = true;
await PageService.UpdatePageAsync(Page);
await logger.LogInformation("Page Deleted {Page}", Page);
NavigationManager.NavigateTo(NavigateUrl("admin/pages", Reload.Site));
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Pages {Error}", ex.Message);
AddModuleMessage("Error Loading Pages", MessageType.Error);
await logger.LogError(ex, "Error Deleting Page {Page} {Error}", Page, ex.Message);
AddModuleMessage("Error Deleting Page", MessageType.Error);
}
}
}

View File

@ -1,94 +0,0 @@
@namespace Oqtane.Modules.Admin.Roles
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IRoleService RoleService
<table class="table table-borderless">
<tr>
<td>
<label for="Name" class="control-label">Name: </label>
</td>
<td>
<input class="form-control" @bind="@name" readonly />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Description: </label>
</td>
<td>
<textarea class="form-control" @bind="@description" rows="5" readonly />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Auto Assigned? </label>
</td>
<td>
<select class="form-control" @bind="@isautoassigned" readonly>
<option value="True">Yes</option>
<option value="False">No</option>
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">System Role? </label>
</td>
<td>
<select class="form-control" @bind="@issystem" readonly>
<option value="True">Yes</option>
<option value="False">No</option>
</select>
</td>
</tr>
</table>
<button type="button" class="btn btn-success" @onclick="DeleteRole">Delete</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
@code {
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
int roleid;
string name = "";
string description = "";
string isautoassigned = "False";
string issystem = "False";
protected override async Task OnInitializedAsync()
{
try
{
roleid = Int32.Parse(PageState.QueryString["id"]);
Role role = await RoleService.GetRoleAsync(roleid);
if (role != null)
{
name = role.Name;
description = role.Description;
isautoassigned = role.IsAutoAssigned.ToString();
issystem = role.IsSystem.ToString();
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Role {RoleId} {Error}", roleid, ex.Message);
AddModuleMessage("Error Loading Role", MessageType.Error);
}
}
private async Task DeleteRole()
{
try
{
await RoleService.DeleteRoleAsync(roleid);
await logger.LogInformation("Role Deleted {RoleId}", roleid);
NavigationManager.NavigateTo(NavigateUrl());
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Role {RoleId} {Error}", roleid, ex.Message);
AddModuleMessage("Error Deleting Role", MessageType.Error);
}
}
}

View File

@ -8,18 +8,18 @@
}
else
{
<ActionLink Action="Add" Text="Add Role" Style="float: right; margin: 10px;" />
<ActionLink Action="Add" Text="Add Role" />
<Pager Items="@Roles">
<Header>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>Name</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</Header>
<Row>
<td>@context.Name</td>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.RoleId.ToString())" /></td>
<td><ActionLink Action="Delete" Parameters="@($"id=" + context.RoleId.ToString())" Class="btn btn-danger" /></td>
<td><ActionDialog Header="Delete Role" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Role?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteRole(context))" /></td>
<td>@context.Name</td>
</Row>
</Pager>
}
@ -29,8 +29,23 @@ else
List<Role> Roles;
protected override async Task OnInitializedAsync()
protected override async Task OnParametersSetAsync()
{
Roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
}
private async Task DeleteRole(Role Role)
{
try
{
await RoleService.DeleteRoleAsync(Role.RoleId);
await logger.LogInformation("Role Deleted {Role}", Role);
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Role {Role} {Error}", Role, ex.Message);
AddModuleMessage("Error Deleting Role", MessageType.Error);
}
}
}

View File

@ -1,185 +0,0 @@
@namespace Oqtane.Modules.Admin.Sites
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject ISiteService SiteService
@inject IThemeService ThemeService
@if (themes == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table table-borderless">
<tr>
<td>
<label for="Name" class="control-label">Name: </label>
</td>
<td>
<input class="form-control" @bind="@name" disabled />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Aliases: </label>
</td>
<td>
<textarea class="form-control" @bind="@urls" rows="3" disabled />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Logo: </label>
</td>
<td>
<input class="form-control" @bind="@logo" disabled />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Default Theme: </label>
</td>
<td>
<select class="form-control" @bind="@themetype" disabled>
<option value="">&lt;Select Theme&gt;</option>
@foreach (KeyValuePair<string, string> item in themes)
{
if (item.Key == themetype)
{
<option value="@item.Key" selected>@item.Value</option>
}
else
{
<option value="@item.Key">@item.Value</option>
}
}
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Default Layout: </label>
</td>
<td>
<select class="form-control" @bind="@layouttype" disabled>
<option value="">&lt;Select Layout&gt;</option>
@foreach (KeyValuePair<string, string> panelayout in panelayouts)
{
<option value="@panelayout.Key">@panelayout.Value</option>
}
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Default Container: </label>
</td>
<td>
<select class="form-control" @bind="@containertype" disabled>
<option value="">&lt;Select Container&gt;</option>
@foreach (KeyValuePair<string, string> container in containers)
{
<option value="@container.Key">@container.Value</option>
}
</select>
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Is Deleted? </label>
</td>
<td>
<select class="form-control" @bind="@isdeleted" disabled>
<option value="True">Yes</option>
<option value="False">No</option>
</select>
</td>
</tr>
</table>
<button type="button" class="btn btn-success" @onclick="DeleteSite">Delete</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
}
@code {
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
Dictionary<string, string> themes = new Dictionary<string, string>();
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
Dictionary<string, string> containers = new Dictionary<string, string>();
Alias Alias;
int siteid;
string name = "";
List<Alias> aliases;
string urls = "";
string logo = "";
string themetype;
string layouttype;
string containertype;
string createdby;
DateTime createdon;
string modifiedby;
DateTime modifiedon;
string deletedby;
DateTime? deletedon;
string isdeleted;
protected override async Task OnInitializedAsync()
{
try
{
themes = ThemeService.GetThemeTypes(PageState.Themes);
containers = ThemeService.GetContainerTypes(PageState.Themes);
Alias = PageState.Aliases.Where(item => item.AliasId == Int32.Parse(PageState.QueryString["id"])).FirstOrDefault();
siteid = Alias.SiteId;
Site site = await SiteService.GetSiteAsync(siteid, Alias);
if (site != null)
{
name = site.Name;
aliases = PageState.Aliases.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList();
foreach (Alias alias in aliases)
{
urls += alias.Name + "\n";
}
logo = site.Logo;
themetype = site.DefaultThemeType;
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
layouttype = site.DefaultLayoutType;
containertype = site.DefaultContainerType;
createdby = site.CreatedBy;
createdon = site.CreatedOn;
modifiedby = site.ModifiedBy;
modifiedon = site.ModifiedOn;
deletedby = site.DeletedBy;
deletedon = site.DeletedOn;
isdeleted = site.IsDeleted.ToString();
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Site {SiteId} {Error}", siteid, ex.Message);
AddModuleMessage("Error Loading Site", MessageType.Error);
}
}
private async Task DeleteSite()
{
try
{
await SiteService.DeleteSiteAsync(siteid, Alias);
await logger.LogInformation("Sited Deleted {SiteId}", siteid);
NavigationManager.NavigateTo(NavigateUrl());
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Site {Error}", ex.Message);
AddModuleMessage(ex.Message, MessageType.Error);
}
}
}

View File

@ -2,6 +2,7 @@
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IAliasService AliasService
@inject ISiteService SiteService
@if (sites == null)
{
@ -9,18 +10,18 @@
}
else
{
<ActionLink Action="Add" Text="Add Site" Style="float: right; margin: 10px;" />
<ActionLink Action="Add" Text="Add Site" />
<Pager Items="@sites">
<Header>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>Name</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</Header>
<Row>
<td><a href="@(scheme + context.Name)">@context.Name</a></td>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.AliasId.ToString())" /></td>
<td><ActionLink Action="Delete" Parameters="@($"id=" + context.AliasId.ToString())" Class="btn btn-danger" /></td>
<td><ActionDialog Header="Delete Site" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Site?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteSite(context))" /></td>
<td><a href="@(scheme + context.Name)">@context.Name</a></td>
</Row>
</Pager>
}
@ -31,7 +32,7 @@ else
List<Alias> sites;
string scheme;
protected override void OnInitialized()
protected override void OnParametersSet()
{
Uri uri = new Uri(NavigationManager.Uri);
scheme = uri.Scheme + "://";
@ -45,4 +46,19 @@ else
}
}
}
private async Task DeleteSite(Alias Alias)
{
try
{
await SiteService.DeleteSiteAsync(Alias.SiteId, Alias);
await logger.LogInformation("Sited Deleted {Alias}", Alias);
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Site {Error}", ex.Message);
AddModuleMessage("Error Deleting Site", MessageType.Error);
}
}
}

View File

@ -1,80 +0,0 @@
@namespace Oqtane.Modules.Admin.Tenants
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject ITenantService TenantService
<table class="table table-borderless">
<tr>
<td>
<label for="Name" class="control-label">Name: </label>
</td>
<td>
<input class="form-control" @bind="@name" readonly />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Connection String: </label>
</td>
<td>
<input class="form-control" @bind="@connectionstring" readonly />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Schema: </label>
</td>
<td>
<input class="form-control" @bind="@schema" readonly />
</td>
</tr>
</table>
<button type="button" class="btn btn-success" @onclick="DeleteTenant">Delete</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
@code {
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
int tenantid;
string name = "";
string connectionstring = "";
string schema = "";
protected override async Task OnInitializedAsync()
{
try
{
tenantid = Int32.Parse(PageState.QueryString["id"]);
Tenant tenant = await TenantService.GetTenantAsync(tenantid);
if (tenant != null)
{
name = tenant.Name;
connectionstring = tenant.DBConnectionString;
schema = tenant.DBSchema;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Tenant {TenantId} {Error}", tenantid, ex.Message);
AddModuleMessage(ex.Message, MessageType.Error);
}
}
private async Task DeleteTenant()
{
try
{
Tenant tenant = await TenantService.GetTenantAsync(tenantid);
if (tenant != null)
{
await TenantService.DeleteTenantAsync(tenantid);
await logger.LogInformation("Tenant Deleted {TenantId}", tenantid);
NavigationManager.NavigateTo(NavigateUrl());
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Tenant {TenantId} {Error}", tenantid, ex.Message);
AddModuleMessage("Error Deleting Tenant", MessageType.Error);
}
}
}

View File

@ -8,18 +8,18 @@
}
else
{
<ActionLink Action="Add" Text="Add Tenant" Style="float: right; margin: 10px;" />
<ActionLink Action="Add" Text="Add Tenant" />
<Pager Items="@tenants">
<Header>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>Name</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</Header>
<Row>
<td>@context.Name</td>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.TenantId.ToString())" /></td>
<td><ActionLink Action="Delete" Parameters="@($"id=" + context.TenantId.ToString())" Class="btn btn-danger" /></td>
<td><ActionDialog Header="Delete Tenant" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Tenant?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteTenant(context))" /></td>
<td>@context.Name</td>
</Row>
</Pager>
@ -30,8 +30,23 @@ else
List<Tenant> tenants;
protected override async Task OnInitializedAsync()
protected override async Task OnParametersSetAsync()
{
tenants = await TenantService.GetTenantsAsync();
}
private async Task DeleteTenant(Tenant Tenant)
{
try
{
await TenantService.DeleteTenantAsync(Tenant.TenantId);
await logger.LogInformation("Tenant Deleted {Tenant}", Tenant);
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Tenant {Tenant} {Error}", Tenant, ex.Message);
AddModuleMessage("Error Deleting Tenant", MessageType.Error);
}
}
}

View File

@ -10,24 +10,24 @@
}
else
{
<ActionLink Action="Add" Text="Install Theme" Style="float: right; margin: 10px;" />
<ActionLink Action="Add" Text="Install Theme" />
<Pager Items="@themes">
<Header>
<th>&nbsp;</th>
<th>Name</th>
<th>Version</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</Header>
<Row>
<td>@context.Name</td>
<td>@context.Version</td>
<td>
@if (context.AssemblyName != "Oqtane.Client")
{
<button type="button" class="btn btn-danger" @onclick=@(async () => await DeleteTheme(context.ThemeName))>Delete</button>
<ActionDialog Header="Delete Theme" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Theme?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteTheme(context))" />
}
</td>
<td>@context.Name</td>
<td>@context.Version</td>
<td>
@if (UpgradeAvailable(context.ThemeName, context.Version))
{
@ -64,13 +64,15 @@ else
private async Task DownloadTheme(string themename, string version)
{
await PackageService.DownloadPackageAsync(themename, version, "Themes");
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", themename, version);
await ThemeService.InstallThemesAsync();
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
}
private async Task DeleteTheme(string themename)
private async Task DeleteTheme(Theme Theme)
{
await ThemeService.DeleteThemeAsync(themename);
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
await logger.LogInformation("Theme Deleted {Theme}", Theme);
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
}
}

View File

@ -1,115 +0,0 @@
@namespace Oqtane.Modules.Admin.Users
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IUserService UserService
@inject IProfileService ProfileService
@inject ISettingService SettingService
@if (!string.IsNullOrWhiteSpace(username))
{
<table class="table table-borderless">
<tr>
<td>
<label for="Name" class="control-label">Username: </label>
</td>
<td>
<input class="form-control" @bind="@username" disabled />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Email: </label>
</td>
<td>
<input class="form-control" @bind="@email" disabled />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Full Name: </label>
</td>
<td>
<input class="form-control" @bind="@displayname" disabled />
</td>
</tr>
<tr>
<td>
<label for="Name" class="control-label">Is Deleted? </label>
</td>
<td>
<select class="form-control" @bind="@isdeleted" disabled>
<option value="True">Yes</option>
<option value="False">No</option>
</select>
</td>
</tr>
</table>
<button type="button" class="btn btn-primary" @onclick="DeleteUser">Delete</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
}
@code {
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
int userid;
string username = "";
string email = "";
string displayname = "";
string createdby;
DateTime createdon;
string modifiedby;
DateTime modifiedon;
string deletedby;
DateTime? deletedon;
string isdeleted;
protected override async Task OnInitializedAsync()
{
try
{
userid = Int32.Parse(PageState.QueryString["id"]);
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
if (user != null)
{
username = user.Username;
email = user.Email;
displayname = user.DisplayName;
createdby = user.CreatedBy;
createdon = user.CreatedOn;
modifiedby = user.ModifiedBy;
modifiedon = user.ModifiedOn;
deletedby = user.DeletedBy;
deletedon = user.DeletedOn;
isdeleted = user.IsDeleted.ToString();
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading User {UserId} {Error}", userid, ex.Message);
AddModuleMessage("Error Loading User", MessageType.Error);
}
}
private async Task DeleteUser()
{
try
{
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
if (user != null)
{
await UserService.DeleteUserAsync(userid);
await logger.LogInformation("User Deleted {UserId}", userid);
NavigationManager.NavigateTo(NavigateUrl());
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading User {UserId} {Error}", userid, ex.Message);
AddModuleMessage(ex.Message, MessageType.Error);
}
}
}

View File

@ -1,6 +1,7 @@
@namespace Oqtane.Modules.Admin.Users
@inherits ModuleBase
@inject IUserRoleService UserRoleService
@inject IUserService UserService
@if (userroles == null)
{
@ -8,20 +9,20 @@
}
else
{
<ActionLink Action="Add" Text="Add User" Style="float: right; margin: 10px;" />
<ActionLink Action="Add" Text="Add User" />
<Pager Items="@userroles">
<Header>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>Name</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</Header>
<Row>
<td>@context.User.DisplayName</td>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())" /></td>
<td><ActionLink Action="Delete" Parameters="@($"id=" + context.UserId.ToString())" Class="btn btn-danger" /></td>
<td><ActionDialog Header="Delete User" Message="@("Are You Sure You Wish To Delete " + context.User.DisplayName + "?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" /></td>
<td><ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" /></td>
<td>@context.User.DisplayName</td>
</Row>
</Pager>
}
@ -36,4 +37,23 @@ else
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
userroles = userroles.Where(item => item.Role.Name == Constants.RegisteredRole).ToList();
}
private async Task DeleteUser(UserRole UserRole)
{
try
{
User user = await UserService.GetUserAsync(UserRole.UserId, PageState.Site.SiteId);
if (user != null)
{
await UserService.DeleteUserAsync(user.UserId);
await logger.LogInformation("User Deleted {User}", UserRole.User);
StateHasChanged();
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting User {User} {Error}", UserRole.User, ex.Message);
AddModuleMessage(ex.Message, MessageType.Error);
}
}
}

View File

@ -25,7 +25,7 @@
}
@if (authorized)
{
<button class="@Class" @onclick="DisplayModal">@Action</button>
<button class="@Class" @onclick="DisplayModal">@Text</button>
}
@code {
@ -41,6 +41,9 @@
[Parameter]
public SecurityAccessLevel? Security { get; set; } // optional - can be used to explicitly specify SecurityAccessLevel
[Parameter]
public string Text { get; set; } // optional - defaults to Action if not specified
[Parameter]
public string Class { get; set; } // optional
@ -56,6 +59,10 @@
{
Action = "Ok";
}
if (string.IsNullOrEmpty(Text))
{
Text = Action;
}
if (string.IsNullOrEmpty(Class))
{
Class = "btn btn-success";

View File

@ -36,12 +36,12 @@
protected override void OnParametersSet()
{
text = Action;
if (!String.IsNullOrEmpty(Text))
if (!string.IsNullOrEmpty(Text))
{
text = Text;
}
if (!String.IsNullOrEmpty(Parameters))
if (!string.IsNullOrEmpty(Parameters))
{
parameters = Parameters;
}

View File

@ -0,0 +1,19 @@
using Oqtane.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Oqtane.Services
{
public interface IScheduleLogService
{
Task<List<ScheduleLog>> GetScheduleLogsAsync();
Task<ScheduleLog> GetScheduleLogAsync(int ScheduleLogId);
Task<ScheduleLog> AddScheduleLogAsync(ScheduleLog ScheduleLog);
Task<ScheduleLog> UpdateScheduleLogAsync(ScheduleLog ScheduleLog);
Task DeleteScheduleLogAsync(int ScheduleLogId);
}
}

View File

@ -0,0 +1,19 @@
using Oqtane.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Oqtane.Services
{
public interface IScheduleService
{
Task<List<Schedule>> GetSchedulesAsync();
Task<Schedule> GetScheduleAsync(int ScheduleId);
Task<Schedule> AddScheduleAsync(Schedule Schedule);
Task<Schedule> UpdateScheduleAsync(Schedule Schedule);
Task DeleteScheduleAsync(int ScheduleId);
}
}

View File

@ -0,0 +1,54 @@
using Oqtane.Models;
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class ScheduleLogService : ServiceBase, IScheduleLogService
{
private readonly HttpClient http;
private readonly SiteState sitestate;
private readonly NavigationManager NavigationManager;
public ScheduleLogService(HttpClient http, SiteState sitestate, NavigationManager NavigationManager)
{
this.http = http;
this.sitestate = sitestate;
this.NavigationManager = NavigationManager;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "ScheduleLog"); }
}
public async Task<List<ScheduleLog>> GetScheduleLogsAsync()
{
List<ScheduleLog> schedulelogs = await http.GetJsonAsync<List<ScheduleLog>>(apiurl);
return schedulelogs.OrderBy(item => item.StartDate).ToList();
}
public async Task<ScheduleLog> GetScheduleLogAsync(int ScheduleLogId)
{
return await http.GetJsonAsync<ScheduleLog>(apiurl + "/" + ScheduleLogId.ToString());
}
public async Task<ScheduleLog> AddScheduleLogAsync(ScheduleLog schedulelog)
{
return await http.PostJsonAsync<ScheduleLog>(apiurl, schedulelog);
}
public async Task<ScheduleLog> UpdateScheduleLogAsync(ScheduleLog schedulelog)
{
return await http.PutJsonAsync<ScheduleLog>(apiurl + "/" + schedulelog.ScheduleLogId.ToString(), schedulelog);
}
public async Task DeleteScheduleLogAsync(int ScheduleLogId)
{
await http.DeleteAsync(apiurl + "/" + ScheduleLogId.ToString());
}
}
}

View File

@ -0,0 +1,54 @@
using Oqtane.Models;
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class ScheduleService : ServiceBase, IScheduleService
{
private readonly HttpClient http;
private readonly SiteState sitestate;
private readonly NavigationManager NavigationManager;
public ScheduleService(HttpClient http, SiteState sitestate, NavigationManager NavigationManager)
{
this.http = http;
this.sitestate = sitestate;
this.NavigationManager = NavigationManager;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "Schedule"); }
}
public async Task<List<Schedule>> GetSchedulesAsync()
{
List<Schedule> schedules = await http.GetJsonAsync<List<Schedule>>(apiurl);
return schedules.OrderBy(item => item.Name).ToList();
}
public async Task<Schedule> GetScheduleAsync(int ScheduleId)
{
return await http.GetJsonAsync<Schedule>(apiurl + "/" + ScheduleId.ToString());
}
public async Task<Schedule> AddScheduleAsync(Schedule schedule)
{
return await http.PostJsonAsync<Schedule>(apiurl, schedule);
}
public async Task<Schedule> UpdateScheduleAsync(Schedule schedule)
{
return await http.PutJsonAsync<Schedule>(apiurl + "/" + schedule.ScheduleId.ToString(), schedule);
}
public async Task DeleteScheduleAsync(int ScheduleId)
{
await http.DeleteAsync(apiurl + "/" + ScheduleId.ToString());
}
}
}

View File

@ -54,6 +54,8 @@ namespace Oqtane.Client
services.AddScoped<IFileService, FileService>();
services.AddScoped<IPackageService, PackageService>();
services.AddScoped<ILogService, LogService>();
services.AddScoped<IScheduleService, ScheduleService>();
services.AddScoped<IScheduleLogService, ScheduleLogService>();
// dynamically register module contexts and repository services
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

View File

@ -7,24 +7,49 @@
@inject IModuleService ModuleService
@inject IPageService PageService
@inject IPageModuleService PageModuleService
@inject ILogService logger
@if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions))
{
<div class="app-controlpanel" style="@display">
<div class="card @cardclass mb-3">
<div class="card-header">
<div class="@CardClass">
<div class="@HeaderClass">
Control Panel
<button type="button" class="close" @onclick="HideControlPanel" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="card-body">
<div class="@BodyClass">
<ul class="nav flex-column">
<li class="nav-item px-3"><button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Navigate("Admin"))>Admin Dashboard</button></li>
<li class="nav-item px-3">&nbsp;</li>
<li class="nav-item px-3"><button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Navigate("Add"))>Add Page</button></li>
<li class="nav-item px-3"><button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Navigate("Edit"))>Edit Page</button></li>
<li class="nav-item px-3"><button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => await Delete(PageState.Page))>Delete Page</button></li>
<li class="nav-item px-3">
<button class="btn btn-primary btn-block mx-auto" @onclick="ConfirmDelete">Delete Page</button>
@if (deleteconfirmation)
{
<div class="app-admin-modal">
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete Page</h5>
<button type="button" class="close" @onclick="ConfirmDelete" aria-label="Close">&times;</button>
</div>
<div class="modal-body">
<p>Are You Sure You Want To Delete This Page?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" @onclick="DeletePage">Delete</button>
<button type="button" class="btn btn-secondary" @onclick="ConfirmDelete">Cancel</button>
</div>
</div>
</div>
</div>
</div>
}
</li>
</ul>
<hr class="app-rule" />
<table class="table table-borderless">
@ -124,17 +149,17 @@
@if (PageState.EditMode)
{
<button type="button" class="btn @buttonclass active" data-toggle="button" aria-pressed="true" autocomplete="off" @onclick="EditMode">
<button type="button" class="btn @ButtonClass active" data-toggle="button" aria-pressed="true" autocomplete="off" @onclick="(async () => 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="EditMode">
<button type="button" class="btn @ButtonClass" data-toggle="button" aria-pressed="false" autocomplete="off" @onclick="(async () => ToggleEditMode(PageState.EditMode))">
<span class="oi oi-pencil"></span>
</button>
}
<button type="button" class="btn @buttonclass" @onclick="ShowControlPanel">
<button type="button" class="btn @ButtonClass" @onclick="ShowControlPanel">
<span class="oi oi-menu"></span>
</button>
}
@ -146,6 +171,13 @@
[Parameter]
public string CardClass { get; set; }
[Parameter]
public string HeaderClass { get; set; }
[Parameter]
public string BodyClass { get; set; }
bool deleteconfirmation = false;
string moduletype = "new";
List<string> categories = new List<string>();
List<ModuleDefinition> moduledefinitions;
@ -159,19 +191,25 @@
string title = "";
string containertype = "";
string display = "display: none;";
string buttonclass = "btn-outline-primary";
string cardclass = "text-white bg-secondary";
string message = "";
protected override void OnParametersSet()
{
if (!string.IsNullOrEmpty(ButtonClass))
if (string.IsNullOrEmpty(ButtonClass))
{
buttonclass = ButtonClass;
ButtonClass = "btn-outline-primary";
}
if (!string.IsNullOrEmpty(CardClass))
if (string.IsNullOrEmpty(CardClass))
{
cardclass = CardClass;
CardClass = "card bg-secondary mb-3";
}
if (string.IsNullOrEmpty(HeaderClass))
{
HeaderClass = "card-header text-white";
}
if (string.IsNullOrEmpty(BodyClass))
{
BodyClass = "card-body";
}
if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions))
@ -292,11 +330,11 @@
}
}
private void EditMode()
private void ToggleEditMode(bool EditMode)
{
if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions))
{
if (PageState.EditMode)
if (EditMode)
{
PageState.EditMode = false;
PageState.DesignMode = false;
@ -363,10 +401,26 @@
}
}
private async Task Delete(Page Page)
private void ConfirmDelete()
{
Page.IsDeleted = true;
await PageService.UpdatePageAsync(Page);
deleteconfirmation = !deleteconfirmation;
StateHasChanged();
}
private async Task DeletePage()
{
ConfirmDelete();
Page page = PageState.Page;
try
{
page.IsDeleted = true;
await PageService.UpdatePageAsync(page);
await logger.Log(page.PageId, null, PageState.User.UserId, this.GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
NavigationManager.NavigateTo(NavigateUrl("", Reload.Site));
}
catch (Exception ex)
{
await logger.Log(page.PageId, null, PageState.User.UserId, this.GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, ex, "Page Deleted {Page} {Error}", page, ex.Message);
}
}
}

View File

@ -0,0 +1,72 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Oqtane.Repository;
using Oqtane.Models;
using Oqtane.Shared;
using Oqtane.Infrastructure;
namespace Oqtane.Controllers
{
[Route("{site}/api/[controller]")]
public class ScheduleController : Controller
{
private readonly IScheduleRepository Schedules;
private readonly ILogManager logger;
public ScheduleController(IScheduleRepository Schedules, ILogManager logger)
{
this.Schedules = Schedules;
this.logger = logger;
}
// GET: api/<controller>
[HttpGet]
public IEnumerable<Schedule> Get()
{
return Schedules.GetSchedules();
}
// GET api/<controller>/5
[HttpGet("{id}")]
public Schedule Get(int id)
{
return Schedules.GetSchedule(id);
}
// POST api/<controller>
[HttpPost]
[Authorize(Roles = Constants.HostRole)]
public Schedule Post([FromBody] Schedule Schedule)
{
if (ModelState.IsValid)
{
Schedule = Schedules.AddSchedule(Schedule);
logger.Log(LogLevel.Information, this, LogFunction.Create, "Schedule Added {Schedule}", Schedule);
}
return Schedule;
}
// PUT api/<controller>/5
[HttpPut("{id}")]
[Authorize(Roles = Constants.HostRole)]
public Schedule Put(int id, [FromBody] Schedule Schedule)
{
if (ModelState.IsValid)
{
Schedule = Schedules.UpdateSchedule(Schedule);
logger.Log(LogLevel.Information, this, LogFunction.Update, "Schedule Updated {Schedule}", Schedule);
}
return Schedule;
}
// DELETE api/<controller>/5
[HttpDelete("{id}")]
[Authorize(Roles = Constants.HostRole)]
public void Delete(int id)
{
Schedules.DeleteSchedule(id);
logger.Log(LogLevel.Information, this, LogFunction.Delete, "Schedule Deleted {ScheduleId}", id);
}
}
}

View File

@ -0,0 +1,74 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Oqtane.Repository;
using Oqtane.Models;
using Oqtane.Shared;
using Oqtane.Infrastructure;
namespace Oqtane.Controllers
{
[Route("{site}/api/[controller]")]
public class ScheduleLogController : Controller
{
private readonly IScheduleLogRepository ScheduleLogs;
private readonly ILogManager logger;
public ScheduleLogController(IScheduleLogRepository ScheduleLogs, ILogManager logger)
{
this.ScheduleLogs = ScheduleLogs;
this.logger = logger;
}
// GET: api/<controller>
[HttpGet]
[Authorize(Roles = Constants.HostRole)]
public IEnumerable<ScheduleLog> Get()
{
return ScheduleLogs.GetScheduleLogs();
}
// GET api/<controller>/5
[HttpGet("{id}")]
[Authorize(Roles = Constants.HostRole)]
public ScheduleLog Get(int id)
{
return ScheduleLogs.GetScheduleLog(id);
}
// POST api/<controller>
[HttpPost]
[Authorize(Roles = Constants.HostRole)]
public ScheduleLog Post([FromBody] ScheduleLog ScheduleLog)
{
if (ModelState.IsValid)
{
ScheduleLog = ScheduleLogs.AddScheduleLog(ScheduleLog);
logger.Log(LogLevel.Information, this, LogFunction.Create, "Schedule Log Added {ScheduleLog}", ScheduleLog);
}
return ScheduleLog;
}
// PUT api/<controller>/5
[HttpPut("{id}")]
[Authorize(Roles = Constants.HostRole)]
public ScheduleLog Put(int id, [FromBody] ScheduleLog ScheduleLog)
{
if (ModelState.IsValid)
{
ScheduleLog = ScheduleLogs.UpdateScheduleLog(ScheduleLog);
logger.Log(LogLevel.Information, this, LogFunction.Update, "Schedule Log Updated {ScheduleLog}", ScheduleLog);
}
return ScheduleLog;
}
// DELETE api/<controller>/5
[HttpDelete("{id}")]
[Authorize(Roles = Constants.HostRole)]
public void Delete(int id)
{
ScheduleLogs.DeleteScheduleLog(id);
logger.Log(LogLevel.Information, this, LogFunction.Delete, "Schedule Log Deleted {ScheduleLogId}", id);
}
}
}

View File

@ -18,6 +18,8 @@ namespace Oqtane.Repository
public virtual DbSet<Alias> Alias { get; set; }
public virtual DbSet<Tenant> Tenant { get; set; }
public virtual DbSet<ModuleDefinition> ModuleDefinition { get; set; }
public virtual DbSet<Schedule> Schedule { get; set; }
public virtual DbSet<ScheduleLog> ScheduleLog { get; set; }
public override int SaveChanges()
{

View File

@ -0,0 +1,14 @@
using System.Collections.Generic;
using Oqtane.Models;
namespace Oqtane.Repository
{
public interface IScheduleLogRepository
{
IEnumerable<ScheduleLog> GetScheduleLogs();
ScheduleLog AddScheduleLog(ScheduleLog ScheduleLog);
ScheduleLog UpdateScheduleLog(ScheduleLog ScheduleLog);
ScheduleLog GetScheduleLog(int ScheduleLogId);
void DeleteScheduleLog(int ScheduleLogId);
}
}

View File

@ -0,0 +1,14 @@
using System.Collections.Generic;
using Oqtane.Models;
namespace Oqtane.Repository
{
public interface IScheduleRepository
{
IEnumerable<Schedule> GetSchedules();
Schedule AddSchedule(Schedule Schedule);
Schedule UpdateSchedule(Schedule Schedule);
Schedule GetSchedule(int ScheduleId);
void DeleteSchedule(int ScheduleId);
}
}

View File

@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.Linq;
using Oqtane.Models;
using Microsoft.EntityFrameworkCore;
using System;
namespace Oqtane.Repository
{
public class ScheduleLogRepository : IScheduleLogRepository
{
private MasterDBContext db;
public ScheduleLogRepository(MasterDBContext context)
{
db = context;
}
public IEnumerable<ScheduleLog> GetScheduleLogs()
{
return db.ScheduleLog.ToList();
}
public ScheduleLog AddScheduleLog(ScheduleLog ScheduleLog)
{
db.ScheduleLog.Add(ScheduleLog);
db.SaveChanges();
return ScheduleLog;
}
public ScheduleLog UpdateScheduleLog(ScheduleLog ScheduleLog)
{
db.Entry(ScheduleLog).State = EntityState.Modified;
db.SaveChanges();
return ScheduleLog;
}
public ScheduleLog GetScheduleLog(int ScheduleLogId)
{
return db.ScheduleLog.Find(ScheduleLogId);
}
public void DeleteScheduleLog(int ScheduleLogId)
{
ScheduleLog schedulelog = db.ScheduleLog.Find(ScheduleLogId);
db.ScheduleLog.Remove(schedulelog);
db.SaveChanges();
}
}
}

View File

@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.Linq;
using Oqtane.Models;
using Microsoft.EntityFrameworkCore;
using System;
namespace Oqtane.Repository
{
public class ScheduleRepository : IScheduleRepository
{
private MasterDBContext db;
public ScheduleRepository(MasterDBContext context)
{
db = context;
}
public IEnumerable<Schedule> GetSchedules()
{
return db.Schedule.ToList();
}
public Schedule AddSchedule(Schedule Schedule)
{
db.Schedule.Add(Schedule);
db.SaveChanges();
return Schedule;
}
public Schedule UpdateSchedule(Schedule Schedule)
{
db.Entry(Schedule).State = EntityState.Modified;
db.SaveChanges();
return Schedule;
}
public Schedule GetSchedule(int ScheduleId)
{
return db.Schedule.Find(ScheduleId);
}
public void DeleteSchedule(int ScheduleId)
{
Schedule schedule = db.Schedule.Find(ScheduleId);
db.Schedule.Remove(schedule);
db.SaveChanges();
}
}
}

View File

@ -50,6 +50,41 @@ CREATE TABLE [dbo].[ModuleDefinition](
)
GO
CREATE TABLE [dbo].[Schedule] (
[ScheduleId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](200) NULL,
[JobType] [nvarchar](200) NOT NULL,
[Period] [int] NOT NULL,
[Frequency] [char](1) NOT NULL,
[StartDate] [datetime] NULL,
[IsActive] [bit] NOT NULL,
[RetentionHistory] [int] NOT NULL,
[CreatedBy] [nvarchar](256) NULL,
[CreatedOn] [datetime] NULL,
[ModifiedBy] [nvarchar](256) NULL,
[ModifiedOn] [datetime] NULL,
CONSTRAINT [PK_Schedule] PRIMARY KEY CLUSTERED
(
[ScheduleId] ASC
)
)
GO
CREATE TABLE [dbo].[ScheduleLog] (
[ScheduleLogId] [int] IDENTITY(1,1) NOT NULL,
[ScheduleId] [int] NOT NULL,
[StartDate] [datetime] NOT NULL,
[FinishDate] [datetime] NULL,
[Succeeded] [bit] NULL,
[Notes] [nvarchar](max) NULL,
[NextExecution] [datetime] NULL,
CONSTRAINT [PK_ScheduleLog] PRIMARY KEY CLUSTERED
(
[ScheduleLogId] ASC
)
)
GO
CREATE TABLE [dbo].[ApplicationVersion](
[ApplicationVersionId] [int] IDENTITY(1,1) NOT NULL,
[Version] [nvarchar](50) NOT NULL,
@ -71,6 +106,11 @@ REFERENCES [dbo].[Tenant] ([TenantId])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[ScheduleLog] WITH NOCHECK ADD CONSTRAINT [FK_ScheduleLog_Schedule] FOREIGN KEY([ScheduleId])
REFERENCES [dbo].[Schedule] ([ScheduleId])
ON DELETE CASCADE
GO
/*
Create seed data

View File

@ -100,6 +100,8 @@ namespace Oqtane.Server
services.AddScoped<IFileService, FileService>();
services.AddScoped<IPackageService, PackageService>();
services.AddScoped<ILogService, LogService>();
services.AddScoped<IScheduleService, ScheduleService>();
services.AddScoped<IScheduleLogService, ScheduleLogService>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
@ -175,6 +177,8 @@ namespace Oqtane.Server
services.AddTransient<ISettingRepository, SettingRepository>();
services.AddTransient<ILogRepository, LogRepository>();
services.AddTransient<ILogManager, LogManager>();
services.AddTransient<IScheduleRepository, ScheduleRepository>();
services.AddTransient<IScheduleLogRepository, ScheduleLogRepository>();
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
@ -367,6 +371,8 @@ namespace Oqtane.Server
services.AddTransient<ISettingRepository, SettingRepository>();
services.AddTransient<ILogRepository, LogRepository>();
services.AddTransient<ILogManager, LogManager>();
services.AddTransient<IScheduleRepository, ScheduleRepository>();
services.AddTransient<IScheduleLogRepository, ScheduleLogRepository>();
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

View File

@ -0,0 +1,21 @@
using System;
namespace Oqtane.Models
{
public class Schedule : IAuditable
{
public int ScheduleId { get; set; }
public string Name { get; set; }
public string JobType { get; set; }
public int Period { get; set; }
public string Frequency { get; set; }
public DateTime? StartDate { get; set; }
public bool IsActive { get; set; }
public int RetentionHistory { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public string ModifiedBy { get; set; }
public DateTime ModifiedOn { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace Oqtane.Models
{
public class ScheduleLog
{
public int ScheduleLogId { get; set; }
public int ScheduleId { get; set; }
public DateTime StartDate { get; set; }
public DateTime? FinishDate { get; set; }
public bool? Succeeded { get; set; }
public string Notes { get; set; }
public DateTime? NextExecution { get; set; }
}
}