completed background job scheduler
This commit is contained in:
parent
b4cd038e17
commit
25d2c6596d
137
Oqtane.Client/Modules/Admin/Jobs/Add.razor
Normal file
137
Oqtane.Client/Modules/Admin/Jobs/Add.razor
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
@namespace Oqtane.Modules.Admin.Jobs
|
||||||
|
@inherits ModuleBase
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject IJobService JobService
|
||||||
|
|
||||||
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Name: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@name" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Type: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@jobtype" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Enabled? </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select class="form-control" @bind="@isenabled">
|
||||||
|
<option value="True">Yes</option>
|
||||||
|
<option value="False">No</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Runs Every: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@interval" />
|
||||||
|
<select class="form-control" @bind="@frequency">
|
||||||
|
<option value="m">Minute(s)</option>
|
||||||
|
<option value="H">Hour(s)</option>
|
||||||
|
<option value="d">Day(s)</option>
|
||||||
|
<option value="M">Month(s)</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Starting: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@startdate" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Ending: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@enddate" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Retention Log (Items): </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@retentionhistory" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveJob">Save</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||||
|
|
||||||
|
string name = "";
|
||||||
|
string jobtype = "";
|
||||||
|
string isenabled = "True";
|
||||||
|
string interval = "";
|
||||||
|
string frequency = "";
|
||||||
|
string startdate = "";
|
||||||
|
string enddate = "";
|
||||||
|
string retentionhistory = "10";
|
||||||
|
|
||||||
|
private async Task SaveJob()
|
||||||
|
{
|
||||||
|
if (name != "" && !string.IsNullOrEmpty(jobtype) && frequency != "" && interval != "" && retentionhistory != "")
|
||||||
|
{
|
||||||
|
Job job = new Job();
|
||||||
|
job.Name = name;
|
||||||
|
job.JobType = jobtype;
|
||||||
|
job.IsEnabled = Boolean.Parse(isenabled);
|
||||||
|
job.Frequency = frequency;
|
||||||
|
job.Interval = int.Parse(interval);
|
||||||
|
if (startdate == "")
|
||||||
|
{
|
||||||
|
job.StartDate = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
job.StartDate = DateTime.Parse(startdate);
|
||||||
|
}
|
||||||
|
if (enddate == "")
|
||||||
|
{
|
||||||
|
job.EndDate = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
job.EndDate = DateTime.Parse(enddate);
|
||||||
|
}
|
||||||
|
job.RetentionHistory = int.Parse(retentionhistory);
|
||||||
|
job.IsStarted = false;
|
||||||
|
job.IsExecuting = false;
|
||||||
|
job.NextExecution = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
job = await JobService.AddJobAsync(job);
|
||||||
|
await logger.LogInformation("Job Added {Job}", job);
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Adding Job {Job} {Error}", job, ex.Message);
|
||||||
|
AddModuleMessage("Error Adding Job", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage("You Must Provide The Job Name, Type, Frequency, and Retention", MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
160
Oqtane.Client/Modules/Admin/Jobs/Edit.razor
Normal file
160
Oqtane.Client/Modules/Admin/Jobs/Edit.razor
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
@namespace Oqtane.Modules.Admin.Jobs
|
||||||
|
@inherits ModuleBase
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject IJobService JobService
|
||||||
|
|
||||||
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Name: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@name" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Type: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@jobtype" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Enabled? </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select class="form-control" @bind="@isenabled">
|
||||||
|
<option value="True">Yes</option>
|
||||||
|
<option value="False">No</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Runs Every: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@interval" />
|
||||||
|
<select class="form-control" @bind="@frequency">
|
||||||
|
<option value="m">Minute(s)</option>
|
||||||
|
<option value="H">Hour(s)</option>
|
||||||
|
<option value="d">Day(s)</option>
|
||||||
|
<option value="M">Month(s)</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Starting: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@startdate" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Ending: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@enddate" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="Name" class="control-label">Retention Log (Items): </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@retentionhistory" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveJob">Save</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||||
|
|
||||||
|
int jobid;
|
||||||
|
string name = "";
|
||||||
|
string jobtype = "";
|
||||||
|
string isenabled = "True";
|
||||||
|
string interval = "";
|
||||||
|
string frequency = "";
|
||||||
|
string startdate = "";
|
||||||
|
string enddate = "";
|
||||||
|
string retentionhistory = "";
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
jobid = Int32.Parse(PageState.QueryString["id"]);
|
||||||
|
Job job = await JobService.GetJobAsync(jobid);
|
||||||
|
if (job != null)
|
||||||
|
{
|
||||||
|
name = job.Name;
|
||||||
|
jobtype = job.JobType;
|
||||||
|
isenabled = job.IsEnabled.ToString();
|
||||||
|
interval = job.Interval.ToString();
|
||||||
|
frequency = job.Frequency;
|
||||||
|
startdate = (job.StartDate != null) ? job.StartDate.ToString() : "";
|
||||||
|
enddate = (job.EndDate != null) ? job.EndDate.ToString() : "";
|
||||||
|
retentionhistory = job.RetentionHistory.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading Job {JobId} {Error}", jobid, ex.Message);
|
||||||
|
AddModuleMessage("Error Loading Job", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveJob()
|
||||||
|
{
|
||||||
|
if (name != "" && !string.IsNullOrEmpty(jobtype) && frequency != "" && interval != "" && retentionhistory != "")
|
||||||
|
{
|
||||||
|
Job job = await JobService.GetJobAsync(jobid);
|
||||||
|
job.Name = name;
|
||||||
|
job.JobType = jobtype;
|
||||||
|
job.IsEnabled = Boolean.Parse(isenabled);
|
||||||
|
job.Frequency = frequency;
|
||||||
|
job.Interval = int.Parse(interval);
|
||||||
|
if (startdate == "")
|
||||||
|
{
|
||||||
|
job.StartDate = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
job.StartDate = DateTime.Parse(startdate);
|
||||||
|
}
|
||||||
|
if (enddate == "")
|
||||||
|
{
|
||||||
|
job.EndDate = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
job.EndDate = DateTime.Parse(enddate);
|
||||||
|
}
|
||||||
|
job.RetentionHistory = int.Parse(retentionhistory);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
job = await JobService.UpdateJobAsync(job);
|
||||||
|
await logger.LogInformation("Job Updated {Job}", job);
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Udate Job {Job} {Error}", job, ex.Message);
|
||||||
|
AddModuleMessage("Error Updating Job", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage("You Must Provide The Job Name, Type, Frequency, and Retention", MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
137
Oqtane.Client/Modules/Admin/Jobs/Index.razor
Normal file
137
Oqtane.Client/Modules/Admin/Jobs/Index.razor
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
@namespace Oqtane.Modules.Admin.Jobs
|
||||||
|
@inherits ModuleBase
|
||||||
|
@inject IJobService JobService
|
||||||
|
|
||||||
|
@if (Jobs == null)
|
||||||
|
{
|
||||||
|
<p><em>Loading...</em></p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<ActionLink Action="Add" Text="Add Job" />
|
||||||
|
<ActionLink Action="Log" Class="btn btn-secondary" Text="View Logs" />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="(async () => await Refresh())">Refresh</button>
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
<Pager Items="@Jobs">
|
||||||
|
<Header>
|
||||||
|
<th> </th>
|
||||||
|
<th> </th>
|
||||||
|
<th> </th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Frequency</th>
|
||||||
|
<th>Next Execution</th>
|
||||||
|
<th> </th>
|
||||||
|
</Header>
|
||||||
|
<Row>
|
||||||
|
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.JobId.ToString())" /></td>
|
||||||
|
<td><ActionDialog Header="Delete Job" Message="@("Are You Sure You Wish To Delete This Job?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteJob(context))" /></td>
|
||||||
|
<td><ActionLink Action="Log" Class="btn btn-secondary" Parameters="@($"id=" + context.JobId.ToString())" /></td>
|
||||||
|
<td>@context.Name</td>
|
||||||
|
<td>@DisplayStatus(context.IsEnabled, context.IsExecuting)</td>
|
||||||
|
<td>@DisplayFrequency(context.Interval, context.Frequency)</td>
|
||||||
|
<td>@context.NextExecution</td>
|
||||||
|
<td>
|
||||||
|
@if (context.IsStarted)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-danger" @onclick="(async () => await StopJob(context.JobId))">Stop</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-success" @onclick="(async () => await StartJob(context.JobId))">Start</button>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</Row>
|
||||||
|
</Pager>
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||||
|
|
||||||
|
List<Job> Jobs;
|
||||||
|
|
||||||
|
protected override async Task OnParametersSetAsync()
|
||||||
|
{
|
||||||
|
Jobs = await JobService.GetJobsAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DisplayStatus(bool IsEnabled, bool IsExecuting)
|
||||||
|
{
|
||||||
|
string status = "";
|
||||||
|
if (!IsEnabled)
|
||||||
|
{
|
||||||
|
status = "Disabled";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IsExecuting)
|
||||||
|
{
|
||||||
|
status = "Executing";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = "Idle";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private string DisplayFrequency(int Interval, string Frequency)
|
||||||
|
{
|
||||||
|
string frequency = "Every " + Interval.ToString() + " ";
|
||||||
|
switch (Frequency)
|
||||||
|
{
|
||||||
|
case "m":
|
||||||
|
frequency += "Minute";
|
||||||
|
break;
|
||||||
|
case "H":
|
||||||
|
frequency += "Hour";
|
||||||
|
break;
|
||||||
|
case "d":
|
||||||
|
frequency += "Day";
|
||||||
|
break;
|
||||||
|
case "M":
|
||||||
|
frequency += "Month";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (Interval > 1)
|
||||||
|
{
|
||||||
|
frequency += "s";
|
||||||
|
}
|
||||||
|
return frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteJob(Job Job)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await JobService.DeleteJobAsync(Job.JobId);
|
||||||
|
await logger.LogInformation("Job Deleted {Job}", Job);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Deleting Job {Job} {Error}", Job, ex.Message);
|
||||||
|
AddModuleMessage("Error Deleting Job", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartJob(int JobId)
|
||||||
|
{
|
||||||
|
await JobService.StartJobAsync(JobId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StopJob(int JobId)
|
||||||
|
{
|
||||||
|
await JobService.StopJobAsync(JobId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Refresh()
|
||||||
|
{
|
||||||
|
Jobs = await JobService.GetJobsAsync();
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
64
Oqtane.Client/Modules/Admin/Jobs/Log.razor
Normal file
64
Oqtane.Client/Modules/Admin/Jobs/Log.razor
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
@namespace Oqtane.Modules.Admin.Jobs
|
||||||
|
@inherits ModuleBase
|
||||||
|
@inject IJobLogService JobLogService
|
||||||
|
|
||||||
|
@if (JobLogs == null)
|
||||||
|
{
|
||||||
|
<p><em>Loading...</em></p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<Pager Items="@JobLogs">
|
||||||
|
<Header>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Started</th>
|
||||||
|
<th>Finished</th>
|
||||||
|
<th>Notes</th>
|
||||||
|
</Header>
|
||||||
|
<Row>
|
||||||
|
<td>@context.Job.Name</td>
|
||||||
|
<td>@DisplayStatus(context.Job.IsExecuting, context.Succeeded)</td>
|
||||||
|
<td>@context.StartDate</td>
|
||||||
|
<td>@context.FinishDate</td>
|
||||||
|
<td><ActionDialog Header="Job Notes" Message="@context.Notes" Text="View" Security="SecurityAccessLevel.Host" /></td>
|
||||||
|
</Row>
|
||||||
|
</Pager>
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||||
|
|
||||||
|
List<JobLog> JobLogs;
|
||||||
|
|
||||||
|
protected override async Task OnParametersSetAsync()
|
||||||
|
{
|
||||||
|
JobLogs = await JobLogService.GetJobLogsAsync();
|
||||||
|
if (PageState.QueryString.ContainsKey("id"))
|
||||||
|
{
|
||||||
|
JobLogs = JobLogs.Where(item => item.JobId == Int32.Parse(PageState.QueryString["id"])).ToList();
|
||||||
|
}
|
||||||
|
JobLogs = JobLogs.OrderByDescending(item => item.JobLogId).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DisplayStatus(bool IsExecuting, bool? Succeeded)
|
||||||
|
{
|
||||||
|
string status = "";
|
||||||
|
if (IsExecuting)
|
||||||
|
{
|
||||||
|
status = "Executing";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Succeeded.Value)
|
||||||
|
{
|
||||||
|
status = "Succeeded";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = "Failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,14 +56,15 @@
|
||||||
|
|
||||||
private async Task SaveRole()
|
private async Task SaveRole()
|
||||||
{
|
{
|
||||||
|
Role role = new Role();
|
||||||
|
role.SiteId = PageState.Page.SiteId;
|
||||||
|
role.Name = name;
|
||||||
|
role.Description = description;
|
||||||
|
role.IsAutoAssigned = (isautoassigned == null ? false : Boolean.Parse(isautoassigned));
|
||||||
|
role.IsSystem = (issystem == null ? false : Boolean.Parse(issystem));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Role role = new Role();
|
|
||||||
role.SiteId = PageState.Page.SiteId;
|
|
||||||
role.Name = name;
|
|
||||||
role.Description = description;
|
|
||||||
role.IsAutoAssigned = (isautoassigned == null ? false : Boolean.Parse(isautoassigned));
|
|
||||||
role.IsSystem = (issystem == null ? false : Boolean.Parse(issystem));
|
|
||||||
role = await RoleService.AddRoleAsync(role);
|
role = await RoleService.AddRoleAsync(role);
|
||||||
await logger.LogInformation("Role Added {Role}", role);
|
await logger.LogInformation("Role Added {Role}", role);
|
||||||
|
|
||||||
|
@ -71,8 +72,8 @@
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Adding Role", ex.Message);
|
await logger.LogError(ex, "Error Adding Role {Role} {Error}", role, ex.Message);
|
||||||
AddModuleMessage(ex.Message, MessageType.Error);
|
AddModuleMessage("Error Adding Role", MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,20 +78,21 @@
|
||||||
|
|
||||||
private async Task SaveRole()
|
private async Task SaveRole()
|
||||||
{
|
{
|
||||||
|
Role role = await RoleService.GetRoleAsync(roleid);
|
||||||
|
role.Name = name;
|
||||||
|
role.Description = description;
|
||||||
|
role.IsAutoAssigned = (isautoassigned == null ? false : Boolean.Parse(isautoassigned));
|
||||||
|
role.IsSystem = (issystem == null ? false : Boolean.Parse(issystem));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Role role = await RoleService.GetRoleAsync(roleid);
|
|
||||||
role.Name = name;
|
|
||||||
role.Description = description;
|
|
||||||
role.IsAutoAssigned = (isautoassigned == null ? false : Boolean.Parse(isautoassigned));
|
|
||||||
role.IsSystem = (issystem == null ? false : Boolean.Parse(issystem));
|
|
||||||
role = await RoleService.UpdateRoleAsync(role);
|
role = await RoleService.UpdateRoleAsync(role);
|
||||||
await logger.LogInformation("Role Saved {Role}", role);
|
await logger.LogInformation("Role Saved {Role}", role);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Saving Role {RoleId} {Error}", roleid, ex.Message);
|
await logger.LogError(ex, "Error Saving Role {Role} {Error}", role, ex.Message);
|
||||||
AddModuleMessage("Error Saving Role", MessageType.Error);
|
AddModuleMessage("Error Saving Role", MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
<p>@Message</p>
|
<p>@Message</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="@Class" @onclick="Confirm">@Action</button>
|
@if (!string.IsNullOrEmpty(Action))
|
||||||
|
{
|
||||||
|
<button type="button" class="@Class" @onclick="Confirm">@Action</button>
|
||||||
|
}
|
||||||
<button type="button" class="btn btn-secondary" @onclick="DisplayModal">Cancel</button>
|
<button type="button" class="btn btn-secondary" @onclick="DisplayModal">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,29 +39,25 @@
|
||||||
public string Message { get; set; } // required
|
public string Message { get; set; } // required
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Action { get; set; } // defaults to Ok if not specified
|
public string Text { get; set; } // optional - defaults to Action if not specified
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Action { get; set; } // optional
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public SecurityAccessLevel? Security { get; set; } // optional - can be used to explicitly specify SecurityAccessLevel
|
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]
|
[Parameter]
|
||||||
public string Class { get; set; } // optional
|
public string Class { get; set; } // optional
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Action OnClick { get; set; } // required - executes a method in the calling component
|
public Action OnClick { get; set; } // required if an Action is specified - executes a method in the calling component
|
||||||
|
|
||||||
bool visible = false;
|
bool visible = false;
|
||||||
bool authorized = false;
|
bool authorized = false;
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Action))
|
|
||||||
{
|
|
||||||
Action = "Ok";
|
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(Text))
|
if (string.IsNullOrEmpty(Text))
|
||||||
{
|
{
|
||||||
Text = Action;
|
Text = Action;
|
||||||
|
|
19
Oqtane.Client/Services/Interfaces/IJobLogService.cs
Normal file
19
Oqtane.Client/Services/Interfaces/IJobLogService.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using Oqtane.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
public interface IJobLogService
|
||||||
|
{
|
||||||
|
Task<List<JobLog>> GetJobLogsAsync();
|
||||||
|
|
||||||
|
Task<JobLog> GetJobLogAsync(int JobLogId);
|
||||||
|
|
||||||
|
Task<JobLog> AddJobLogAsync(JobLog JobLog);
|
||||||
|
|
||||||
|
Task<JobLog> UpdateJobLogAsync(JobLog JobLog);
|
||||||
|
|
||||||
|
Task DeleteJobLogAsync(int JobLogId);
|
||||||
|
}
|
||||||
|
}
|
23
Oqtane.Client/Services/Interfaces/IJobService.cs
Normal file
23
Oqtane.Client/Services/Interfaces/IJobService.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
using Oqtane.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
public interface IJobService
|
||||||
|
{
|
||||||
|
Task<List<Job>> GetJobsAsync();
|
||||||
|
|
||||||
|
Task<Job> GetJobAsync(int JobId);
|
||||||
|
|
||||||
|
Task<Job> AddJobAsync(Job Job);
|
||||||
|
|
||||||
|
Task<Job> UpdateJobAsync(Job Job);
|
||||||
|
|
||||||
|
Task DeleteJobAsync(int JobId);
|
||||||
|
|
||||||
|
Task StartJobAsync(int JobId);
|
||||||
|
|
||||||
|
Task StopJobAsync(int JobId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
54
Oqtane.Client/Services/JobLogService.cs
Normal file
54
Oqtane.Client/Services/JobLogService.cs
Normal 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 JobLogService : ServiceBase, IJobLogService
|
||||||
|
{
|
||||||
|
private readonly HttpClient http;
|
||||||
|
private readonly SiteState sitestate;
|
||||||
|
private readonly NavigationManager NavigationManager;
|
||||||
|
|
||||||
|
public JobLogService(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, "JobLog"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<JobLog>> GetJobLogsAsync()
|
||||||
|
{
|
||||||
|
List<JobLog> Joblogs = await http.GetJsonAsync<List<JobLog>>(apiurl);
|
||||||
|
return Joblogs.OrderBy(item => item.StartDate).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<JobLog> GetJobLogAsync(int JobLogId)
|
||||||
|
{
|
||||||
|
return await http.GetJsonAsync<JobLog>(apiurl + "/" + JobLogId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<JobLog> AddJobLogAsync(JobLog Joblog)
|
||||||
|
{
|
||||||
|
return await http.PostJsonAsync<JobLog>(apiurl, Joblog);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<JobLog> UpdateJobLogAsync(JobLog Joblog)
|
||||||
|
{
|
||||||
|
return await http.PutJsonAsync<JobLog>(apiurl + "/" + Joblog.JobLogId.ToString(), Joblog);
|
||||||
|
}
|
||||||
|
public async Task DeleteJobLogAsync(int JobLogId)
|
||||||
|
{
|
||||||
|
await http.DeleteAsync(apiurl + "/" + JobLogId.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
Oqtane.Client/Services/JobService.cs
Normal file
64
Oqtane.Client/Services/JobService.cs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
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 JobService : ServiceBase, IJobService
|
||||||
|
{
|
||||||
|
private readonly HttpClient http;
|
||||||
|
private readonly SiteState sitestate;
|
||||||
|
private readonly NavigationManager NavigationManager;
|
||||||
|
|
||||||
|
public JobService(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, "Job"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Job>> GetJobsAsync()
|
||||||
|
{
|
||||||
|
List<Job> Jobs = await http.GetJsonAsync<List<Job>>(apiurl);
|
||||||
|
return Jobs.OrderBy(item => item.Name).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Job> GetJobAsync(int JobId)
|
||||||
|
{
|
||||||
|
return await http.GetJsonAsync<Job>(apiurl + "/" + JobId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Job> AddJobAsync(Job Job)
|
||||||
|
{
|
||||||
|
return await http.PostJsonAsync<Job>(apiurl, Job);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Job> UpdateJobAsync(Job Job)
|
||||||
|
{
|
||||||
|
return await http.PutJsonAsync<Job>(apiurl + "/" + Job.JobId.ToString(), Job);
|
||||||
|
}
|
||||||
|
public async Task DeleteJobAsync(int JobId)
|
||||||
|
{
|
||||||
|
await http.DeleteAsync(apiurl + "/" + JobId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StartJobAsync(int JobId)
|
||||||
|
{
|
||||||
|
await http.GetAsync(apiurl + "/start/" + JobId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StopJobAsync(int JobId)
|
||||||
|
{
|
||||||
|
await http.GetAsync(apiurl + "/stop/" + JobId.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,54 +0,0 @@
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -54,8 +54,8 @@ namespace Oqtane.Client
|
||||||
services.AddScoped<IFileService, FileService>();
|
services.AddScoped<IFileService, FileService>();
|
||||||
services.AddScoped<IPackageService, PackageService>();
|
services.AddScoped<IPackageService, PackageService>();
|
||||||
services.AddScoped<ILogService, LogService>();
|
services.AddScoped<ILogService, LogService>();
|
||||||
services.AddScoped<IScheduleService, ScheduleService>();
|
services.AddScoped<IJobService, JobService>();
|
||||||
services.AddScoped<IScheduleLogService, ScheduleLogService>();
|
services.AddScoped<IJobLogService, JobLogService>();
|
||||||
|
|
||||||
// dynamically register module contexts and repository services
|
// dynamically register module contexts and repository services
|
||||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||||
|
|
105
Oqtane.Server/Controllers/JobController.cs
Normal file
105
Oqtane.Server/Controllers/JobController.cs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
using Oqtane.Infrastructure;
|
||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Oqtane.Controllers
|
||||||
|
{
|
||||||
|
[Route("{site}/api/[controller]")]
|
||||||
|
public class JobController : Controller
|
||||||
|
{
|
||||||
|
private readonly IJobRepository Jobs;
|
||||||
|
private readonly ILogManager logger;
|
||||||
|
private readonly IServiceProvider ServiceProvider;
|
||||||
|
|
||||||
|
public JobController(IJobRepository Jobs, ILogManager logger, IServiceProvider ServiceProvider)
|
||||||
|
{
|
||||||
|
this.Jobs = Jobs;
|
||||||
|
this.logger = logger;
|
||||||
|
this.ServiceProvider = ServiceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET: api/<controller>
|
||||||
|
[HttpGet]
|
||||||
|
public IEnumerable<Job> Get()
|
||||||
|
{
|
||||||
|
return Jobs.GetJobs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET api/<controller>/5
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public Job Get(int id)
|
||||||
|
{
|
||||||
|
return Jobs.GetJob(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST api/<controller>
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
|
public Job Post([FromBody] Job Job)
|
||||||
|
{
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
|
Job = Jobs.AddJob(Job);
|
||||||
|
logger.Log(LogLevel.Information, this, LogFunction.Create, "Job Added {Job}", Job);
|
||||||
|
}
|
||||||
|
return Job;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT api/<controller>/5
|
||||||
|
[HttpPut("{id}")]
|
||||||
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
|
public Job Put(int id, [FromBody] Job Job)
|
||||||
|
{
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
|
Job = Jobs.UpdateJob(Job);
|
||||||
|
logger.Log(LogLevel.Information, this, LogFunction.Update, "Job Updated {Job}", Job);
|
||||||
|
}
|
||||||
|
return Job;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE api/<controller>/5
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
|
public void Delete(int id)
|
||||||
|
{
|
||||||
|
Jobs.DeleteJob(id);
|
||||||
|
logger.Log(LogLevel.Information, this, LogFunction.Delete, "Job Deleted {JobId}", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET api/<controller>/start
|
||||||
|
[HttpGet("start/{id}")]
|
||||||
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
|
public void Start(int id)
|
||||||
|
{
|
||||||
|
Job job = Jobs.GetJob(id);
|
||||||
|
Type jobtype = Type.GetType(job.JobType);
|
||||||
|
if (jobtype != null)
|
||||||
|
{
|
||||||
|
var jobobject = ActivatorUtilities.CreateInstance(ServiceProvider, jobtype);
|
||||||
|
((IHostedService)jobobject).StartAsync(new System.Threading.CancellationToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET api/<controller>/stop
|
||||||
|
[HttpGet("stop/{id}")]
|
||||||
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
|
public void Stop(int id)
|
||||||
|
{
|
||||||
|
Job job = Jobs.GetJob(id);
|
||||||
|
Type jobtype = Type.GetType(job.JobType);
|
||||||
|
if (jobtype != null)
|
||||||
|
{
|
||||||
|
var jobobject = ActivatorUtilities.CreateInstance(ServiceProvider, jobtype);
|
||||||
|
((IHostedService)jobobject).StopAsync(new System.Threading.CancellationToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,55 +9,57 @@ using Oqtane.Infrastructure;
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
[Route("{site}/api/[controller]")]
|
[Route("{site}/api/[controller]")]
|
||||||
public class ScheduleController : Controller
|
public class JobLogController : Controller
|
||||||
{
|
{
|
||||||
private readonly IScheduleRepository Schedules;
|
private readonly IJobLogRepository JobLogs;
|
||||||
private readonly ILogManager logger;
|
private readonly ILogManager logger;
|
||||||
|
|
||||||
public ScheduleController(IScheduleRepository Schedules, ILogManager logger)
|
public JobLogController(IJobLogRepository JobLogs, ILogManager logger)
|
||||||
{
|
{
|
||||||
this.Schedules = Schedules;
|
this.JobLogs = JobLogs;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: api/<controller>
|
// GET: api/<controller>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IEnumerable<Schedule> Get()
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
|
public IEnumerable<JobLog> Get()
|
||||||
{
|
{
|
||||||
return Schedules.GetSchedules();
|
return JobLogs.GetJobLogs();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/5
|
// GET api/<controller>/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public Schedule Get(int id)
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
|
public JobLog Get(int id)
|
||||||
{
|
{
|
||||||
return Schedules.GetSchedule(id);
|
return JobLogs.GetJobLog(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST api/<controller>
|
// POST api/<controller>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Authorize(Roles = Constants.HostRole)]
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
public Schedule Post([FromBody] Schedule Schedule)
|
public JobLog Post([FromBody] JobLog JobLog)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
Schedule = Schedules.AddSchedule(Schedule);
|
JobLog = JobLogs.AddJobLog(JobLog);
|
||||||
logger.Log(LogLevel.Information, this, LogFunction.Create, "Schedule Added {Schedule}", Schedule);
|
logger.Log(LogLevel.Information, this, LogFunction.Create, "Job Log Added {JobLog}", JobLog);
|
||||||
}
|
}
|
||||||
return Schedule;
|
return JobLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT api/<controller>/5
|
// PUT api/<controller>/5
|
||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
[Authorize(Roles = Constants.HostRole)]
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
public Schedule Put(int id, [FromBody] Schedule Schedule)
|
public JobLog Put(int id, [FromBody] JobLog JobLog)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
Schedule = Schedules.UpdateSchedule(Schedule);
|
JobLog = JobLogs.UpdateJobLog(JobLog);
|
||||||
logger.Log(LogLevel.Information, this, LogFunction.Update, "Schedule Updated {Schedule}", Schedule);
|
logger.Log(LogLevel.Information, this, LogFunction.Update, "Job Log Updated {JobLog}", JobLog);
|
||||||
}
|
}
|
||||||
return Schedule;
|
return JobLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE api/<controller>/5
|
// DELETE api/<controller>/5
|
||||||
|
@ -65,8 +67,8 @@ namespace Oqtane.Controllers
|
||||||
[Authorize(Roles = Constants.HostRole)]
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
public void Delete(int id)
|
public void Delete(int id)
|
||||||
{
|
{
|
||||||
Schedules.DeleteSchedule(id);
|
JobLogs.DeleteJobLog(id);
|
||||||
logger.Log(LogLevel.Information, this, LogFunction.Delete, "Schedule Deleted {ScheduleId}", id);
|
logger.Log(LogLevel.Information, this, LogFunction.Delete, "Job Log Deleted {JobLogId}", id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,74 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Oqtane.Models;
|
|
||||||
using Oqtane.Repository;
|
|
||||||
using Oqtane.Shared;
|
|
||||||
|
|
||||||
namespace Oqtane.Infrastructure
|
|
||||||
{
|
|
||||||
public abstract class HostedServiceBase : IHostedService, IDisposable
|
|
||||||
{
|
|
||||||
private Task ExecutingTask;
|
|
||||||
private readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
|
|
||||||
private readonly IServiceScopeFactory ServiceScopeFactory;
|
|
||||||
|
|
||||||
public HostedServiceBase(IServiceScopeFactory ServiceScopeFactory)
|
|
||||||
{
|
|
||||||
this.ServiceScopeFactory = ServiceScopeFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
// abstract method must be overridden by job
|
|
||||||
public abstract void ExecuteJob(IServiceProvider provider);
|
|
||||||
|
|
||||||
|
|
||||||
protected async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
// allows consumption of scoped services
|
|
||||||
using (var scope = ServiceScopeFactory.CreateScope())
|
|
||||||
{
|
|
||||||
string JobType = Utilities.GetFullTypeName(this.GetType().AssemblyQualifiedName);
|
|
||||||
IScheduleRepository ScheduleRepository = scope.ServiceProvider.GetRequiredService<IScheduleRepository>();
|
|
||||||
List<Schedule> schedules = ScheduleRepository.GetSchedules().ToList();
|
|
||||||
Schedule schedule = schedules.Where(item => item.JobType == JobType).FirstOrDefault();
|
|
||||||
if (schedule != null && schedule.IsActive)
|
|
||||||
{
|
|
||||||
ExecuteJob(scope.ServiceProvider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// can occur during the initial installation as there is no DBContext
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
ExecutingTask = ExecuteAsync(CancellationTokenSource.Token);
|
|
||||||
|
|
||||||
if (ExecutingTask.IsCompleted)
|
|
||||||
{
|
|
||||||
return ExecutingTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task StopAsync(CancellationToken CancellationToken)
|
|
||||||
{
|
|
||||||
if (ExecutingTask == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CancellationTokenSource.Cancel();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
await Task.WhenAny(ExecutingTask, Task.Delay(Timeout.Infinite, CancellationToken));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
CancellationTokenSource.Cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
197
Oqtane.Server/Infrastructure/Jobs/HostedServiceBase.cs
Normal file
197
Oqtane.Server/Infrastructure/Jobs/HostedServiceBase.cs
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Infrastructure
|
||||||
|
{
|
||||||
|
public abstract class HostedServiceBase : IHostedService, IDisposable
|
||||||
|
{
|
||||||
|
private Task ExecutingTask;
|
||||||
|
private readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
|
||||||
|
private readonly IServiceScopeFactory ServiceScopeFactory;
|
||||||
|
|
||||||
|
public HostedServiceBase(IServiceScopeFactory ServiceScopeFactory)
|
||||||
|
{
|
||||||
|
this.ServiceScopeFactory = ServiceScopeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// abstract method must be overridden
|
||||||
|
public abstract string ExecuteJob(IServiceProvider provider);
|
||||||
|
|
||||||
|
protected async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
using (var scope = ServiceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
// get name of job
|
||||||
|
string JobType = Utilities.GetFullTypeName(this.GetType().AssemblyQualifiedName);
|
||||||
|
|
||||||
|
// load jobs and find current job
|
||||||
|
IJobRepository Jobs = scope.ServiceProvider.GetRequiredService<IJobRepository>();
|
||||||
|
Job Job = Jobs.GetJobs().Where(item => item.JobType == JobType).FirstOrDefault();
|
||||||
|
if (Job != null && Job.IsEnabled && !Job.IsExecuting)
|
||||||
|
{
|
||||||
|
// set next execution date
|
||||||
|
if (Job.NextExecution == null)
|
||||||
|
{
|
||||||
|
if (Job.StartDate != null)
|
||||||
|
{
|
||||||
|
Job.NextExecution = Job.StartDate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Job.NextExecution = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine if the job should be run
|
||||||
|
if (Job.NextExecution <= DateTime.Now && (Job.EndDate == null || Job.EndDate >= DateTime.Now))
|
||||||
|
{
|
||||||
|
IJobLogRepository JobLogs = scope.ServiceProvider.GetRequiredService<IJobLogRepository>();
|
||||||
|
|
||||||
|
// create a job log entry
|
||||||
|
JobLog log = new JobLog();
|
||||||
|
log.JobId = Job.JobId;
|
||||||
|
log.StartDate = DateTime.Now;
|
||||||
|
log.FinishDate = null;
|
||||||
|
log.Succeeded = false;
|
||||||
|
log.Notes = "";
|
||||||
|
log = JobLogs.AddJobLog(log);
|
||||||
|
|
||||||
|
// update the job to indicate it is running
|
||||||
|
Job.IsExecuting = true;
|
||||||
|
Jobs.UpdateJob(Job);
|
||||||
|
|
||||||
|
// execute the job
|
||||||
|
try
|
||||||
|
{
|
||||||
|
log.Notes = ExecuteJob(scope.ServiceProvider);
|
||||||
|
log.Succeeded = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.Notes = ex.Message;
|
||||||
|
log.Succeeded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the job log
|
||||||
|
log.FinishDate = DateTime.Now;
|
||||||
|
JobLogs.UpdateJobLog(log);
|
||||||
|
|
||||||
|
// update the job
|
||||||
|
Job.NextExecution = CalculateNextExecution(Job.NextExecution.Value, Job.Frequency, Job.Interval);
|
||||||
|
Job.IsExecuting = false;
|
||||||
|
Jobs.UpdateJob(Job);
|
||||||
|
|
||||||
|
// trim the job log
|
||||||
|
List<JobLog> logs = JobLogs.GetJobLogs().Where(item => item.JobId == Job.JobId)
|
||||||
|
.OrderByDescending(item => item.JobLogId).ToList();
|
||||||
|
for (int i = logs.Count; i > Job.RetentionHistory; i--)
|
||||||
|
{
|
||||||
|
JobLogs.DeleteJobLog(logs[i - 1].JobLogId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait 1 minute
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// can occur during the initial installation as there is no DBContext
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime CalculateNextExecution(DateTime NextExecution, string Frequency, int Interval)
|
||||||
|
{
|
||||||
|
switch (Frequency)
|
||||||
|
{
|
||||||
|
case "m": // minutes
|
||||||
|
NextExecution = NextExecution.AddMinutes(Interval);
|
||||||
|
break;
|
||||||
|
case "H": // hours
|
||||||
|
NextExecution = NextExecution.AddHours(Interval);
|
||||||
|
break;
|
||||||
|
case "d": // days
|
||||||
|
NextExecution = NextExecution.AddDays(Interval);
|
||||||
|
break;
|
||||||
|
case "M": // months
|
||||||
|
NextExecution = NextExecution.AddMonths(Interval);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (NextExecution < DateTime.Now)
|
||||||
|
{
|
||||||
|
NextExecution = DateTime.Now;
|
||||||
|
}
|
||||||
|
return NextExecution;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// set IsExecuting to false in case this job was forcefully terminated previously
|
||||||
|
using (var scope = ServiceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
string JobType = Utilities.GetFullTypeName(this.GetType().AssemblyQualifiedName);
|
||||||
|
IJobRepository Jobs = scope.ServiceProvider.GetRequiredService<IJobRepository>();
|
||||||
|
Job Job = Jobs.GetJobs().Where(item => item.JobType == JobType).FirstOrDefault();
|
||||||
|
if (Job != null)
|
||||||
|
{
|
||||||
|
Job.IsStarted = true;
|
||||||
|
Job.IsExecuting = false;
|
||||||
|
Jobs.UpdateJob(Job);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// can occur during the initial installation as there is no DBContext
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecutingTask = ExecuteAsync(CancellationTokenSource.Token);
|
||||||
|
|
||||||
|
if (ExecutingTask.IsCompleted)
|
||||||
|
{
|
||||||
|
return ExecutingTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StopAsync(CancellationToken CancellationToken)
|
||||||
|
{
|
||||||
|
if (ExecutingTask == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CancellationTokenSource.Cancel();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
await Task.WhenAny(ExecutingTask, Task.Delay(Timeout.Infinite, CancellationToken));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
CancellationTokenSource.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
Oqtane.Server/Infrastructure/Jobs/SampleJob.cs
Normal file
33
Oqtane.Server/Infrastructure/Jobs/SampleJob.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Infrastructure
|
||||||
|
{
|
||||||
|
public class SampleJob : HostedServiceBase
|
||||||
|
{
|
||||||
|
// JobType = "Oqtane.Infrastructure.SampleJob, Oqtane.Server"
|
||||||
|
|
||||||
|
public SampleJob(IServiceScopeFactory ServiceScopeFactory) : base(ServiceScopeFactory) {}
|
||||||
|
|
||||||
|
public override string ExecuteJob(IServiceProvider provider)
|
||||||
|
{
|
||||||
|
// get the first alias for this installation
|
||||||
|
var Aliases = provider.GetRequiredService<IAliasRepository>();
|
||||||
|
Alias alias = Aliases.GetAliases().FirstOrDefault();
|
||||||
|
|
||||||
|
// use the SiteState to set the Alias explicitly so the tenant can be resolved
|
||||||
|
var sitestate = provider.GetRequiredService<SiteState>();
|
||||||
|
sitestate.Alias = alias;
|
||||||
|
|
||||||
|
// call a repository service which requires tenant resolution
|
||||||
|
var Sites = provider.GetRequiredService<ISiteRepository>();
|
||||||
|
Site site = Sites.GetSites().FirstOrDefault();
|
||||||
|
|
||||||
|
return "You Should Include Any Notes Related To The Execution Of The Schedule Job. This Job Simply Reports That The Default Site Is " + site.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
using System;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Oqtane.Models;
|
|
||||||
using Oqtane.Repository;
|
|
||||||
|
|
||||||
namespace Oqtane.Infrastructure
|
|
||||||
{
|
|
||||||
public class TestJob : HostedServiceBase
|
|
||||||
{
|
|
||||||
public TestJob(IServiceScopeFactory ServiceScopeFactory) : base(ServiceScopeFactory) {}
|
|
||||||
|
|
||||||
public override void ExecuteJob(IServiceProvider provider)
|
|
||||||
{
|
|
||||||
var Tenants = provider.GetRequiredService<ITenantRepository>();
|
|
||||||
foreach(Tenant tenant in Tenants.GetTenants())
|
|
||||||
{
|
|
||||||
// is it possible to set the HttpContext so that DbContextBase will resolve properly for tenants?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -42,7 +42,7 @@ namespace Oqtane.Repository
|
||||||
ChangeTracker.DetectChanges();
|
ChangeTracker.DetectChanges();
|
||||||
|
|
||||||
string username = "";
|
string username = "";
|
||||||
if (accessor.HttpContext.User.Identity.Name != null)
|
if (accessor.HttpContext != null && accessor.HttpContext.User.Identity.Name != null)
|
||||||
{
|
{
|
||||||
username = accessor.HttpContext.User.Identity.Name;
|
username = accessor.HttpContext.User.Identity.Name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,15 @@ namespace Oqtane.Repository
|
||||||
public virtual DbSet<Alias> Alias { get; set; }
|
public virtual DbSet<Alias> Alias { get; set; }
|
||||||
public virtual DbSet<Tenant> Tenant { get; set; }
|
public virtual DbSet<Tenant> Tenant { get; set; }
|
||||||
public virtual DbSet<ModuleDefinition> ModuleDefinition { get; set; }
|
public virtual DbSet<ModuleDefinition> ModuleDefinition { get; set; }
|
||||||
public virtual DbSet<Schedule> Schedule { get; set; }
|
public virtual DbSet<Job> Job { get; set; }
|
||||||
public virtual DbSet<ScheduleLog> ScheduleLog { get; set; }
|
public virtual DbSet<JobLog> JobLog { get; set; }
|
||||||
|
|
||||||
public override int SaveChanges()
|
public override int SaveChanges()
|
||||||
{
|
{
|
||||||
ChangeTracker.DetectChanges();
|
ChangeTracker.DetectChanges();
|
||||||
|
|
||||||
string username = "";
|
string username = "";
|
||||||
if (accessor.HttpContext.User.Identity.Name != null)
|
if (accessor.HttpContext != null && accessor.HttpContext.User.Identity.Name != null)
|
||||||
{
|
{
|
||||||
username = accessor.HttpContext.User.Identity.Name;
|
username = accessor.HttpContext.User.Identity.Name;
|
||||||
}
|
}
|
||||||
|
|
14
Oqtane.Server/Repository/Interfaces/IJobLogRepository.cs
Normal file
14
Oqtane.Server/Repository/Interfaces/IJobLogRepository.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Models;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository
|
||||||
|
{
|
||||||
|
public interface IJobLogRepository
|
||||||
|
{
|
||||||
|
IEnumerable<JobLog> GetJobLogs();
|
||||||
|
JobLog AddJobLog(JobLog JobLog);
|
||||||
|
JobLog UpdateJobLog(JobLog JobLog);
|
||||||
|
JobLog GetJobLog(int JobLogId);
|
||||||
|
void DeleteJobLog(int JobLogId);
|
||||||
|
}
|
||||||
|
}
|
14
Oqtane.Server/Repository/Interfaces/IJobRepository.cs
Normal file
14
Oqtane.Server/Repository/Interfaces/IJobRepository.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Models;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository
|
||||||
|
{
|
||||||
|
public interface IJobRepository
|
||||||
|
{
|
||||||
|
IEnumerable<Job> GetJobs();
|
||||||
|
Job AddJob(Job Job);
|
||||||
|
Job UpdateJob(Job Job);
|
||||||
|
Job GetJob(int JobId);
|
||||||
|
void DeleteJob(int JobId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
51
Oqtane.Server/Repository/JobLogRepository.cs
Normal file
51
Oqtane.Server/Repository/JobLogRepository.cs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository
|
||||||
|
{
|
||||||
|
public class JobLogRepository : IJobLogRepository
|
||||||
|
{
|
||||||
|
private MasterDBContext db;
|
||||||
|
|
||||||
|
public JobLogRepository(MasterDBContext context)
|
||||||
|
{
|
||||||
|
db = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<JobLog> GetJobLogs()
|
||||||
|
{
|
||||||
|
return db.JobLog
|
||||||
|
.Include(item => item.Job) // eager load jobs
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobLog AddJobLog(JobLog JobLog)
|
||||||
|
{
|
||||||
|
db.JobLog.Add(JobLog);
|
||||||
|
db.SaveChanges();
|
||||||
|
return JobLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobLog UpdateJobLog(JobLog JobLog)
|
||||||
|
{
|
||||||
|
db.Entry(JobLog).State = EntityState.Modified;
|
||||||
|
db.SaveChanges();
|
||||||
|
return JobLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JobLog GetJobLog(int JobLogId)
|
||||||
|
{
|
||||||
|
return db.JobLog.Include(item => item.Job) // eager load job
|
||||||
|
.SingleOrDefault(item => item.JobLogId == JobLogId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteJobLog(int JobLogId)
|
||||||
|
{
|
||||||
|
JobLog Joblog = db.JobLog.Find(JobLogId);
|
||||||
|
db.JobLog.Remove(Joblog);
|
||||||
|
db.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
Oqtane.Server/Repository/JobRepository.cs
Normal file
49
Oqtane.Server/Repository/JobRepository.cs
Normal 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 JobRepository : IJobRepository
|
||||||
|
{
|
||||||
|
private MasterDBContext db;
|
||||||
|
|
||||||
|
public JobRepository(MasterDBContext context)
|
||||||
|
{
|
||||||
|
db = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Job> GetJobs()
|
||||||
|
{
|
||||||
|
return db.Job.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Job AddJob(Job Job)
|
||||||
|
{
|
||||||
|
db.Job.Add(Job);
|
||||||
|
db.SaveChanges();
|
||||||
|
return Job;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Job UpdateJob(Job Job)
|
||||||
|
{
|
||||||
|
db.Entry(Job).State = EntityState.Modified;
|
||||||
|
db.SaveChanges();
|
||||||
|
return Job;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Job GetJob(int JobId)
|
||||||
|
{
|
||||||
|
return db.Job.Find(JobId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteJob(int JobId)
|
||||||
|
{
|
||||||
|
Job Job = db.Job.Find(JobId);
|
||||||
|
db.Job.Remove(Job);
|
||||||
|
db.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,49 +0,0 @@
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -92,6 +92,9 @@ namespace Oqtane.Repository
|
||||||
SiteTemplate.Add(new PageTemplate { Name = "Theme Management", Parent = "Admin", Path = "admin/themes", Icon = "brush", IsNavigation = false, IsPersonalizable = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", PageTemplateModules = new List<PageTemplateModule> {
|
SiteTemplate.Add(new PageTemplate { Name = "Theme Management", Parent = "Admin", Path = "admin/themes", Icon = "brush", IsNavigation = false, IsPersonalizable = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", PageTemplateModules = new List<PageTemplateModule> {
|
||||||
new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.Admin.Themes, Oqtane.Client", Title = "Theme Management", Pane = "Content", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Content = "" }
|
new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.Admin.Themes, Oqtane.Client", Title = "Theme Management", Pane = "Content", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Content = "" }
|
||||||
}});
|
}});
|
||||||
|
SiteTemplate.Add(new PageTemplate { Name = "Scheduled Jobs", Parent = "Admin", Path = "admin/jobs", Icon = "timer", IsNavigation = false, IsPersonalizable = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", PageTemplateModules = new List<PageTemplateModule> {
|
||||||
|
new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.Admin.Jobs, Oqtane.Client", Title = "Scheduled Jobs", Pane = "Content", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Content = "" }
|
||||||
|
}});
|
||||||
SiteTemplate.Add(new PageTemplate { Name = "Upgrade Service", Parent = "Admin", Path = "admin/upgrade", Icon = "aperture", IsNavigation = false, IsPersonalizable = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", PageTemplateModules = new List<PageTemplateModule> {
|
SiteTemplate.Add(new PageTemplate { Name = "Upgrade Service", Parent = "Admin", Path = "admin/upgrade", Icon = "aperture", IsNavigation = false, IsPersonalizable = false, EditMode = true, PagePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", PageTemplateModules = new List<PageTemplateModule> {
|
||||||
new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.Admin.Upgrade, Oqtane.Client", Title = "Upgrade Service", Pane = "Content", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Content = "" }
|
new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.Admin.Upgrade, Oqtane.Client", Title = "Upgrade Service", Pane = "Content", ModulePermissions = "[{\"PermissionName\":\"View\",\"Permissions\":\"Administrators\"},{\"PermissionName\":\"Edit\",\"Permissions\":\"Administrators\"}]", Content = "" }
|
||||||
}});
|
}});
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System;
|
using System;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
|
@ -12,12 +13,14 @@ namespace Oqtane.Repository
|
||||||
private readonly string aliasname;
|
private readonly string aliasname;
|
||||||
private readonly IAliasRepository Aliases;
|
private readonly IAliasRepository Aliases;
|
||||||
private readonly ITenantRepository Tenants;
|
private readonly ITenantRepository Tenants;
|
||||||
|
private readonly SiteState sitestate;
|
||||||
|
|
||||||
public TenantResolver(MasterDBContext context, IHttpContextAccessor accessor, IAliasRepository Aliases, ITenantRepository Tenants)
|
public TenantResolver(MasterDBContext context, IHttpContextAccessor accessor, IAliasRepository Aliases, ITenantRepository Tenants, SiteState sitestate)
|
||||||
{
|
{
|
||||||
db = context;
|
db = context;
|
||||||
this.Aliases = Aliases;
|
this.Aliases = Aliases;
|
||||||
this.Tenants = Tenants;
|
this.Tenants = Tenants;
|
||||||
|
this.sitestate = sitestate;
|
||||||
aliasname = "";
|
aliasname = "";
|
||||||
|
|
||||||
// get alias based on request context
|
// get alias based on request context
|
||||||
|
@ -35,6 +38,13 @@ namespace Oqtane.Repository
|
||||||
aliasname = aliasname.Substring(0, aliasname.Length - 1);
|
aliasname = aliasname.Substring(0, aliasname.Length - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else // background processes can pass in an alias using the SiteState service
|
||||||
|
{
|
||||||
|
if (sitestate != null)
|
||||||
|
{
|
||||||
|
aliasname = sitestate.Alias.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Alias GetAlias()
|
public Alias GetAlias()
|
||||||
|
|
|
@ -3,22 +3,6 @@
|
||||||
Create tables
|
Create tables
|
||||||
|
|
||||||
*/
|
*/
|
||||||
CREATE TABLE [dbo].[Alias](
|
|
||||||
[AliasId] [int] IDENTITY(1,1) NOT NULL,
|
|
||||||
[Name] [nvarchar](200) NOT NULL,
|
|
||||||
[TenantId] [int] NOT NULL,
|
|
||||||
[SiteId] [int] NOT NULL,
|
|
||||||
[CreatedBy] [nvarchar](256) NOT NULL,
|
|
||||||
[CreatedOn] [datetime] NOT NULL,
|
|
||||||
[ModifiedBy] [nvarchar](256) NOT NULL,
|
|
||||||
[ModifiedOn] [datetime] NOT NULL,
|
|
||||||
CONSTRAINT [PK_Alias] PRIMARY KEY CLUSTERED
|
|
||||||
(
|
|
||||||
[AliasId] ASC
|
|
||||||
)
|
|
||||||
)
|
|
||||||
GO
|
|
||||||
|
|
||||||
CREATE TABLE [dbo].[Tenant](
|
CREATE TABLE [dbo].[Tenant](
|
||||||
[TenantId] [int] IDENTITY(1,1) NOT NULL,
|
[TenantId] [int] IDENTITY(1,1) NOT NULL,
|
||||||
[Name] [nvarchar](100) NOT NULL,
|
[Name] [nvarchar](100) NOT NULL,
|
||||||
|
@ -36,6 +20,23 @@ CREATE TABLE [dbo].[Tenant](
|
||||||
)
|
)
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
CREATE TABLE [dbo].[Alias](
|
||||||
|
[AliasId] [int] IDENTITY(1,1) NOT NULL,
|
||||||
|
[Name] [nvarchar](200) NOT NULL,
|
||||||
|
[TenantId] [int] NOT NULL,
|
||||||
|
[SiteId] [int] NOT NULL,
|
||||||
|
[CreatedBy] [nvarchar](256) NOT NULL,
|
||||||
|
[CreatedOn] [datetime] NOT NULL,
|
||||||
|
[ModifiedBy] [nvarchar](256) NOT NULL,
|
||||||
|
[ModifiedOn] [datetime] NOT NULL,
|
||||||
|
CONSTRAINT [PK_Alias] PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[AliasId] ASC
|
||||||
|
)
|
||||||
|
)
|
||||||
|
GO
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE [dbo].[ModuleDefinition](
|
CREATE TABLE [dbo].[ModuleDefinition](
|
||||||
[ModuleDefinitionId] [int] IDENTITY(1,1) NOT NULL,
|
[ModuleDefinitionId] [int] IDENTITY(1,1) NOT NULL,
|
||||||
[ModuleDefinitionName] [nvarchar](200) NOT NULL,
|
[ModuleDefinitionName] [nvarchar](200) NOT NULL,
|
||||||
|
@ -50,38 +51,40 @@ CREATE TABLE [dbo].[ModuleDefinition](
|
||||||
)
|
)
|
||||||
GO
|
GO
|
||||||
|
|
||||||
CREATE TABLE [dbo].[Schedule] (
|
CREATE TABLE [dbo].[Job] (
|
||||||
[ScheduleId] [int] IDENTITY(1,1) NOT NULL,
|
[JobId] [int] IDENTITY(1,1) NOT NULL,
|
||||||
[Name] [nvarchar](200) NOT NULL,
|
[Name] [nvarchar](200) NOT NULL,
|
||||||
[JobType] [nvarchar](200) NOT NULL,
|
[JobType] [nvarchar](200) NOT NULL,
|
||||||
[Period] [int] NOT NULL,
|
|
||||||
[Frequency] [char](1) NOT NULL,
|
[Frequency] [char](1) NOT NULL,
|
||||||
|
[Interval] [int] NOT NULL,
|
||||||
[StartDate] [datetime] NULL,
|
[StartDate] [datetime] NULL,
|
||||||
[IsActive] [bit] NOT NULL,
|
[EndDate] [datetime] NULL,
|
||||||
|
[IsEnabled] [bit] NOT NULL,
|
||||||
|
[IsStarted] [bit] NOT NULL,
|
||||||
[IsExecuting] [bit] NOT NULL,
|
[IsExecuting] [bit] NOT NULL,
|
||||||
[NextExecution] [datetime] NULL,
|
[NextExecution] [datetime] NULL,
|
||||||
[RetentionHistory] [int] NOT NULL,
|
[RetentionHistory] [int] NOT NULL,
|
||||||
[CreatedBy] [nvarchar](256) NULL,
|
[CreatedBy] [nvarchar](256) NOT NULL,
|
||||||
[CreatedOn] [datetime] NULL,
|
[CreatedOn] [datetime] NOT NULL,
|
||||||
[ModifiedBy] [nvarchar](256) NULL,
|
[ModifiedBy] [nvarchar](256) NOT NULL,
|
||||||
[ModifiedOn] [datetime] NULL,
|
[ModifiedOn] [datetime] NOT NULL,
|
||||||
CONSTRAINT [PK_Schedule] PRIMARY KEY CLUSTERED
|
CONSTRAINT [PK_Job] PRIMARY KEY CLUSTERED
|
||||||
(
|
(
|
||||||
[ScheduleId] ASC
|
[JobId] ASC
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
GO
|
GO
|
||||||
|
|
||||||
CREATE TABLE [dbo].[ScheduleLog] (
|
CREATE TABLE [dbo].[JobLog] (
|
||||||
[ScheduleLogId] [int] IDENTITY(1,1) NOT NULL,
|
[JobLogId] [int] IDENTITY(1,1) NOT NULL,
|
||||||
[ScheduleId] [int] NOT NULL,
|
[JobId] [int] NOT NULL,
|
||||||
[StartDate] [datetime] NOT NULL,
|
[StartDate] [datetime] NOT NULL,
|
||||||
[FinishDate] [datetime] NULL,
|
[FinishDate] [datetime] NULL,
|
||||||
[Succeeded] [bit] NULL,
|
[Succeeded] [bit] NULL,
|
||||||
[Notes] [nvarchar](max) NULL,
|
[Notes] [nvarchar](max) NULL,
|
||||||
CONSTRAINT [PK_ScheduleLog] PRIMARY KEY CLUSTERED
|
CONSTRAINT [PK_JobLog] PRIMARY KEY CLUSTERED
|
||||||
(
|
(
|
||||||
[ScheduleLogId] ASC
|
[JobLogId] ASC
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
GO
|
GO
|
||||||
|
@ -107,8 +110,8 @@ REFERENCES [dbo].[Tenant] ([TenantId])
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
GO
|
GO
|
||||||
|
|
||||||
ALTER TABLE [dbo].[ScheduleLog] WITH NOCHECK ADD CONSTRAINT [FK_ScheduleLog_Schedule] FOREIGN KEY([ScheduleId])
|
ALTER TABLE [dbo].[JobLog] WITH NOCHECK ADD CONSTRAINT [FK_JobLog_Job] FOREIGN KEY([JobId])
|
||||||
REFERENCES [dbo].[Schedule] ([ScheduleId])
|
REFERENCES [dbo].[Job] ([JobId])
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
@ -132,3 +135,12 @@ VALUES (1, N'{Alias}', 1, 1, '', getdate(), '', getdate())
|
||||||
GO
|
GO
|
||||||
SET IDENTITY_INSERT [dbo].[Alias] OFF
|
SET IDENTITY_INSERT [dbo].[Alias] OFF
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
SET IDENTITY_INSERT [dbo].[Job] ON
|
||||||
|
GO
|
||||||
|
INSERT [dbo].[Job] ([JobId], [Name], [JobType], [Frequency], [Interval], [StartDate], [EndDate], [IsEnabled], [IsStarted], [IsExecuting], [NextExecution], [RetentionHistory], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
|
||||||
|
VALUES (1, N'Sample Daily Job', N'Oqtane.Infrastructure.SampleJob, Oqtane.Server', N'd', 1, null, null, 1, 0, 0, null, 10, '', getdate(), '', getdate())
|
||||||
|
GO
|
||||||
|
SET IDENTITY_INSERT [dbo].[Job] OFF
|
||||||
|
GO
|
||||||
|
|
||||||
|
|
|
@ -100,8 +100,8 @@ namespace Oqtane.Server
|
||||||
services.AddScoped<IFileService, FileService>();
|
services.AddScoped<IFileService, FileService>();
|
||||||
services.AddScoped<IPackageService, PackageService>();
|
services.AddScoped<IPackageService, PackageService>();
|
||||||
services.AddScoped<ILogService, LogService>();
|
services.AddScoped<ILogService, LogService>();
|
||||||
services.AddScoped<IScheduleService, ScheduleService>();
|
services.AddScoped<IJobService, JobService>();
|
||||||
services.AddScoped<IScheduleLogService, ScheduleLogService>();
|
services.AddScoped<IJobLogService, JobLogService>();
|
||||||
|
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
|
@ -173,8 +173,8 @@ namespace Oqtane.Server
|
||||||
services.AddTransient<ISettingRepository, SettingRepository>();
|
services.AddTransient<ISettingRepository, SettingRepository>();
|
||||||
services.AddTransient<ILogRepository, LogRepository>();
|
services.AddTransient<ILogRepository, LogRepository>();
|
||||||
services.AddTransient<ILogManager, LogManager>();
|
services.AddTransient<ILogManager, LogManager>();
|
||||||
services.AddTransient<IScheduleRepository, ScheduleRepository>();
|
services.AddTransient<IJobRepository, JobRepository>();
|
||||||
services.AddTransient<IScheduleLogRepository, ScheduleLogRepository>();
|
services.AddTransient<IJobLogRepository, JobLogRepository>();
|
||||||
|
|
||||||
// get list of loaded assemblies
|
// get list of loaded assemblies
|
||||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||||
|
@ -382,8 +382,8 @@ namespace Oqtane.Server
|
||||||
services.AddTransient<ISettingRepository, SettingRepository>();
|
services.AddTransient<ISettingRepository, SettingRepository>();
|
||||||
services.AddTransient<ILogRepository, LogRepository>();
|
services.AddTransient<ILogRepository, LogRepository>();
|
||||||
services.AddTransient<ILogManager, LogManager>();
|
services.AddTransient<ILogManager, LogManager>();
|
||||||
services.AddTransient<IScheduleRepository, ScheduleRepository>();
|
services.AddTransient<IJobRepository, JobRepository>();
|
||||||
services.AddTransient<IScheduleLogRepository, ScheduleLogRepository>();
|
services.AddTransient<IJobLogRepository, JobLogRepository>();
|
||||||
|
|
||||||
// get list of loaded assemblies
|
// get list of loaded assemblies
|
||||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||||
|
|
|
@ -2,15 +2,17 @@
|
||||||
|
|
||||||
namespace Oqtane.Models
|
namespace Oqtane.Models
|
||||||
{
|
{
|
||||||
public class Schedule : IAuditable
|
public class Job : IAuditable
|
||||||
{
|
{
|
||||||
public int ScheduleId { get; set; }
|
public int JobId { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string JobType { get; set; }
|
public string JobType { get; set; }
|
||||||
public int Period { get; set; }
|
|
||||||
public string Frequency { get; set; }
|
public string Frequency { get; set; }
|
||||||
|
public int Interval { get; set; }
|
||||||
public DateTime? StartDate { get; set; }
|
public DateTime? StartDate { get; set; }
|
||||||
public bool IsActive { get; set; }
|
public DateTime? EndDate { get; set; }
|
||||||
|
public bool IsEnabled { get; set; }
|
||||||
|
public bool IsStarted { get; set; }
|
||||||
public bool IsExecuting { get; set; }
|
public bool IsExecuting { get; set; }
|
||||||
public DateTime? NextExecution { get; set; }
|
public DateTime? NextExecution { get; set; }
|
||||||
public int RetentionHistory { get; set; }
|
public int RetentionHistory { get; set; }
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
namespace Oqtane.Models
|
namespace Oqtane.Models
|
||||||
{
|
{
|
||||||
public class ScheduleLog
|
public class JobLog
|
||||||
{
|
{
|
||||||
public int ScheduleLogId { get; set; }
|
public int JobLogId { get; set; }
|
||||||
public int ScheduleId { get; set; }
|
public int JobId { get; set; }
|
||||||
public DateTime StartDate { get; set; }
|
public DateTime StartDate { get; set; }
|
||||||
public DateTime? FinishDate { get; set; }
|
public DateTime? FinishDate { get; set; }
|
||||||
public bool? Succeeded { get; set; }
|
public bool? Succeeded { get; set; }
|
||||||
public string Notes { get; set; }
|
public string Notes { get; set; }
|
||||||
|
|
||||||
|
public Job Job { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user