diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/DigitalData.Services.EDMIService.wsdl b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/DigitalData.Services.EDMIService.wsdl index f3a8b3f..b60633d 100644 --- a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/DigitalData.Services.EDMIService.wsdl +++ b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/DigitalData.Services.EDMIService.wsdl @@ -14,11 +14,17 @@ - - + + - - + + + + + + + + @@ -31,9 +37,13 @@ - - - + + + + + + + diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/DigitalData.Services.EDMIService.xsd b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/DigitalData.Services.EDMIService.xsd index 954b67a..e0b3476 100644 --- a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/DigitalData.Services.EDMIService.xsd +++ b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/DigitalData.Services.EDMIService.xsd @@ -13,15 +13,29 @@ - + - + - + + + + + + + + + + + + + + + @@ -33,7 +47,7 @@ - + diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.GetJobHistoryGetJobHistoryResponse.datasource b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.GetJobHistoryGetJobHistoryResponse.datasource deleted file mode 100644 index 5844430..0000000 --- a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.GetJobHistoryGetJobHistoryResponse.datasource +++ /dev/null @@ -1,10 +0,0 @@ - - - - ECM.JobRunner.Common.JobRunnerReference.GetJobHistoryGetJobHistoryResponse, Connected Services.JobRunnerReference.Reference.vb.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null - \ No newline at end of file diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.GetJobStatusGetJobStatusResponse.datasource b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.GetJobStatusGetJobStatusResponse.datasource new file mode 100644 index 0000000..c97a588 --- /dev/null +++ b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.GetJobStatusGetJobStatusResponse.datasource @@ -0,0 +1,10 @@ + + + + ECM.JobRunner.Common.JobRunnerReference.GetJobStatusGetJobStatusResponse, Connected Services.JobRunnerReference.Reference.vb.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.UpdateJobUpdateJobResponse.datasource b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.UpdateJobUpdateJobResponse.datasource new file mode 100644 index 0000000..eb713ef --- /dev/null +++ b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.JobRunnerReference.UpdateJobUpdateJobResponse.datasource @@ -0,0 +1,10 @@ + + + + ECM.JobRunner.Common.JobRunnerReference.UpdateJobUpdateJobResponse, Connected Services.JobRunnerReference.Reference.vb.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.xsd b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.xsd index 633107e..ba385b7 100644 --- a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.xsd +++ b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Common.xsd @@ -1,5 +1,6 @@  - + + @@ -16,12 +17,25 @@ - + - + - + + + + + + + + + + + + + + @@ -41,6 +55,12 @@ + + + + + + diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Windows.xsd b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Windows.xsd index 1d037c6..463249c 100644 --- a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Windows.xsd +++ b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/ECM.JobRunner.Windows.xsd @@ -1,16 +1,17 @@  - + - + + - + @@ -19,12 +20,35 @@ + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/Reference.vb b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/Reference.vb index 4c22bd5..4baf8c0 100644 --- a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/Reference.vb +++ b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/Reference.vb @@ -15,80 +15,81 @@ Imports System Imports System.Runtime.Serialization Namespace JobRunnerReference - - _ + + Partial Public Class BaseBaseResponse Inherits Object Implements System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged - - _ + + Private extensionDataField As System.Runtime.Serialization.ExtensionDataObject - - _ + + Private ErrorDetailsField As String - - _ + + Private ErrorMessageField As String - - _ + + Private OKField As Boolean - - _ + + Public Property ExtensionData() As System.Runtime.Serialization.ExtensionDataObject Implements System.Runtime.Serialization.IExtensibleDataObject.ExtensionData Get Return Me.extensionDataField End Get Set - Me.extensionDataField = value + Me.extensionDataField = Value End Set End Property - - _ + + Public Property ErrorDetails() As String Get Return Me.ErrorDetailsField End Get Set - If (Object.ReferenceEquals(Me.ErrorDetailsField, value) <> true) Then - Me.ErrorDetailsField = value + If (Object.ReferenceEquals(Me.ErrorDetailsField, Value) <> True) Then + Me.ErrorDetailsField = Value Me.RaisePropertyChanged("ErrorDetails") End If End Set End Property - - _ + + Public Property ErrorMessage() As String Get Return Me.ErrorMessageField End Get Set - If (Object.ReferenceEquals(Me.ErrorMessageField, value) <> true) Then - Me.ErrorMessageField = value + If (Object.ReferenceEquals(Me.ErrorMessageField, Value) <> True) Then + Me.ErrorMessageField = Value Me.RaisePropertyChanged("ErrorMessage") End If End Set End Property - - _ + + Public Property OK() As Boolean Get Return Me.OKField End Get Set - If (Me.OKField.Equals(value) <> true) Then - Me.OKField = value + If (Me.OKField.Equals(Value) <> True) Then + Me.OKField = Value Me.RaisePropertyChanged("OK") End If End Set End Property - + Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged - + Protected Sub RaisePropertyChanged(ByVal propertyName As String) Dim propertyChanged As System.ComponentModel.PropertyChangedEventHandler = Me.PropertyChangedEvent If (Not (propertyChanged) Is Nothing) Then @@ -97,6 +98,14 @@ Namespace JobRunnerReference End Sub End Class + + Partial Public Class UpdateJobUpdateJobResponse + Inherits JobRunnerReference.BaseBaseResponse + End Class + - Partial Public Class GetJobHistoryGetJobHistoryResponse + Partial Public Class GetJobStatusGetJobStatusResponse Inherits JobRunnerReference.BaseBaseResponse - Private ItemsField() As JobRunnerReference.HistoryItem + Private HistoryItemsField() As JobRunnerReference.HistoryItem + + + Private StatusItemsField() As JobRunnerReference.StatusItem - Public Property Items() As JobRunnerReference.HistoryItem() + Public Property HistoryItems() As JobRunnerReference.HistoryItem() Get - Return Me.ItemsField + Return Me.HistoryItemsField End Get Set - If (Object.ReferenceEquals(Me.ItemsField, Value) <> True) Then - Me.ItemsField = Value - Me.RaisePropertyChanged("Items") + If (Object.ReferenceEquals(Me.HistoryItemsField, Value) <> True) Then + Me.HistoryItemsField = Value + Me.RaisePropertyChanged("HistoryItems") + End If + End Set + End Property + + + Public Property StatusItems() As JobRunnerReference.StatusItem() + Get + Return Me.StatusItemsField + End Get + Set + If (Object.ReferenceEquals(Me.StatusItemsField, Value) <> True) Then + Me.StatusItemsField = Value + Me.RaisePropertyChanged("StatusItems") End If End Set End Property @@ -272,6 +297,165 @@ Namespace JobRunnerReference End Sub End Class + + Partial Public Class StatusItem + Inherits Object + Implements System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged + + + Private extensionDataField As System.Runtime.Serialization.ExtensionDataObject + + + Private CompleteTimeField As Date + + + Private ExecutingField As Boolean + + + Private ExecutionTimeField As System.TimeSpan + + + Private IdField As String + + + Private NameField As String + + + Private ProgressCurrentField As Integer + + + Private ProgressTotalField As Integer + + + Private StartTimeField As Date + + + Public Property ExtensionData() As System.Runtime.Serialization.ExtensionDataObject Implements System.Runtime.Serialization.IExtensibleDataObject.ExtensionData + Get + Return Me.extensionDataField + End Get + Set + Me.extensionDataField = Value + End Set + End Property + + + Public Property CompleteTime() As Date + Get + Return Me.CompleteTimeField + End Get + Set + If (Me.CompleteTimeField.Equals(Value) <> True) Then + Me.CompleteTimeField = Value + Me.RaisePropertyChanged("CompleteTime") + End If + End Set + End Property + + + Public Property Executing() As Boolean + Get + Return Me.ExecutingField + End Get + Set + If (Me.ExecutingField.Equals(Value) <> True) Then + Me.ExecutingField = Value + Me.RaisePropertyChanged("Executing") + End If + End Set + End Property + + + Public Property ExecutionTime() As System.TimeSpan + Get + Return Me.ExecutionTimeField + End Get + Set + If (Me.ExecutionTimeField.Equals(Value) <> True) Then + Me.ExecutionTimeField = Value + Me.RaisePropertyChanged("ExecutionTime") + End If + End Set + End Property + + + Public Property Id() As String + Get + Return Me.IdField + End Get + Set + If (Object.ReferenceEquals(Me.IdField, Value) <> True) Then + Me.IdField = Value + Me.RaisePropertyChanged("Id") + End If + End Set + End Property + + + Public Property Name() As String + Get + Return Me.NameField + End Get + Set + If (Object.ReferenceEquals(Me.NameField, Value) <> True) Then + Me.NameField = Value + Me.RaisePropertyChanged("Name") + End If + End Set + End Property + + + Public Property ProgressCurrent() As Integer + Get + Return Me.ProgressCurrentField + End Get + Set + If (Me.ProgressCurrentField.Equals(Value) <> True) Then + Me.ProgressCurrentField = Value + Me.RaisePropertyChanged("ProgressCurrent") + End If + End Set + End Property + + + Public Property ProgressTotal() As Integer + Get + Return Me.ProgressTotalField + End Get + Set + If (Me.ProgressTotalField.Equals(Value) <> True) Then + Me.ProgressTotalField = Value + Me.RaisePropertyChanged("ProgressTotal") + End If + End Set + End Property + + + Public Property StartTime() As Date + Get + Return Me.StartTimeField + End Get + Set + If (Me.StartTimeField.Equals(Value) <> True) Then + Me.StartTimeField = Value + Me.RaisePropertyChanged("StartTime") + End If + End Set + End Property + + Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged + + Protected Sub RaisePropertyChanged(ByVal propertyName As String) + Dim propertyChanged As System.ComponentModel.PropertyChangedEventHandler = Me.PropertyChangedEvent + If (Not (propertyChanged) Is Nothing) Then + propertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName)) + End If + End Sub + End Class + + Partial Public Class UpdateJobUpdateJobRequest + Inherits Object + Implements System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged + + + Private extensionDataField As System.Runtime.Serialization.ExtensionDataObject + + + Private ActionField As JobRunnerReference.UpdateJobUpdateJobRequest.UpdateJobAction + + + Private JobField As JobRunnerReference.JobDefinition + + + Public Property ExtensionData() As System.Runtime.Serialization.ExtensionDataObject Implements System.Runtime.Serialization.IExtensibleDataObject.ExtensionData + Get + Return Me.extensionDataField + End Get + Set + Me.extensionDataField = Value + End Set + End Property + + + Public Property Action() As JobRunnerReference.UpdateJobUpdateJobRequest.UpdateJobAction + Get + Return Me.ActionField + End Get + Set + If (Me.ActionField.Equals(Value) <> True) Then + Me.ActionField = Value + Me.RaisePropertyChanged("Action") + End If + End Set + End Property + + + Public Property Job() As JobRunnerReference.JobDefinition + Get + Return Me.JobField + End Get + Set + If (Object.ReferenceEquals(Me.JobField, Value) <> True) Then + Me.JobField = Value + Me.RaisePropertyChanged("Job") + End If + End Set + End Property + + Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged + + Protected Sub RaisePropertyChanged(ByVal propertyName As String) + Dim propertyChanged As System.ComponentModel.PropertyChangedEventHandler = Me.PropertyChangedEvent + If (Not (propertyChanged) Is Nothing) Then + propertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName)) + End If + End Sub + + + Public Enum UpdateJobAction As Integer + + + Create = 0 + + + Update = 1 + + + Delete = 2 + End Enum + End Class + Public Interface IEDMIService @@ -488,11 +749,17 @@ Namespace JobRunnerReference Function GetHeartbeatAsync() As System.Threading.Tasks.Task(Of Date) - - Function GetJobHistory() As JobRunnerReference.GetJobHistoryGetJobHistoryResponse + + Function GetJobStatus() As JobRunnerReference.GetJobStatusGetJobStatusResponse - - Function GetJobHistoryAsync() As System.Threading.Tasks.Task(Of JobRunnerReference.GetJobHistoryGetJobHistoryResponse) + + Function GetJobStatusAsync() As System.Threading.Tasks.Task(Of JobRunnerReference.GetJobStatusGetJobStatusResponse) + + + Function UpdateJob(ByVal pData As JobRunnerReference.UpdateJobUpdateJobRequest) As JobRunnerReference.UpdateJobUpdateJobResponse + + + Function UpdateJobAsync(ByVal pData As JobRunnerReference.UpdateJobUpdateJobRequest) As System.Threading.Tasks.Task(Of JobRunnerReference.UpdateJobUpdateJobResponse) Function GetJobConfig() As JobRunnerReference.GetJobConfigGetJobConfigResponse @@ -501,51 +768,59 @@ Namespace JobRunnerReference Function GetJobConfigAsync() As System.Threading.Tasks.Task(Of JobRunnerReference.GetJobConfigGetJobConfigResponse) End Interface - _ + Public Interface IEDMIServiceChannel Inherits JobRunnerReference.IEDMIService, System.ServiceModel.IClientChannel End Interface - - _ + + Partial Public Class EDMIServiceClient Inherits System.ServiceModel.ClientBase(Of JobRunnerReference.IEDMIService) Implements JobRunnerReference.IEDMIService - + Public Sub New() MyBase.New End Sub - + Public Sub New(ByVal endpointConfigurationName As String) MyBase.New(endpointConfigurationName) End Sub - + Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As String) MyBase.New(endpointConfigurationName, remoteAddress) End Sub - + Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As System.ServiceModel.EndpointAddress) MyBase.New(endpointConfigurationName, remoteAddress) End Sub - + Public Sub New(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress) MyBase.New(binding, remoteAddress) End Sub - + Public Function GetHeartbeat() As Date Implements JobRunnerReference.IEDMIService.GetHeartbeat Return MyBase.Channel.GetHeartbeat End Function - + Public Function GetHeartbeatAsync() As System.Threading.Tasks.Task(Of Date) Implements JobRunnerReference.IEDMIService.GetHeartbeatAsync Return MyBase.Channel.GetHeartbeatAsync End Function - - Public Function GetJobHistory() As JobRunnerReference.GetJobHistoryGetJobHistoryResponse Implements JobRunnerReference.IEDMIService.GetJobHistory - Return MyBase.Channel.GetJobHistory + + Public Function GetJobStatus() As JobRunnerReference.GetJobStatusGetJobStatusResponse Implements JobRunnerReference.IEDMIService.GetJobStatus + Return MyBase.Channel.GetJobStatus + End Function + + Public Function GetJobStatusAsync() As System.Threading.Tasks.Task(Of JobRunnerReference.GetJobStatusGetJobStatusResponse) Implements JobRunnerReference.IEDMIService.GetJobStatusAsync + Return MyBase.Channel.GetJobStatusAsync End Function - Public Function GetJobHistoryAsync() As System.Threading.Tasks.Task(Of JobRunnerReference.GetJobHistoryGetJobHistoryResponse) Implements JobRunnerReference.IEDMIService.GetJobHistoryAsync - Return MyBase.Channel.GetJobHistoryAsync + Public Function UpdateJob(ByVal pData As JobRunnerReference.UpdateJobUpdateJobRequest) As JobRunnerReference.UpdateJobUpdateJobResponse Implements JobRunnerReference.IEDMIService.UpdateJob + Return MyBase.Channel.UpdateJob(pData) + End Function + + Public Function UpdateJobAsync(ByVal pData As JobRunnerReference.UpdateJobUpdateJobRequest) As System.Threading.Tasks.Task(Of JobRunnerReference.UpdateJobUpdateJobResponse) Implements JobRunnerReference.IEDMIService.UpdateJobAsync + Return MyBase.Channel.UpdateJobAsync(pData) End Function Public Function GetJobConfig() As JobRunnerReference.GetJobConfigGetJobConfigResponse Implements JobRunnerReference.IEDMIService.GetJobConfig diff --git a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/service.wsdl b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/service.wsdl index 85a9b1c..b4d0d27 100644 --- a/ECM.JobRunner.Common/Connected Services/JobRunnerReference/service.wsdl +++ b/ECM.JobRunner.Common/Connected Services/JobRunnerReference/service.wsdl @@ -50,8 +50,17 @@ - - + + + + + + + + + + + diff --git a/ECM.JobRunner.Common/ECM.JobRunner.Common.vbproj b/ECM.JobRunner.Common/ECM.JobRunner.Common.vbproj index b0ae436..76d76e4 100644 --- a/ECM.JobRunner.Common/ECM.JobRunner.Common.vbproj +++ b/ECM.JobRunner.Common/ECM.JobRunner.Common.vbproj @@ -74,6 +74,7 @@ + True @@ -107,7 +108,10 @@ Reference.svcmap - + + Reference.svcmap + + Reference.svcmap diff --git a/ECM.JobRunner.Common/JobStatus/StatusItem.vb b/ECM.JobRunner.Common/JobStatus/StatusItem.vb new file mode 100644 index 0000000..432a2d0 --- /dev/null +++ b/ECM.JobRunner.Common/JobStatus/StatusItem.vb @@ -0,0 +1,14 @@ +Public Class StatusItem + Public Const PROGRESS_CURRENT = "__Progress_Current" + Public Const PROGRESS_TOTAL = "__Progress_Total" + + Public Id As String + Public Name As String + Public ExecutionTime As TimeSpan + Public ProgressCurrent As Integer + Public ProgressTotal As Integer + Public Executing As Boolean = False + + Public StartTime As Date + Public CompleteTime As Date +End Class diff --git a/ECM.JobRunner.Web/Components/Job/JobForm.razor b/ECM.JobRunner.Web/Components/Job/JobForm.razor new file mode 100644 index 0000000..66ff5ae --- /dev/null +++ b/ECM.JobRunner.Web/Components/Job/JobForm.razor @@ -0,0 +1,89 @@ +@using ECM.JobRunner.Common.JobRunnerReference; +@using ECM.JobRunner.Web.Data; +@inject JobService Jobs; + +@if (job == null) +{ +

Form loading..

+} +else +{ + + + + +
+ + +
Die Datenbank Id des Jobs.
+
+
+ + +
Der Name des Jobs. Wird in der Übersicht angezeigt.
+
+
+ + +
Die Zeitplan des Jobs. Erwartet eine Quartz.NET Cron Expression.
+
+ +
+ + +
Der Typ des Jobs.
+
+ +
+ + +
+ +
+ + + + Back + + +
+
+} + +@code { + [Parameter] + public int JobId { get; set; } + + [Parameter] + public EventCallback OnValidSubmit { get; set; } + + private JobDefinition? job = new(); + private List? types; + + protected override async Task OnInitializedAsync() + { + types = await Jobs.GetJobTypes(); + + if (JobId == Constants.ENTITY_ID_NEW) + { + job = new JobDefinition() { Id = Constants.ENTITY_ID_NEW }; + } + else + { + job = await Jobs.GetJob(JobId); + } + } +} diff --git a/ECM.JobRunner.Web/Components/Status/JobStatus.razor b/ECM.JobRunner.Web/Components/Status/JobStatus.razor new file mode 100644 index 0000000..6b8c8b0 --- /dev/null +++ b/ECM.JobRunner.Web/Components/Status/JobStatus.razor @@ -0,0 +1,5 @@ +

JobStatus

+ +@code { + +} diff --git a/ECM.JobRunner.Web/Components/Status/Progress.razor b/ECM.JobRunner.Web/Components/Status/Progress.razor new file mode 100644 index 0000000..2c1feb6 --- /dev/null +++ b/ECM.JobRunner.Web/Components/Status/Progress.razor @@ -0,0 +1,29 @@ +@using ECM.JobRunner.Common.JobRunnerReference; + +
+
+
+ +@code { + [Parameter] + public StatusItem? jobStatus { get; set; } + + protected float getCompletedPercent(StatusItem? entry) + { + if (entry != null && entry.ProgressCurrent > 0 && entry.ProgressTotal > 0) + { + return ((float)entry.ProgressCurrent / (float)entry.ProgressTotal) * 100; + } + else + { + return 0; + } + } +} diff --git a/ECM.JobRunner.Web/Constants.cs b/ECM.JobRunner.Web/Constants.cs new file mode 100644 index 0000000..fe5ffe1 --- /dev/null +++ b/ECM.JobRunner.Web/Constants.cs @@ -0,0 +1,7 @@ +namespace ECM.JobRunner.Web +{ + public class Constants + { + public const int ENTITY_ID_NEW = -1; + } +} diff --git a/ECM.JobRunner.Web/Data/ApiService.cs b/ECM.JobRunner.Web/Data/ApiService.cs deleted file mode 100644 index 89be948..0000000 --- a/ECM.JobRunner.Web/Data/ApiService.cs +++ /dev/null @@ -1,92 +0,0 @@ -using DigitalData.Modules.Messaging.WCF; -using ECM.JobRunner.Common; - -namespace ECM.JobRunner.Web.Data -{ - public class ApiService - { - private readonly Channel channelManager; - private readonly Common.JobRunnerReference.IEDMIServiceChannel channel; - private ServerAddress address; - - private System.Timers.Timer pollingTimer = new(); - - public event EventHandler DataUpdated; - - public ApiService(LoggingService Logging, WcfService Wcf) - { - channel = Wcf.Channel; - - pollingTimer.Elapsed += PollingTimer_Elapsed; - pollingTimer.Interval = 1000; - pollingTimer.Start(); - } - - protected virtual void OnDataUpdated(ApiStatusResponse e) - { - EventHandler handler = DataUpdated; - if (handler != null) - { - handler(this, e); - } - } - - private async void PollingTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - OnDataUpdated(await GetData()); - } - - public async Task?> GetJobList() - { - var resp = await channel.GetJobConfigAsync(); - - if (resp != null && resp.OK) - { - return resp.JobDefinitions.ToList(); - } - else - { - return null; - } - } - - public async Task GetData() - { - DateTime heartbeat = await GetHeartbeat(); - List jobHistory = await GetHistoryEntries(); - - return new ApiStatusResponse() - { - heartbeat = heartbeat, - jobHistory = jobHistory.OrderByDescending(e => e.CreatedAt).Take(10).ToList() - }; - } - - private async Task GetHeartbeat() - { - return await channel.GetHeartbeatAsync(); - } - - private async Task> GetHistoryEntries() - { - try - { - var oResponse = await channel.GetJobHistoryAsync(); - - if (oResponse.OK) - { - return oResponse.Items.ToList(); - } - else - { - return new(); - } - } - catch (Exception) - { - throw; - } - - } - } -} diff --git a/ECM.JobRunner.Web/Data/ApiStatusResponse.cs b/ECM.JobRunner.Web/Data/DashboardResponse.cs similarity index 70% rename from ECM.JobRunner.Web/Data/ApiStatusResponse.cs rename to ECM.JobRunner.Web/Data/DashboardResponse.cs index 419a618..72c2c7e 100644 --- a/ECM.JobRunner.Web/Data/ApiStatusResponse.cs +++ b/ECM.JobRunner.Web/Data/DashboardResponse.cs @@ -2,9 +2,10 @@ namespace ECM.JobRunner.Web.Data { - public class ApiStatusResponse + public class DashboardResponse { public DateTime heartbeat = DateTime.MinValue; public List jobHistory = new(); + public List jobStatus = new(); } } diff --git a/ECM.JobRunner.Web/Data/DashboardService.cs b/ECM.JobRunner.Web/Data/DashboardService.cs new file mode 100644 index 0000000..0792562 --- /dev/null +++ b/ECM.JobRunner.Web/Data/DashboardService.cs @@ -0,0 +1,107 @@ +using DigitalData.Modules.Logging; +using DigitalData.Modules.Messaging.WCF; +using ECM.JobRunner.Common; + +namespace ECM.JobRunner.Web.Data +{ + public class DashboardService + { + private readonly Common.JobRunnerReference.IEDMIServiceChannel channel; + private Logger logger; + + private System.Timers.Timer pollingTimer = new(); + + public event EventHandler DataUpdated; + + public DashboardService(LoggingService Logging, WcfService Wcf) + { + logger = Logging.LogConfig.GetLogger(); + channel = Wcf.Channel; + + pollingTimer.Elapsed += PollingTimer_Elapsed; + pollingTimer.Interval = 1000; + pollingTimer.Start(); + } + + protected virtual void OnDataUpdated(DashboardResponse e) + { + EventHandler handler = DataUpdated; + if (handler != null) + { + handler(this, e); + } + } + + private async void PollingTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + OnDataUpdated(await GetData()); + } + + + + public async Task GetData() + { + DateTime heartbeat = await GetHeartbeat(); + List jobHistory = await GetHistoryItems(); + List jobStatus = await GetStatusItems(); + + return new DashboardResponse() + { + heartbeat = heartbeat, + jobHistory = jobHistory.OrderByDescending(e => e.CreatedAt).Take(10).ToList(), + jobStatus = jobStatus.OrderByDescending(e => e.StartTime).Take(10).ToList() + }; + } + + private async Task GetHeartbeat() + { + return await channel.GetHeartbeatAsync(); + } + + private async Task> GetHistoryItems() + { + try + { + var oResponse = await channel.GetJobStatusAsync(); + + if (oResponse.OK) + { + return oResponse.HistoryItems.ToList(); + } + else + { + return new(); + } + } + catch (Exception e) + { + logger.Error(e); + return new(); + } + + } + + private async Task> GetStatusItems() + { + try + { + var oResponse = await channel.GetJobStatusAsync(); + + if (oResponse.OK) + { + return oResponse.StatusItems.ToList(); + } + else + { + return new(); + } + } + catch (Exception e) + { + logger.Error(e); + return new(); + } + + } + } +} diff --git a/ECM.JobRunner.Web/Data/JobService.cs b/ECM.JobRunner.Web/Data/JobService.cs new file mode 100644 index 0000000..ed51e47 --- /dev/null +++ b/ECM.JobRunner.Web/Data/JobService.cs @@ -0,0 +1,138 @@ +using DigitalData.Modules.Logging; +using ECM.JobRunner.Common.JobRunnerReference; +using System.Threading.Channels; + +namespace ECM.JobRunner.Web.Data +{ + public class JobService + { + private readonly Logger logger; + private readonly Common.JobRunnerReference.IEDMIServiceChannel channel; + + public JobService(LoggingService Logging, WcfService Wcf) + { + logger = Logging.LogConfig.GetLogger(); + channel = Wcf.Channel; + } + + public async Task> GetJobs() + { + var resp = await channel.GetJobConfigAsync(); + + if (resp != null && resp.OK) + { + return resp.JobDefinitions.ToList(); + } + else + { + return new(); + } + } + + public async Task> GetJobTypes() + { + var resp = await channel.GetJobConfigAsync(); + + if (resp != null && resp.OK) + { + return resp.JobTypes.ToList(); + } + else + { + return new(); + } + } + + public async Task GetJob(int pJobId) + { + var resp = await channel.GetJobConfigAsync(); + + if (resp != null && resp.OK) + { + return resp.JobDefinitions. + Where(j => j.Id == pJobId). + FirstOrDefault(); + } + else + { + return null; + } + } + + public async Task UpdateJob(JobDefinition job) + { + var resp = await channel.UpdateJobAsync(new UpdateJobUpdateJobRequest { + Job = job, + Action = UpdateJobUpdateJobRequest.UpdateJobAction.Update + }); + + if (resp != null && resp.OK) + { + return true; + } + else + { + return false; + } + } + + public async Task CreateJob(JobDefinition job) + { + var resp = await channel.UpdateJobAsync(new UpdateJobUpdateJobRequest + { + Job = job, + Action = UpdateJobUpdateJobRequest.UpdateJobAction.Create + }); + + if (resp != null && resp.OK) + { + return true; + } + else + { + return false; + } + } + + public async Task DeleteJob(JobDefinition job) + { + var resp = await channel.UpdateJobAsync(new UpdateJobUpdateJobRequest + { + Job = job, + Action = UpdateJobUpdateJobRequest.UpdateJobAction.Delete + }); + + if (resp != null && resp.OK) + { + return true; + } + else + { + return false; + } + } + + public DateTime GetNextExecutionTime(string pCronExpression) + { + Quartz.CronExpression expression = new(pCronExpression); + + if (expression != null) + { + var next = expression.GetNextValidTimeAfter(DateTimeOffset.Now); + + if (next != null) + { + return ((DateTimeOffset)next).DateTime; + } + else + { + return DateTime.MinValue; + } + } + else + { + return DateTime.MinValue; + } + } + } +} diff --git a/ECM.JobRunner.Web/ECM.JobRunner.Web.csproj b/ECM.JobRunner.Web/ECM.JobRunner.Web.csproj index 50df0da..f7cb108 100644 --- a/ECM.JobRunner.Web/ECM.JobRunner.Web.csproj +++ b/ECM.JobRunner.Web/ECM.JobRunner.Web.csproj @@ -8,6 +8,7 @@ + diff --git a/ECM.JobRunner.Web/Pages/History.razor b/ECM.JobRunner.Web/Pages/History.razor index 4058f74..7c6cb0f 100644 --- a/ECM.JobRunner.Web/Pages/History.razor +++ b/ECM.JobRunner.Web/Pages/History.razor @@ -1,7 +1,7 @@ @page "/history" @using ECM.JobRunner.Common.JobRunnerReference; @using ECM.JobRunner.Web.Data; -@inject ApiService Api +@inject DashboardService Api History @@ -41,18 +41,18 @@ else protected async override void OnInitialized() { - ApiStatusResponse data = await Api.GetData(); + DashboardResponse data = await Api.GetData(); UpdateData(data); Api.DataUpdated += Api_DataUpdated; } - protected void Api_DataUpdated(object sender, ApiStatusResponse e) + protected void Api_DataUpdated(object sender, DashboardResponse e) { UpdateData(e); } - protected void UpdateData(ApiStatusResponse response) + protected void UpdateData(DashboardResponse response) { today = response.heartbeat; historyEntries = response.jobHistory; diff --git a/ECM.JobRunner.Web/Pages/Job/EditJob.razor b/ECM.JobRunner.Web/Pages/Job/EditJob.razor new file mode 100644 index 0000000..1be0e08 --- /dev/null +++ b/ECM.JobRunner.Web/Pages/Job/EditJob.razor @@ -0,0 +1,28 @@ +@page "/jobs/{jobId:int}/edit" +@using ECM.JobRunner.Common.JobRunnerReference; +@using ECM.JobRunner.Web.Data; +@using ECM.JobRunner.Web.Components.Job; +@inject NavigationManager Navigation; +@inject JobService Jobs; + +Job bearbeiten + +

Job bearbeiten

+ + + +@code { + [Parameter] + public int JobId { get; set; } + + private async void OnFormSubmit(EditContext ctx) + { + JobDefinition job = (JobDefinition)ctx.Model; + bool result = await Jobs.UpdateJob(job); + + if (result == true) + { + Navigation.NavigateTo($"/jobs/{job.Id}"); + } + } +} diff --git a/ECM.JobRunner.Web/Pages/Job/JobList.razor b/ECM.JobRunner.Web/Pages/Job/JobList.razor new file mode 100644 index 0000000..6dc4ccb --- /dev/null +++ b/ECM.JobRunner.Web/Pages/Job/JobList.razor @@ -0,0 +1,76 @@ +@page "/jobs" +@using ECM.JobRunner.Common.JobRunnerReference; +@using ECM.JobRunner.Web.Data; +@inject JobService Jobs + +Jobs + +

Jobs

+ +@if (jobs == null) +{ +
    +
  • Loading Jobs..
  • +
+} +else +{ + + + +} + +@code { + private List? jobs; + + protected async override void OnInitialized() + { + jobs = await Jobs.GetJobs(); + StateHasChanged(); + } +} \ No newline at end of file diff --git a/ECM.JobRunner.Web/Pages/JobPage.razor b/ECM.JobRunner.Web/Pages/Job/JobPage.razor similarity index 88% rename from ECM.JobRunner.Web/Pages/JobPage.razor rename to ECM.JobRunner.Web/Pages/Job/JobPage.razor index 0a91548..5cf602f 100644 --- a/ECM.JobRunner.Web/Pages/JobPage.razor +++ b/ECM.JobRunner.Web/Pages/Job/JobPage.razor @@ -1,7 +1,10 @@ @page "/jobs/{jobId:int}" @using ECM.JobRunner.Common.JobRunnerReference; @using ECM.JobRunner.Web.Data; -@inject ApiService Api + +@inject NavigationManager Navigation; +@inject IJSRuntime JsRuntime +@inject JobService Jobs Job @@ -49,7 +52,7 @@ else Next Run at - @DateTime.Now.AddMinutes(5) + @nextExecution @@ -66,7 +69,7 @@ else Edit - + Delete @@ -79,15 +82,31 @@ else public int JobId { get; set; } private JobDefinition? job; + private DateTime nextExecution; protected async override void OnInitialized() { - var jobs = await Api.GetJobList(); + job = await Jobs.GetJob(JobId); - if (jobs != null) - { - job = jobs.Where(j => j.Id == JobId).SingleOrDefault(); + if (job != null) + { + nextExecution = Jobs.GetNextExecutionTime(job.CronSchedule); StateHasChanged(); } } + + protected async void DeleteJob() + { + if (job != null) + { + bool confirmed = await JsRuntime.InvokeAsync("confirm", "Are you sure?"); + if (confirmed) + { + await Jobs.DeleteJob(job); + Navigation.NavigateTo($"/jobs"); + } + } + } + + } \ No newline at end of file diff --git a/ECM.JobRunner.Web/Pages/Job/NewJob.razor b/ECM.JobRunner.Web/Pages/Job/NewJob.razor new file mode 100644 index 0000000..43f371e --- /dev/null +++ b/ECM.JobRunner.Web/Pages/Job/NewJob.razor @@ -0,0 +1,28 @@ +@page "/jobs/new" +@using ECM.JobRunner.Common.JobRunnerReference; +@using ECM.JobRunner.Web.Data; +@using ECM.JobRunner.Web.Components.Job; +@inject NavigationManager Navigation; +@inject JobService Jobs; + +Job erstellen + +

Job erstellen

+ + + +@code { + public int JobId = -1; + + private async void OnFormSubmit(EditContext ctx) + { + JobDefinition job = (JobDefinition)ctx.Model; + + bool result = await Jobs.CreateJob(job); + + if (result == true) + { + Navigation.NavigateTo($"/jobs"); + } + } +} diff --git a/ECM.JobRunner.Web/Pages/JobForm.razor b/ECM.JobRunner.Web/Pages/JobForm.razor deleted file mode 100644 index 883ad3b..0000000 --- a/ECM.JobRunner.Web/Pages/JobForm.razor +++ /dev/null @@ -1,5 +0,0 @@ -

JobForm

- -@code { - -} diff --git a/ECM.JobRunner.Web/Pages/JobList.razor b/ECM.JobRunner.Web/Pages/JobList.razor deleted file mode 100644 index ca08a65..0000000 --- a/ECM.JobRunner.Web/Pages/JobList.razor +++ /dev/null @@ -1,42 +0,0 @@ -@page "/jobs" -@using ECM.JobRunner.Common.JobRunnerReference; -@using ECM.JobRunner.Web.Data; -@inject ApiService Api - -Jobs - -

Jobs

- -@if (jobList == null) -{ -
    -
  • Loading Jobs..
  • -
-} -else -{ -
-} - -@code { - private List? jobList; - - protected async override void OnInitialized() - { - jobList = await Api.GetJobList(); - StateHasChanged(); - } -} \ No newline at end of file diff --git a/ECM.JobRunner.Web/Pages/NewJob.razor b/ECM.JobRunner.Web/Pages/NewJob.razor deleted file mode 100644 index 6ccc168..0000000 --- a/ECM.JobRunner.Web/Pages/NewJob.razor +++ /dev/null @@ -1,7 +0,0 @@ -New Job - -

New Job

- -@code { - -} diff --git a/ECM.JobRunner.Web/Pages/Status.razor b/ECM.JobRunner.Web/Pages/Status.razor new file mode 100644 index 0000000..ff2d80c --- /dev/null +++ b/ECM.JobRunner.Web/Pages/Status.razor @@ -0,0 +1,135 @@ +@page "/status" +@using ECM.JobRunner.Common.JobRunnerReference; +@using ECM.JobRunner.Web.Components.Status; +@using ECM.JobRunner.Web.Data; +@inject DashboardService Api + +Status + +

Job Status

+ +
+ @if (executingEntries == null) + { +

Executing

+ +
    +
  • Loading Job Status..
  • +
+ } + else if (executingEntries.Count == 0) + { +

Executing

+
    +
  • No jobs currently executing
  • +
+ } + else + { +

Executing (@executingEntries.Count)

+ +
    + @foreach (var entry in executingEntries) + { +
  • +
    +
    +
    + + + + + @entry.Name +
    + +
    + Started @entry.StartTime.ToLongTimeString() +
    + +
  • + } +
+ } + +
+ +@if (completedEntries == null) +{ +

Completed

+ +
    +
  • Loading Job Status..
  • +
+} +else if (completedEntries.Count == 0) +{ +

Completed

+ +
    +
  • No jobs currently executing
  • +
+} +else +{ +

Completed (@completedEntries.Count)

+ +
    + @foreach (var entry in completedEntries) + { +
  • +
    +
    + + + + + @entry.Name +
    +
      +
    • Execution Time: @((int)entry.ExecutionTime.TotalSeconds)s
    • +
    • Started: @entry.StartTime.ToLongTimeString()
    • +
    • Completed: @entry.CompleteTime.ToLongTimeString()
    • +
    +
    + Completed @entry.CompleteTime.ToLongTimeString() +
  • + } +
+} + + +@code { + private DateTime today; + private List? executingEntries; + private List? completedEntries; + + protected async override void OnInitialized() + { + DashboardResponse data = await Api.GetData(); + UpdateData(data); + + Api.DataUpdated += Api_DataUpdated; + } + + protected void Api_DataUpdated(object sender, DashboardResponse e) + { + UpdateData(e); + } + + protected void UpdateData(DashboardResponse response) + { + today = response.heartbeat; + + executingEntries = response.jobStatus. + Where(s => s.ProgressTotal > 0). + Where(s => s.Executing). + ToList(); + + completedEntries = response.jobStatus. + Where(s => !s.Executing). + Where(s => s.StartTime.AddMinutes(1) > DateTime.Now). + ToList(); + + InvokeAsync(StateHasChanged); + } +} diff --git a/ECM.JobRunner.Web/Program.cs b/ECM.JobRunner.Web/Program.cs index 57bacea..3e6e5c8 100644 --- a/ECM.JobRunner.Web/Program.cs +++ b/ECM.JobRunner.Web/Program.cs @@ -11,7 +11,8 @@ builder.Services.AddServerSideBlazor(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddSingleton(); -builder.Services.AddTransient(); +builder.Services.AddTransient(); +builder.Services.AddTransient(); var app = builder.Build(); diff --git a/ECM.JobRunner.Web/Shared/NavMenu.razor b/ECM.JobRunner.Web/Shared/NavMenu.razor index 869b555..9099d9a 100644 --- a/ECM.JobRunner.Web/Shared/NavMenu.razor +++ b/ECM.JobRunner.Web/Shared/NavMenu.razor @@ -24,6 +24,14 @@ Jobs +