aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules
diff options
context:
space:
mode:
authorShlomo Hecht <shlomo@twine-s.com>2020-03-18 10:03:11 +0200
committerShlomo Hecht <shlomo@twine-s.com>2020-03-18 10:03:11 +0200
commitada2ce25bd36b6f7b3c8aa01039cc9611b22e55c (patch)
tree0684b4e94a807188d2d92f46c33ed36b724692bc /Software/Visual_Studio/MachineStudio/Modules
parent2cd94c78ab9de58fc1f8525e69ab5fa563d0ff75 (diff)
parentcb7fff096f2fe6812184a286290eaad193c7c2df (diff)
downloadTango-ada2ce25bd36b6f7b3c8aa01039cc9611b22e55c.tar.gz
Tango-ada2ce25bd36b6f7b3c8aa01039cc9611b22e55c.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/Tango/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules')
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs67
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml4
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Controls/JobOutlineControl.cs14
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs19
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml8
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml.cs5
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs2
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs4
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineSettingsView.xaml9
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachinesView.xaml2
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/SpoolsView.xaml11
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj14
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs237
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/MainView.xaml2
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ProcessParametersView.xaml2
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml25
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/SpoolsView.xaml85
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/SpoolsView.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ThreadParametersView.xaml98
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ThreadParametersView.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/App.config20
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/CollectionConverter .cs44
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/DateTimeToStringFormatConverter.cs30
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/JobLengthConverter.cs35
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/LiquidTypeToColorConverter.cs43
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/MidTankLevelToElementHeightConverter.cs41
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/NanoLiterToLiterFormatConverter.cs30
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToBoolYesNoNullConverter.cs37
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToFirstLetterConverter.cs30
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs48
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunStatisticsModel.cs45
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/RmlModel.cs15
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/StatisticsValueCollection.cs312
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj38
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs413
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs486
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs338
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml113
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml.cs35
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml699
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs86
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml114
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs6
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/packages.config1
44 files changed, 3141 insertions, 582 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs
index 408789d9f..df2643d88 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs
@@ -16,12 +16,15 @@ using Tango.BL.ValueObjects;
using Tango.Core.Commands;
using Tango.Core.ExtensionMethods;
using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Common.Notifications;
using Tango.SharedUI.Components;
namespace Tango.MachineStudio.ActionLogs.ViewModels
{
public class MainViewVM : StudioViewModel
{
+ private INotificationProvider _notification;
+
#region Properties
private DateTime _startSelectedDate;
@@ -83,30 +86,23 @@ namespace Tango.MachineStudio.ActionLogs.ViewModels
set { _differenceObject = value; RaisePropertyChangedAuto(); }
}
-
- private bool _isRunning;
- public bool IsRunning
- {
- get { return _isRunning; }
- set { _isRunning = value; }
- }
-
#endregion
public RelayCommand SearchCommand { get; set; }
public RelayCommand CopyToClipBoardCommand { get; set; }
public RelayCommand CopyRelateObjectIDCommand { get; set; }
- public MainViewVM()
+ public MainViewVM(INotificationProvider notification)
{
+ _notification = notification;
+
ActionLogs = new ObservableCollection<ActionLog>();
- SearchCommand = new RelayCommand(GetActionLogs, () => !IsRunning);
+ SearchCommand = new RelayCommand(GetActionLogs, () => IsFree);
CopyRelateObjectIDCommand = new RelayCommand(CopyRelateObjectID);
CopyToClipBoardCommand = new RelayCommand(CopyToClipBoard, () => SelectedActionLog != null && SelectedActionLog.DifferenceObject != null);
DateTime now = DateTime.Now;
StartSelectedDate = now.AddMonths(-1);
EndSelectedDate = now;
- _isRunning = false;
var source = Enum.GetValues(typeof(ActionLogType)).Cast<ActionLogType>().ToObservableCollection();
var syncedSource = Enum.GetValues(typeof(ActionLogType)).Cast<ActionLogType>().ToObservableCollection();
@@ -139,23 +135,40 @@ namespace Tango.MachineStudio.ActionLogs.ViewModels
if (String.IsNullOrWhiteSpace(filter)) filter = null;
- using (ObservablesContext db = ObservablesContext.CreateDefault())
+ try
+ {
+ IsFree = false;
+
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+
+ DateTime startUtc = new DateTime(StartSelectedDate.Date.Ticks, DateTimeKind.Utc);
+ TimeSpan offsetTime = (EndSelectedDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(24, 0, 0);
+ DateTime endUtc = new DateTime(EndSelectedDate.Date.Ticks + offsetTime.Ticks, DateTimeKind.Utc);
+
+ Debug.Write($"TEST TIME {startUtc} from {endUtc} " + System.Environment.NewLine);
+
+ ActionLogs = await new ActionLogsCollectionBuilder(db).Set(x => x.LastUpdated <= DbFunctions.TruncateTime(endUtc) && x.LastUpdated >= DbFunctions.TruncateTime(startUtc))
+ .WithUsers()
+ .WithActionType(SelectedActionLogTypes.SynchedSource.ToArray())
+ .Query(y => y.Where
+ (x => filter == null ||
+ (x.ID.ToString().ToLower().StartsWith(filter)
+ || (x.RelatedObjectName != null && x.RelatedObjectName.ToLower().StartsWith(filter))
+ || (x.RelatedObjectGuid != null && x.RelatedObjectGuid.ToLower().StartsWith(filter))
+ || (x.User != null && x.User.Contact != null && x.User.Contact.FullName.ToLower().StartsWith(filter)))))
+ .BuildAsync();
+ }
+ }
+ catch (Exception ex)
+ {
+ IsFree = true;
+ LogManager.Log(ex, "Error getting action logs.");
+ _notification.ShowError($"Error occurred while trying to retrieve the action logs.\n{ex.Message}");
+ }
+ finally
{
- DateTime startUtc = StartSelectedDate.ToUniversalTime();
- TimeSpan offsetTime = (EndSelectedDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(23, 59, 59);
- DateTime endUtc = EndSelectedDate.ToUniversalTime() + offsetTime;
- IsRunning = true;
- ActionLogs = await new ActionLogsCollectionBuilder(db).Set(x => x.LastUpdated <= DbFunctions.TruncateTime(endUtc) && x.LastUpdated >= DbFunctions.TruncateTime(startUtc.Date))
- .WithUsers()
- .WithActionType(SelectedActionLogTypes.SynchedSource.ToArray())
- .Query(y => y.Where
- (x => filter == null ||
- (x.ID.ToString().ToLower().StartsWith(filter)
- || (x.RelatedObjectName != null && x.RelatedObjectName.ToLower().StartsWith(filter))
- || (x.RelatedObjectGuid != null && x.RelatedObjectGuid.ToLower().StartsWith(filter))
- || (x.User != null && x.User.Contact != null && x.User.Contact.FullName.ToLower().StartsWith(filter)))))
- .BuildAsync();
- IsRunning = false;
+ IsFree = true;
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml
index 3a7eaa802..02083918b 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml
@@ -207,9 +207,9 @@
</DataGrid.Columns>
</DataGrid>
</Grid>
- <Grid Grid.Row="1" Grid.Column="0" Visibility="{Binding IsRunning,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <Grid Grid.Row="1" Grid.Column="0" Visibility="{Binding IsBusy,Converter={StaticResource BooleanToVisibilityConverter}}">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
- <mahapps:ProgressRing Margin="20 60 20 40" Width="80" Height="80" IsActive="{Binding IsRunning}"></mahapps:ProgressRing>
+ <mahapps:ProgressRing Margin="20 60 20 40" Width="80" Height="80" IsActive="{Binding IsBusy}"></mahapps:ProgressRing>
<TextBlock Text="Loading..." HorizontalAlignment="Center" FontSize="20" FontStyle="Italic" VerticalAlignment="Center" Margin="0 20 0 0"></TextBlock>
</StackPanel>
</Grid>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Controls/JobOutlineControl.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Controls/JobOutlineControl.cs
index ee570ac34..5a3f5d337 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Controls/JobOutlineControl.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Controls/JobOutlineControl.cs
@@ -136,6 +136,20 @@ namespace Tango.MachineStudio.Developer.Controls
_sizeControl.Height += NORMAL_FONT_HEIGHT;
}
}
+ //JobTicket.ThreadParameters
+ if (job.ThreadParameters != null)
+ {
+ _sizeControl.Height += 20;
+ DrawHeaderText(drawingContext, "THREAD PARAMETERS", 17, LevelOffset.level_0);
+ _sizeControl.Height += TITLE_FONT_HEIGHT;
+ _sizeControl.Height += 5.0;
+ basicProps = GetNameValueList(job.ThreadParameters);
+ foreach (var prop in basicProps)
+ {
+ DrawNameValueText(drawingContext, prop, LevelOffset.level_1, PackIconKind.Settings);
+ _sizeControl.Height += NORMAL_FONT_HEIGHT;
+ }
+ }
//JobTicket.Segments
if (job.Segments != null)
{
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs
index efbcaf5ad..9f0ea3423 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs
@@ -1622,7 +1622,7 @@ namespace Tango.MachineStudio.Developer.ViewModels
{
LogManager.Log("Invalidating liquid factors, process parameters and process group history...");
- _selectedRML = new RmlBuilder(_activeJobDbContext).Set(SelectedRML.Guid).WithAllParametersGroup().WithCAT(SelectedMachine.Guid).WithCCT().WithLiquidFactors().Build();
+ _selectedRML = new RmlBuilder(_activeJobDbContext).Set(SelectedRML.Guid).WithAllParametersGroup().WithCAT(SelectedMachine.Guid).WithCCT().WithLiquidFactors().WithSpools().Build();
_selectedRMLBeforeLiquidFactorsSaves = RmlDTO.FromObservable(_selectedRML);
@@ -1681,6 +1681,23 @@ namespace Tango.MachineStudio.Developer.ViewModels
#endregion
+ #region Color Space
+
+ public void OnBrushStopColorSpaceChanged(BrushStop stop)
+ {
+ if (stop != null && stop.ColorSpace != null && stop.BrushColorSpace != BL.Enumerations.ColorSpaces.Volume)
+ {
+ var lubricant = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Lubricant);
+
+ if (lubricant != null)
+ {
+ lubricant.Volume = 100;
+ }
+ }
+ }
+
+ #endregion
+
#region Process Parameters Management
/// <summary>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml
index bf8eddd91..ed8fc57fe 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml
@@ -680,7 +680,7 @@
</StackPanel>
</Border>
- <Border Style="{StaticResource JobFieldBorder}">
+ <Border Style="{StaticResource JobFieldBorder}" Visibility="{Binding IsSideBarOpened,Converter={StaticResource BooleanToVisibilityInverseConverter}}">
<StackPanel Margin="20 5 5 5" Width="140">
<StackPanel Orientation="Horizontal">
<Image Source="../Images/repeat.png" Width="32"></Image>
@@ -792,7 +792,7 @@
</StackPanel>
- <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="60 40 180 0">
+ <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="60 40 180 0" Visibility="{Binding IsSideBarOpened,Converter={StaticResource BooleanToVisibilityInverseConverter}}">
<materialDesign:PackIcon Kind="ChevronLeft" Width="24" Height="24" />
<TextBlock Margin="0 -2 0 0" VerticalAlignment="Center"><Run>MEDIA LIQUIDS</Run> <Run FontSize="10" Foreground="{StaticResource DimGrayBrush}">( Max Nanolitter/CM )</Run></TextBlock>
<materialDesign:PackIcon Kind="ChevronRight" Width="24" Height="24" />
@@ -898,7 +898,7 @@
</DockPanel>
</Grid>
<Grid Margin="0 10 10 0">
- <controls:MultiSelectListBox x:Name="listStops" AutomationProperties.AutomationId="{x:Static automation:Developer.BrushStopsListBox}" SelectionMode="Extended" Style="{x:Null}" Background="Transparent" ScrollViewer.CanContentScroll="False" BorderThickness="0" ItemsSource="{Binding BrushStopsCollectionView}" SelectedItem="{Binding SelectedBrushStop}" SelectedItemsList="{Binding SelectedBrushStops,Mode=TwoWay}" HorizontalContentAlignment="Stretch">
+ <controls:MultiSelectListBox x:Name="listStops" ScrollViewer.HorizontalScrollBarVisibility="Disabled" AutomationProperties.AutomationId="{x:Static automation:Developer.BrushStopsListBox}" SelectionMode="Extended" Style="{x:Null}" Background="Transparent" ScrollViewer.CanContentScroll="False" BorderThickness="0" ItemsSource="{Binding BrushStopsCollectionView}" SelectedItem="{Binding SelectedBrushStop}" SelectedItemsList="{Binding SelectedBrushStops,Mode=TwoWay}" HorizontalContentAlignment="Stretch">
<ListBox.Template>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
@@ -976,7 +976,7 @@
<Image Source="../Images/colorspace.png" Width="24"></Image>
<TextBlock VerticalAlignment="Center" Margin="5 0 0 0" FontSize="10">Color Space</TextBlock>
</StackPanel>
- <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.ColorSpaces}" SelectedItem="{Binding ColorSpace}" DisplayMemberPath="Name" Width="100" HorizontalAlignment="Left">
+ <ComboBox SelectionChanged="OnBrushStopColorSpace_SelectionChanged" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.ColorSpaces}" SelectedItem="{Binding ColorSpace}" DisplayMemberPath="Name" Width="100" HorizontalAlignment="Left">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
<Setter Property="Background" Value="{StaticResource WhiteBrush100}"></Setter>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml.cs
index a4a8fdcf4..94c1ed802 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml.cs
@@ -281,5 +281,10 @@ namespace Tango.MachineStudio.Developer.Views
{
listStops.SelectedItem = (sender as ListBoxItem).DataContext;
}
+
+ private void OnBrushStopColorSpace_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ _vm.OnBrushStopColorSpaceChanged((sender as ComboBox).DataContext as BrushStop);
+ }
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs
index 0a8780346..cf66c1a34 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/ViewModels/MainViewVM.cs
@@ -233,7 +233,7 @@ namespace Tango.MachineStudio.HardwareDesigner.ViewModels
private void CopyParameters(object obj)
{
- obj.MapPropertiesTo(SelectedHardwareObject, MappingFlags.PrimitivesOnly,
+ obj.MapPropertiesTo(SelectedHardwareObject, MappingFlags.ValueTypesOnly,
(prop) =>
!prop.PropertyType.IsEnum
&&
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs
index e0d99d0f0..ed93b4308 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/MainViewVM.cs
@@ -523,7 +523,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels
try
{
initHwConfig = false;
- ActiveMachine = machineCreationDialogVM.SelectedMachineVersion.CreatePrototypeMachine(ActiveMachineAdapter.Context);
+ ActiveMachine = await machineCreationDialogVM.SelectedMachineVersion.CreatePrototypeMachine(ActiveMachineAdapter.Context);
ActiveMachine.SerialNumber = machineCreationDialogVM.SerialNumber;
ActiveMachine.Name = machineCreationDialogVM.Name;
ActiveMachineAdapter.Context.Machines.Add(ActiveMachine);
@@ -547,7 +547,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels
{
var serial = machineCreationDialogVM.SerialNumber + "-" + (i + 1);
- var existingDispenser = await ActiveMachineAdapter.Context.Dispensers.Include(x => x.IdsPacks).SingleAsync(x => x.SerialNumber == serial);
+ var existingDispenser = await ActiveMachineAdapter.Context.Dispensers.Include(x => x.IdsPacks).SingleOrDefaultAsync(x => x.SerialNumber == serial);
if (existingDispenser != null)
{
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineSettingsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineSettingsView.xaml
index 499d6dc89..954ac5f0e 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineSettingsView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineSettingsView.xaml
@@ -6,6 +6,7 @@
xmlns:local="clr-namespace:Tango.MachineStudio.MachineDesigner.Views"
xmlns:global="clr-namespace:Tango.MachineStudio.MachineDesigner"
xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:enumerations="clr-namespace:Tango.BL.Enumerations;assembly=Tango.BL"
xmlns:observables="clr-namespace:Tango.BL.Entities;assembly=Tango.BL"
xmlns:vm="clr-namespace:Tango.MachineStudio.MachineDesigner.ViewModels"
xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
@@ -13,6 +14,11 @@
xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
mc:Ignorable="d"
d:DesignHeight="1080" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
+
+ <UserControl.Resources>
+ <converters:EnumToItemsSourceConverter x:Key="EnumToItemsSourceConverter"/>
+ </UserControl.Resources>
+
<Grid Margin="20">
<DockPanel>
<Grid DockPanel.Dock="Bottom">
@@ -44,6 +50,9 @@
<TextBlock FontWeight="SemiBold">Name</TextBlock>
<TextBox Text="{Binding ActiveMachine.Name}"></TextBox>
+ <TextBlock FontWeight="SemiBold">Head Type</TextBlock>
+ <ComboBox ItemsSource="{Binding Source={x:Type enumerations:HeadTypes},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValue="{Binding ActiveMachine.MachineHeadType}" SelectedValuePath="Value" DisplayMemberPath="DisplayName"></ComboBox>
+
<TextBlock FontWeight="SemiBold">Machine Version</TextBlock>
<ComboBox Background="Transparent" ItemsSource="{Binding ActiveMachineAdapter.MachineVersions}" SelectedItem="{Binding ActiveMachine.MachineVersion}" DisplayMemberPath="Name" Style="{StaticResource TransparentComboBoxStyle}"></ComboBox>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachinesView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachinesView.xaml
index 446303aa2..a231e92a3 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachinesView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachinesView.xaml
@@ -26,7 +26,7 @@
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Margin="0 0 0 10">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="BarcodeScan" Width="32" Height="32" />
- <TextBox Width="400" FontSize="20" Margin="10 0 0 0" materialDesign:HintAssist.Hint="Serial Number" Text="{Binding Filter,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Delay=1500}"></TextBox>
+ <TextBox Width="400" FontSize="20" Margin="10 0 0 0" materialDesign:HintAssist.Hint="Serial Number" Text="{Binding Filter,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Delay=500}"></TextBox>
</StackPanel>
</StackPanel>
</Grid>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/SpoolsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/SpoolsView.xaml
index 3663f72f8..f08da88d1 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/SpoolsView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/SpoolsView.xaml
@@ -9,8 +9,14 @@
xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:Tango.MachineStudio.MachineDesigner.Views"
+ xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1280" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
+
+ <UserControl.Resources>
+ <converters:EmptyStringToNullConverter x:Key="EmptyStringToNullConverter" />
+ </UserControl.Resources>
+
<Grid Margin="20">
<DockPanel>
<Grid DockPanel.Dock="Bottom">
@@ -67,10 +73,7 @@
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
- <DataGridTextColumn Header="START OFFSET PULSES" Binding="{Binding StartOffsetPulses}" Width="Auto" />
- <DataGridTextColumn Header="BACKING RATE" Binding="{Binding BackingRate}" Width="Auto" />
- <DataGridTextColumn Header="SEGMENT OFFSET PULSES" Binding="{Binding SegmentOffsetPulses}" Width="Auto" />
- <DataGridTextColumn Header="BOTTOM BACKING RATE" Binding="{Binding BottomBackingRate}" Width="1*" />
+ <DataGridTextColumn Header="LIMIT SWITCH START POINT OFFSET" Binding="{Binding LimitSwitchStartPointOffset,Converter={StaticResource EmptyStringToNullConverter}}" Width="1*" />
</DataGrid.Columns>
</DataGrid>
</Grid>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj
index 2ff9ab0a3..f448932a0 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj
@@ -118,6 +118,12 @@
<Compile Include="Views\RmlView.xaml.cs">
<DependentUpon>RmlView.xaml</DependentUpon>
</Compile>
+ <Compile Include="Views\ThreadParametersView.xaml.cs">
+ <DependentUpon>ThreadParametersView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\SpoolsView.xaml.cs">
+ <DependentUpon>SpoolsView.xaml</DependentUpon>
+ </Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
@@ -223,6 +229,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\ThreadParametersView.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Views\SpoolsView.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\threads.png" />
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs
index 5c55892ba..1ceaf07df 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs
@@ -24,6 +24,7 @@ using Tango.Core.ExtensionMethods;
using Tango.MachineStudio.Common.Authentication;
using Tango.BL.ActionLogs;
using Tango.BL.DTO;
+using Tango.BL.Enumerations;
namespace Tango.MachineStudio.RML.ViewModels
{
@@ -86,6 +87,13 @@ namespace Tango.MachineStudio.RML.ViewModels
set { _fiberSynths = value; RaisePropertyChangedAuto(); }
}
+ private ObservableCollection<SpoolType> _spoolTypes;
+ public ObservableCollection<SpoolType> SpoolTypes
+ {
+ get { return _spoolTypes; }
+ set { _spoolTypes = value; RaisePropertyChangedAuto(); }
+ }
+
private Rml _selectedRML;
public Rml SelectedRML
{
@@ -149,6 +157,14 @@ namespace Tango.MachineStudio.RML.ViewModels
set { _colorConversionViewVM = value; RaisePropertyChangedAuto(); }
}
+ private RmlsSpool _selectedSpool;
+ public RmlsSpool SelectedSpool
+ {
+ get { return _selectedSpool; }
+ set { _selectedSpool = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
+ }
+
+
/// <summary>
/// Gets or sets the manage RML command.
/// </summary>
@@ -191,6 +207,16 @@ namespace Tango.MachineStudio.RML.ViewModels
public RelayCommand ImportRMLFileCommand { get; set; }
+ /// <summary>
+ /// Gets or sets the add spool command.
+ /// </summary>
+ public RelayCommand AddSpoolCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the remove spool command.
+ /// </summary>
+ public RelayCommand RemoveSpoolCommand { get; set; }
+
public MainViewVM(INotificationProvider notificationProvider, IAuthenticationProvider authentication, IActionLogManager actionLogManager)
{
_notification = notificationProvider;
@@ -214,6 +240,9 @@ namespace Tango.MachineStudio.RML.ViewModels
ExportRMLFileCommand = new RelayCommand(ExportRmlFile, () => SelectedRML != null && IsFree);
ImportRMLFileCommand = new RelayCommand(ImportRmlFile, () => IsFree);
+
+ AddSpoolCommand = new RelayCommand(AddNewSpool);
+ RemoveSpoolCommand = new RelayCommand(RemoveSpool, () => SelectedSpool != null);
}
public override void OnApplicationReady()
@@ -254,101 +283,114 @@ namespace Tango.MachineStudio.RML.ViewModels
{
using (_notification.PushTaskItem("Loading RML..."))
{
- IsFree = false;
-
- if (_active_context != null)
+ try
{
- _active_context.Dispose();
- }
-
- _active_context = ObservablesContext.CreateDefault();
+ IsFree = false;
- CCTS = _active_context.Ccts
- .Select(x => new CctModel()
+ if (_active_context != null)
{
- Guid = x.Guid,
- FileName = x.FileName,
+ _active_context.Dispose();
+ }
- }).ToObservableCollection();
+ _active_context = ObservablesContext.CreateDefault();
- CCTS.Where(x => String.IsNullOrWhiteSpace(x.FileName)).ToList().ForEach(x => x.FileName = x.Guid);
+ CCTS = _active_context.Ccts
+ .Select(x => new CctModel()
+ {
+ Guid = x.Guid,
+ FileName = x.FileName,
- LoadRmlProperties();
+ }).ToObservableCollection();
- ActiveRML = await new RmlBuilder(_active_context)
- .Set(guid)
- .WithActiveParametersGroup()
- .WithLiquidFactors()
- .WithCCT()
- .BuildAsync();
+ CCTS.Where(x => String.IsNullOrWhiteSpace(x.FileName)).ToList().ForEach(x => x.FileName = x.Guid);
- if (ActiveRML.Cct != null)
- {
- SelectedCCT = CCTS.SingleOrDefault(x => x.Guid == ActiveRML.Cct.Guid);
- }
+ LoadRmlProperties();
- if (ActiveRML.ProcessParametersTablesGroups.ToList().Count == 0)
- {
- if (!_notification.ShowQuestion("Could not find any process group for the selected RML. Would you like to create one?"))
+ ActiveRML = await new RmlBuilder(_active_context)
+ .Set(guid)
+ .WithActiveParametersGroup()
+ .WithLiquidFactors()
+ .WithCCT()
+ .WithSpools()
+ .BuildAsync();
+
+ if (ActiveRML.Cct != null)
{
- _notification.ShowError("Cannot load an RML with no process group.");
- IsFree = true;
- return;
+ SelectedCCT = CCTS.SingleOrDefault(x => x.Guid == ActiveRML.Cct.Guid);
}
- else
+
+ if (ActiveRML.ProcessParametersTablesGroups.ToList().Count == 0)
{
- ProcessParametersTablesGroup group = new ProcessParametersTablesGroup();
- group.Name = "Active Group";
- group.Active = true;
- group.ProcessParametersTables.Add(new ProcessParametersTable()
+ if (!_notification.ShowQuestion("Could not find any process group for the selected RML. Would you like to create one?"))
{
- Name = "Process Table 1",
- });
+ _notification.ShowError("Cannot load an RML with no process group.");
+ IsFree = true;
+ return;
+ }
+ else
+ {
+ ProcessParametersTablesGroup group = new ProcessParametersTablesGroup();
+ group.Name = "Active Group";
+ group.Active = true;
+ group.ProcessParametersTables.Add(new ProcessParametersTable()
+ {
+ Name = "Process Table 1",
+ });
- group.Rml = ActiveRML;
+ group.Rml = ActiveRML;
- _active_context.ProcessParametersTablesGroups.Add(group);
- _active_context.ProcessParametersTables.Add(group.ProcessParametersTables[0]);
- await _active_context.SaveChangesAsync();
- LoadActiveRML(ActiveRML.Guid);
- return;
+ _active_context.ProcessParametersTablesGroups.Add(group);
+ _active_context.ProcessParametersTables.Add(group.ProcessParametersTables[0]);
+ await _active_context.SaveChangesAsync();
+ LoadActiveRML(ActiveRML.Guid);
+ return;
+ }
}
- }
-
- ActiveProcessParametersGroup = ActiveRML.ProcessParametersTablesGroups.ToList().FirstOrDefault();
- ActiveProcessParametersTableView = CollectionViewSource.GetDefaultView(ActiveProcessParametersGroup.ProcessParametersTables);
- ActiveProcessParametersTableView.SortDescriptions.Add(new SortDescription(nameof(ProcessParametersTable.TableIndex), ListSortDirection.Ascending));
- CalibrationDataViewVM = new CalibrationDataViewVM(_notification);
- LiquidTypesRmls = ActiveRML.LiquidTypesRmls;
+ ActiveProcessParametersGroup = ActiveRML.ProcessParametersTablesGroups.ToList().FirstOrDefault();
+ ActiveProcessParametersTableView = CollectionViewSource.GetDefaultView(ActiveProcessParametersGroup.ProcessParametersTables);
+ ActiveProcessParametersTableView.SortDescriptions.Add(new SortDescription(nameof(ProcessParametersTable.TableIndex), ListSortDirection.Ascending));
- foreach (var liquidTypeRml in LiquidTypesRmls)
- {
- CalibrationDataVM catVM = new CalibrationDataVM(liquidTypeRml.LiquidType);
+ CalibrationDataViewVM = new CalibrationDataViewVM(_notification);
+ LiquidTypesRmls = ActiveRML.LiquidTypesRmls;
- if (liquidTypeRml.DefaultCatData != null)
+ foreach (var liquidTypeRml in LiquidTypesRmls)
{
- catVM.CalibrationPoints = liquidTypeRml.GetCalibrationData().CalibrationPoints.Select(x => new CalibrationDataPointVM(x.X, x.Y)).ToObservableCollection();
- }
+ CalibrationDataVM catVM = new CalibrationDataVM(liquidTypeRml.LiquidType);
- CalibrationDataViewVM.LiquidsCalibrationData.Add(catVM);
- }
+ if (liquidTypeRml.DefaultCatData != null)
+ {
+ catVM.CalibrationPoints = liquidTypeRml.GetCalibrationData().CalibrationPoints.Select(x => new CalibrationDataPointVM(x.X, x.Y)).ToObservableCollection();
+ }
- ColorConversionViewVM = new ColorConversionViewVM(_notification)
- {
- RML = ActiveRML,
- CCT = SelectedCCT,
- LiquidsCalibrationData = CalibrationDataViewVM.LiquidsCalibrationData,
- LiquidTypesRmls = LiquidTypesRmls,
- };
+ CalibrationDataViewVM.LiquidsCalibrationData.Add(catVM);
+ }
- _rmlBeforeSave = RmlDTO.FromObservable(ActiveRML);
+ ColorConversionViewVM = new ColorConversionViewVM(_notification)
+ {
+ RML = ActiveRML,
+ CCT = SelectedCCT,
+ LiquidsCalibrationData = CalibrationDataViewVM.LiquidsCalibrationData,
+ LiquidTypesRmls = LiquidTypesRmls,
+ };
- View.NavigateTo(RmlNavigationView.RmlView);
+ _rmlBeforeSave = RmlDTO.FromObservable(ActiveRML);
- InvalidateRelayCommands();
+ View.NavigateTo(RmlNavigationView.RmlView);
- IsFree = true;
+ InvalidateRelayCommands();
+
+ IsFree = true;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log($"Error loading RML '{ActiveRML.Name}'...");
+ _notification.ShowError($"Error loading the selected thread.\n{ex.FlattenMessage()}");
+ }
+ finally
+ {
+ IsFree = true;
+ }
}
}
@@ -381,6 +423,7 @@ namespace Tango.MachineStudio.RML.ViewModels
LinearMassDensityUnits = _active_context.LinearMassDensityUnits.ToObservableCollection();
FiberShapes = _active_context.FiberShapes.ToObservableCollection();
FiberSynths = _active_context.FiberSynths.ToObservableCollection();
+ SpoolTypes = _active_context.SpoolTypes.ToObservableCollection();
}
private async void AddNewRml()
@@ -410,6 +453,8 @@ namespace Tango.MachineStudio.RML.ViewModels
Rml rml = new Rml();
rml.Name = name;
+ rml.DisplayName = name;
+ rml.QualificationDate = DateTime.UtcNow;
rml.Manufacturer = "Twine";
rml.Code = Rmls.Max(x => x.Code) + 1;
rml.MediaMaterial = Materials.FirstOrDefault();
@@ -457,7 +502,7 @@ namespace Tango.MachineStudio.RML.ViewModels
if (rml_jobs.Count > 0)
{
- _notification.ShowError($"The following jobs must be removed or change thread type before the selected thread can be deleted:\n{String.Join("\n",rml_jobs.Select(x => $"{x.Machine.SerialNumber} => {x.Name}"))}");
+ _notification.ShowError($"The following jobs must be removed or change thread type before the selected thread can be deleted:\n{String.Join("\n", rml_jobs.Select(x => $"{x.Machine.SerialNumber} => {x.Name}"))}");
return;
}
@@ -492,7 +537,7 @@ namespace Tango.MachineStudio.RML.ViewModels
using (var context = ObservablesContext.CreateDefault())
{
- var rml = await new RmlBuilder(context).Set(SelectedRML.Guid).WithActiveParametersGroup().WithLiquidFactors().BuildAsync();
+ var rml = await new RmlBuilder(context).Set(SelectedRML.Guid).WithActiveParametersGroup().WithLiquidFactors().WithSpools().BuildAsync();
Rml cloned = new Rml();
rml.MapPropertiesTo(cloned, MappingFlags.NoReferenceTypes);
@@ -501,6 +546,9 @@ namespace Tango.MachineStudio.RML.ViewModels
cloned.Guid = Guid.NewGuid().ToString();
cloned.ID = 0;
cloned.Name = name;
+ cloned.DisplayName = name;
+ cloned.RmlQualificationLevel = RmlQualifications.Provisional;
+ cloned.QualificationDate = DateTime.UtcNow;
ProcessParametersTablesGroup group = new ProcessParametersTablesGroup();
group.Name = rml.GetActiveProcessGroup().Name;
@@ -526,6 +574,15 @@ namespace Tango.MachineStudio.RML.ViewModels
cloned.LiquidTypesRmls.Add(l);
}
+ foreach (var spool in rml.RmlsSpools)
+ {
+ RmlsSpool s = new RmlsSpool();
+ spool.MapPropertiesTo(s, MappingFlags.ValueTypesOnly);
+ s.RmlGuid = cloned.Guid;
+ s.SpoolTypeGuid = spool.SpoolTypeGuid;
+ cloned.RmlsSpools.Add(s);
+ }
+
context.Rmls.Add(cloned);
await context.SaveChangesAsync();
@@ -674,6 +731,11 @@ namespace Tango.MachineStudio.RML.ViewModels
ActiveRML.LastUpdated = DateTime.UtcNow;
+ if (_rmlBeforeSave.QualificationLevel != ActiveRML.QualificationLevel)
+ {
+ ActiveRML.QualificationDate = DateTime.UtcNow;
+ }
+
if (SelectedCCT != null)
{
if (SelectedCCT.IsNew)
@@ -698,17 +760,19 @@ namespace Tango.MachineStudio.RML.ViewModels
_actionLogManager.InsertLog(BL.Enumerations.ActionLogType.RmlSaved, _authentication.CurrentUser, _rmlBeforeSave.Name, _rmlBeforeSave, rmlAfter, "RML saved using Machine Studio.");
_rmlBeforeSave = rmlAfter;
+
+ LoadActiveRML(ActiveRML.Guid);
}
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error saving RML {ActiveRML.Name}");
- _notification.ShowError($"An error occurred while trying to save the current RML.\n{ex.Message}");
+ _notification.ShowError($"An error occurred while trying to save the current RML.\n{ex.FlattenMessage()}");
+ }
+ finally
+ {
+ IsFree = true;
}
-
- LoadActiveRML(ActiveRML.Guid);
-
- IsFree = true;
}
private void BackToRmls()
@@ -894,5 +958,26 @@ namespace Tango.MachineStudio.RML.ViewModels
}
#endregion
+
+ #region Spools
+
+ private void AddNewSpool()
+ {
+ _active_context.RmlsSpools.Add(new RmlsSpool()
+ {
+ Rml = ActiveRML,
+ });
+ }
+
+ private void RemoveSpool()
+ {
+ if (SelectedSpool != null)
+ {
+ _active_context.RmlsSpools.Remove(SelectedSpool);
+ ActiveRML.RmlsSpools.Remove(SelectedSpool);
+ }
+ }
+
+ #endregion
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/MainView.xaml
index ab5207722..e52ac4ece 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/MainView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/MainView.xaml
@@ -9,7 +9,7 @@
xmlns:local="clr-namespace:Tango.MachineStudio.RML.Views"
mc:Ignorable="d"
d:DesignHeight="1080" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
- <Grid>
+ <Grid IsEnabled="{Binding IsFree}">
<controls:NavigationControl x:Name="navigationControl" TransitionType="Slide">
<local:RmlsView />
<local:RmlView/>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ProcessParametersView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ProcessParametersView.xaml
index cae614aeb..03bf65522 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ProcessParametersView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ProcessParametersView.xaml
@@ -32,7 +32,7 @@
<DropShadowEffect Opacity="0.4" />
</Border.Effect>
<Grid>
- <TextBlock HorizontalAlignment="Left" Margin="20 0 0 0" FontSize="16">ACTIVE PROCESS GROUP</TextBlock>
+ <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Margin="20 0 0 0" FontSize="16">ACTIVE PROCESS GROUP</TextBlock>
<Button ToolTip="Add new table" Style="{StaticResource MaterialDesignFlatButton}" Height="Auto" Width="30" HorizontalAlignment="Right" Padding="0" Command="{Binding AddProcessParametersTableCommand}">
<materialDesign:PackIcon Kind="Plus" Foreground="#0AC30A" Width="24" Height="24" />
</Button>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml
index e34854046..e967c7d83 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml
@@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:global="clr-namespace:Tango.MachineStudio.RML"
+ xmlns:enumerations="clr-namespace:Tango.BL.Enumerations;assembly=Tango.BL"
xmlns:observables="clr-namespace:Tango.BL.Entities;assembly=Tango.BL"
xmlns:shapes="clr-namespace:Tango.SharedUI.Shapes;assembly=Tango.SharedUI"
xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
@@ -19,6 +20,7 @@
<UserControl.Resources>
<converters:ColorToIntegerConverter x:Key="ColorToIntegerConverter"></converters:ColorToIntegerConverter>
+ <converters:EnumToItemsSourceConverter x:Key="EnumToItemsSourceConverter"/>
</UserControl.Resources>
<Grid Margin="20">
@@ -58,6 +60,15 @@
<TextBlock Text="Name:" ></TextBlock>
<TextBox Text="{Binding ActiveRML.Name,UpdateSourceTrigger=PropertyChanged}"></TextBox>
+ <TextBlock Text="Display Name:" ></TextBlock>
+ <TextBox Text="{Binding ActiveRML.DisplayName,UpdateSourceTrigger=PropertyChanged}"></TextBox>
+
+ <TextBlock Text="Head Type:" ></TextBlock>
+ <ComboBox ItemsSource="{Binding Source={x:Type enumerations:HeadTypes},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValue="{Binding ActiveRML.RmlHeadType}" SelectedValuePath="Value" DisplayMemberPath="DisplayName"></ComboBox>
+
+ <TextBlock Text="Qualification Level:" ></TextBlock>
+ <ComboBox ItemsSource="{Binding Source={x:Type enumerations:RmlQualifications},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValue="{Binding ActiveRML.RmlQualificationLevel}" SelectedValuePath="Value" DisplayMemberPath="DisplayName"></ComboBox>
+
<TextBlock Text="Manufacturer:" ></TextBlock>
<TextBox Text="{Binding ActiveRML.Manufacturer}"></TextBox>
@@ -138,9 +149,12 @@
<Setter Property="Padding" Value="20,2"></Setter>
</Style>
</TabControl.Resources>
- <TabItem Header="PROCESS PARAMETERS" Margin="-100 0 0 0 ">
+ <TabItem Header="PROCESS PARAMETERS" Margin="-100 0 0 0">
<local:ProcessParametersView x:Name="processParametersView" WidthLilquidFactors="{Binding ElementName=calibrationDataView,Path=ActualWidth}"/>
</TabItem>
+ <TabItem Header="THREAD PARAMETERS" Margin="-100 0 0 0">
+ <local:ThreadParametersView/>
+ </TabItem>
<TabItem Header="COLOR CONVERSION" Margin="-100 0 0 0 ">
<Grid>
<Grid.ColumnDefinitions>
@@ -148,18 +162,18 @@
<ColumnDefinition Width="260"></ColumnDefinition>
</Grid.ColumnDefinitions>
<DockPanel>
- <Border DockPanel.Dock="Top" Background="{StaticResource TransparentBackgroundBrush200}" Margin="20 0" Padding="5" CornerRadius="5">
+ <Border DockPanel.Dock="Top" Background="{StaticResource TransparentBackgroundBrush200}" Margin="20 0" Padding="7" CornerRadius="5">
<Border.Effect>
<DropShadowEffect Opacity="0.4" />
</Border.Effect>
<Grid>
- <TextBlock HorizontalAlignment="Left" Margin="20 0 0 0" FontSize="16">COLOR CONVERSION</TextBlock>
+ <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Margin="20 0 0 0" FontSize="16">COLOR CONVERSION</TextBlock>
</Grid>
</Border>
<local:ColorConversionView x:Name="colorConversionView" Margin="0 0 0 0" Grid.Column="0" DataContext="{Binding ColorConversionViewVM}"/>
</DockPanel>
<DockPanel Grid.Column="1">
- <Border DockPanel.Dock="Top" Background="{StaticResource TransparentBackgroundBrush200}" Margin="16 0" Padding="5" CornerRadius="5">
+ <Border DockPanel.Dock="Top" Background="{StaticResource TransparentBackgroundBrush200}" Margin="16 0" Padding="7" CornerRadius="5">
<Border.Effect>
<DropShadowEffect Opacity="0.4" />
</Border.Effect>
@@ -200,6 +214,9 @@
</DockPanel>
</Grid>
</TabItem>
+ <TabItem Header="SPOOLS" Margin="-100 0 0 0">
+ <local:SpoolsView/>
+ </TabItem>
</TabControl>
</Grid>
<Grid Grid.Row="1">
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/SpoolsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/SpoolsView.xaml
new file mode 100644
index 000000000..6eae05c76
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/SpoolsView.xaml
@@ -0,0 +1,85 @@
+<UserControl x:Class="Tango.MachineStudio.RML.Views.SpoolsView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:vm="clr-namespace:Tango.MachineStudio.RML.ViewModels"
+ xmlns:global="clr-namespace:Tango.MachineStudio.RML"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:local="clr-namespace:Tango.MachineStudio.RML.Views"
+ xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
+
+ <UserControl.Resources>
+ <converters:EmptyStringToNullConverter x:Key="EmptyStringToNullConverter" />
+ </UserControl.Resources>
+
+ <Grid>
+ <DockPanel>
+ <Border DockPanel.Dock="Top" Background="{StaticResource TransparentBackgroundBrush200}" Margin="20 0" Padding="5" CornerRadius="5">
+ <Border.Effect>
+ <DropShadowEffect Opacity="0.4" />
+ </Border.Effect>
+ <Grid>
+ <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Margin="20 0 0 0" FontSize="16" Padding="2">SPOOLS</TextBlock>
+ </Grid>
+ </Border>
+
+ <Grid>
+ <DockPanel Grid.Column="1" Margin="25">
+ <Grid DockPanel.Dock="Bottom">
+ <StackPanel VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 0 0 0">
+ <Button Margin="0 0 10 0" MinWidth="160" Height="50" Background="{StaticResource RedBrush300}" BorderBrush="{StaticResource RedBrush300}" Command="{Binding RemoveSpoolCommand}">
+ <StackPanel Orientation="Horizontal">
+ <materialDesign:PackIcon Kind="Delete" Width="20" Height="20" />
+ <TextBlock Margin="5 0 0 0" FontSize="16">DELETE</TextBlock>
+ </StackPanel>
+ </Button>
+ <Button Margin="0 0 0 0" MinWidth="160" Height="50" Background="{StaticResource GreenBrush300}" BorderBrush="{StaticResource GreenBrush300}" Command="{Binding AddSpoolCommand}">
+ <StackPanel Orientation="Horizontal">
+ <materialDesign:PackIcon Kind="Plus" Width="20" Height="20" />
+ <TextBlock Margin="5 0 0 0" FontSize="16">NEW SPOOL</TextBlock>
+ </StackPanel>
+ </Button>
+ </StackPanel>
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
+
+ </StackPanel>
+ </Grid>
+ <Grid>
+ <DataGrid Margin="0 0 0 10" SelectionUnit="FullRow" BorderBrush="{StaticResource borderBrush }" BorderThickness="1" Background="{StaticResource TransparentBackgroundBrush}" AlternatingRowBackground="{StaticResource Transparent200}" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{Binding ActiveRML.RmlsSpools}" SelectedItem="{Binding SelectedSpool}">
+ <DataGrid.CellStyle>
+ <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
+ <Setter Property="VerticalContentAlignment" Value="Center"></Setter>
+ </Style>
+ </DataGrid.CellStyle>
+ <DataGrid.Columns>
+ <DataGridComboBoxColumn Header="SPOOL TYPE" SelectedItemBinding="{Binding SpoolType}" DisplayMemberPath="Name" Width="Auto">
+ <DataGridComboBoxColumn.ElementStyle>
+ <Style TargetType="ComboBox">
+ <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid},Path=DataContext.SpoolTypes}"/>
+ </Style>
+ </DataGridComboBoxColumn.ElementStyle>
+ <DataGridComboBoxColumn.EditingElementStyle>
+ <Style TargetType="ComboBox">
+ <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid},Path=DataContext.SpoolTypes}"/>
+ </Style>
+ </DataGridComboBoxColumn.EditingElementStyle>
+ </DataGridComboBoxColumn>
+ <DataGridTextColumn Header="ROTATIONS PER PASSAGE" Binding="{Binding RotationsPerPassage,Converter={StaticResource EmptyStringToNullConverter}}" Width="Auto" />
+ <DataGridTextColumn Header="MAX LENGTH" Binding="{Binding Length,Converter={StaticResource EmptyStringToNullConverter}}" Width="Auto" />
+ <DataGridTextColumn Header="BACKING RATE" Binding="{Binding BackingRate,Converter={StaticResource EmptyStringToNullConverter}}" Width="Auto" />
+ <DataGridTextColumn Header="BOTTOM BACKING RATE" Binding="{Binding BottomBackingRate,Converter={StaticResource EmptyStringToNullConverter}}" Width="Auto" />
+ </DataGrid.Columns>
+ </DataGrid>
+ </Grid>
+ </DockPanel>
+ </Grid>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/SpoolsView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/SpoolsView.xaml.cs
new file mode 100644
index 000000000..6e363681c
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/SpoolsView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.RML.Views
+{
+ /// <summary>
+ /// Interaction logic for SpoolsView.xaml
+ /// </summary>
+ public partial class SpoolsView : UserControl
+ {
+ public SpoolsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ThreadParametersView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ThreadParametersView.xaml
new file mode 100644
index 000000000..7f1ca2262
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ThreadParametersView.xaml
@@ -0,0 +1,98 @@
+<UserControl x:Class="Tango.MachineStudio.RML.Views.ThreadParametersView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:vm="clr-namespace:Tango.MachineStudio.RML.ViewModels"
+ xmlns:global="clr-namespace:Tango.MachineStudio.RML"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:local="clr-namespace:Tango.MachineStudio.RML.Views"
+ xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
+
+ <UserControl.Resources>
+ <converters:EmptyStringToNullConverter x:Key="EmptyStringToNullConverter" />
+ </UserControl.Resources>
+
+ <Grid>
+ <DockPanel>
+ <Border DockPanel.Dock="Top" Background="{StaticResource TransparentBackgroundBrush200}" Margin="20 0" Padding="5" CornerRadius="5">
+ <Border.Effect>
+ <DropShadowEffect Opacity="0.4" />
+ </Border.Effect>
+ <Grid>
+ <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Margin="20 0 0 0" FontSize="16" Padding="2">THREAD PARAMETERS</TextBlock>
+ </Grid>
+ </Border>
+
+ <Grid>
+ <StackPanel Orientation="Horizontal">
+ <DockPanel Grid.Column="1" Margin="25" HorizontalAlignment="Left" Width="400">
+ <materialDesign:Card>
+ <StackPanel>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" Margin="20 10 0 10" FontSize="16">FEEDER</TextBlock>
+ <controls:TableGrid RowHeight="25" Margin="20 0">
+ <TextBlock Text="Feeder P:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.FeederP,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+
+ <TextBlock Text="Feeder I:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.FeederI,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+
+ <TextBlock Text="Feeder D:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.FeederD,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+ </controls:TableGrid>
+ </DockPanel>
+
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" Margin="20 10 0 10" FontSize="16">PULLER</TextBlock>
+ <controls:TableGrid RowHeight="25" Margin="20 0">
+ <TextBlock Text="Puller P:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.PullerP,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+
+ <TextBlock Text="Puller I:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.PullerI,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+
+ <TextBlock Text="Puller D:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.PullerD,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+ </controls:TableGrid>
+ </DockPanel>
+
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" Margin="20 10 0 10" FontSize="16">WINDER</TextBlock>
+ <controls:TableGrid RowHeight="25" Margin="20 0">
+ <TextBlock Text="Winder P:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.WinderP,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+
+ <TextBlock Text="Winder I:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.WinderI,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+
+ <TextBlock Text="Winder D:" ></TextBlock>
+ <mahapps:NumericUpDown Value="{Binding ActiveRML.WinderD,Mode=TwoWay}" Minimum="-100000" Maximum="1000000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="False" HorizontalContentAlignment="Left"></mahapps:NumericUpDown>
+ </controls:TableGrid>
+ </DockPanel>
+ </StackPanel>
+ </materialDesign:Card>
+ </DockPanel>
+
+ <DockPanel Grid.Column="1" Margin="25" HorizontalAlignment="Left" Width="400">
+ <materialDesign:Card>
+ <StackPanel>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" Margin="20 10 0 10" FontSize="16">ROCKERS</TextBlock>
+ <controls:TableGrid RowHeight="25" Margin="20 0">
+ <TextBlock Text="Bypass Rockers:" ></TextBlock>
+ <ToggleButton IsChecked="{Binding ActiveRML.BypassRockers,Mode=TwoWay}" HorizontalAlignment="Right" ></ToggleButton>
+ </controls:TableGrid>
+ </DockPanel>
+ </StackPanel>
+ </materialDesign:Card>
+ </DockPanel>
+ </StackPanel>
+ </Grid>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ThreadParametersView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ThreadParametersView.xaml.cs
new file mode 100644
index 000000000..aa63e48fb
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/ThreadParametersView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.RML.Views
+{
+ /// <summary>
+ /// Interaction logic for SpoolsView.xaml
+ /// </summary>
+ public partial class ThreadParametersView : UserControl
+ {
+ public ThreadParametersView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/App.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/App.config
index ed4582d5b..75b63289d 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/App.config
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/App.config
@@ -22,7 +22,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
@@ -30,27 +30,27 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
+ <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
@@ -74,7 +74,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-3.19.8.16603" newVersion="3.19.8.16603" />
+ <bindingRedirect oldVersion="0.0.0.0-5.0.5.0" newVersion="5.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
@@ -92,6 +92,10 @@
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Z.EntityFramework.Extensions" publicKeyToken="59b66d028979105b" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.50.0" newVersion="4.0.50.0" />
+ </dependentAssembly>
</assemblyBinding>
</runtime>
</configuration> \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/CollectionConverter .cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/CollectionConverter .cs
new file mode 100644
index 000000000..4cea7f69f
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/CollectionConverter .cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class CollectionConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if(value != null && value is System.Collections.IEnumerable)
+ {
+ var colection = value as System.Collections.IEnumerable;
+ var text = new StringBuilder();
+ foreach(var val in colection)
+ {
+ string visibleText = val.ToString();
+ if (val is bool)
+ {
+ visibleText = (bool)val== true ? "Yes" : "No";
+ }
+ text.Append(visibleText);
+ text.Append("/");
+ }
+ string str_text = text.ToString();
+ if(str_text.Length > 1)
+ {
+ str_text = str_text.Remove(str_text.Length - 1);
+ }
+ return str_text;
+ }
+ return "";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/DateTimeToStringFormatConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/DateTimeToStringFormatConverter.cs
new file mode 100644
index 000000000..6b5154ce3
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/DateTimeToStringFormatConverter.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class DateTimeToStringFormatConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value != null)
+ {
+ return ((TimeSpan)value).ToString(@"hh\:mm\:ss");
+ }
+ else
+ {
+ return TimeSpan.FromSeconds(0).ToString(@"hh\:mm\:ss");
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/JobLengthConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/JobLengthConverter.cs
new file mode 100644
index 000000000..b730d7881
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/JobLengthConverter.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class JobLengthConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ try
+ {
+ if (values != null && values.Count() == 3)
+ {
+ double length = (double)values[0];
+ double endPoint = (double)values[1];
+ double width = (double)values[2];
+ return Math.Round((endPoint / length) * width, MidpointRounding.AwayFromZero);
+ }
+ }
+ catch { }
+
+ return 0d;
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/LiquidTypeToColorConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/LiquidTypeToColorConverter.cs
new file mode 100644
index 000000000..b36bf608e
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/LiquidTypeToColorConverter.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using System.Windows.Media;
+using Tango.BL;
+using Tango.BL.Enumerations;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class LiquidTypeToColorConverter : IValueConverter
+ {
+ private static Dictionary<LiquidTypes,Color> liquidTypes;
+
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (liquidTypes == null)
+ {
+ liquidTypes = new Dictionary<LiquidTypes, Color>();
+
+ foreach (var type in ObservablesStaticCollections.Instance.LiquidTypes.ToList())
+ {
+ liquidTypes.Add(type.Type, type.LiquidTypeColor);
+ }
+ }
+
+ if (value != null)
+ {
+ return liquidTypes[(LiquidTypes)value];
+ }
+
+ return value;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/MidTankLevelToElementHeightConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/MidTankLevelToElementHeightConverter.cs
new file mode 100644
index 000000000..de002046e
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/MidTankLevelToElementHeightConverter.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Globalization;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class MidTankLevelToElementHeightConverter : IMultiValueConverter
+ {
+ public const double MAX_QUANTITY = 130000000;
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ try
+ {
+ double parentActualHeight;
+ Double.TryParse(values[0].ToString(), out parentActualHeight);
+ double quantity;
+ Double.TryParse(values[1].ToString(), out quantity);
+
+ double midTankLevel = (double)Math.Min(quantity, MAX_QUANTITY);
+ double delta = ((midTankLevel / MAX_QUANTITY) * parentActualHeight);
+ if (quantity > 0 && midTankLevel < (MAX_QUANTITY/10))// if quantity < 10|% set 2 pixel
+ delta = 2.0;
+ var test = delta;
+ return parentActualHeight - delta;
+ }
+ catch
+ {
+ return 0d;
+ }
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/NanoLiterToLiterFormatConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/NanoLiterToLiterFormatConverter.cs
new file mode 100644
index 000000000..23d7564e8
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/NanoLiterToLiterFormatConverter.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class NanoLiterToLiterFormatConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ try
+ {
+ double val =(double) ((int)value) / 1000000000;
+ return val.ToString("N2", CultureInfo.InvariantCulture);
+ }
+ catch{ }
+
+ return "";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToBoolYesNoNullConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToBoolYesNoNullConverter.cs
new file mode 100644
index 000000000..f7633a7d0
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToBoolYesNoNullConverter.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class StringToBoolYesNoNullConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if(value is bool)
+ {
+ return (bool)value ? "Yes" : "No";
+ }
+ return "Null";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ //throw new NotImplementedException();
+ if (value is ComboBoxItem)
+ {
+ string str_val = ((ComboBoxItem)value).Content.ToString();
+ if (str_val.ToUpper() == "NO")
+ return false;
+ if (str_val.ToUpper() == "YES")
+ return true;
+ }
+ return null;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToFirstLetterConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToFirstLetterConverter.cs
new file mode 100644
index 000000000..a1c9561b9
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToFirstLetterConverter.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class StringToFirstLetterConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value != null && value.ToString().Length > 1)
+ {
+ return value.ToString().First().ToString();
+ }
+ else
+ {
+ return value;
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs
index 8e5642e3d..83897ca16 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs
@@ -1,45 +1,39 @@
-
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using Tango.BL;
using Tango.BL.Entities;
-using Tango.Core.ExtensionMethods;
namespace Tango.MachineStudio.Statistics.Models
{
- public class JobRunModel : JobRun
+ public class JobRunModel
{
- private static Dictionary<String, Machine> _machines = new Dictionary<string, Machine>();
+ public JobRun JobRun { get; set; }
- public JobRunModel()
- {
+ public Machine Machine { get; set; }
- }
+ public User User { get; set; }
- public JobRunModel(JobRun run)
- {
- run.MapPropertiesTo(this, MappingFlags.NoReferenceTypes);
- }
+ public TimeSpan? UploadDuration { get; set; }
+
+ public TimeSpan? HeatingDuration { get; set; }
- public Task LoadMachine(ObservablesContext context)
+ public RmlModel Rml { get; set; }
+
+ public void Init()
{
- return Task.Factory.StartNew(() =>
+ if (JobRun.HeatingStartDate != null)
{
- if (!_machines.ContainsKey(MachineGuid))
- {
- Machine = context.Machines.SingleOrDefault(x => x.Guid == MachineGuid);
- _machines.Add(MachineGuid, Machine);
- }
- else
- {
- Machine = _machines[MachineGuid];
- }
- });
- }
+ UploadDuration = JobRun.HeatingStartDate - JobRun.StartDate;
+ }
- public Machine Machine { get; set; }
+ if (JobRun.ActualStartDate != null && JobRun.HeatingStartDate != null)
+ {
+ HeatingDuration = JobRun.ActualStartDate - JobRun.HeatingStartDate;
+ }
+
+
+ }
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunStatisticsModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunStatisticsModel.cs
new file mode 100644
index 000000000..98b719cae
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunStatisticsModel.cs
@@ -0,0 +1,45 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.Entities;
+using Tango.Core.ExtensionMethods;
+
+namespace Tango.MachineStudio.Statistics.Models
+{
+ public class JobRunStatisticsModel : JobRun
+ {
+ private static Dictionary<String, Machine> _machines = new Dictionary<string, Machine>();
+
+ public JobRunStatisticsModel()
+ {
+
+ }
+
+ public JobRunStatisticsModel(JobRun run)
+ {
+ run.MapPropertiesTo(this, MappingFlags.NoReferenceTypes);
+ }
+
+ public Task LoadMachine(ObservablesContext context)
+ {
+ return Task.Factory.StartNew(() =>
+ {
+ if (!_machines.ContainsKey(MachineGuid))
+ {
+ Machine = context.Machines.SingleOrDefault(x => x.Guid == MachineGuid);
+ _machines.Add(MachineGuid, Machine);
+ }
+ else
+ {
+ Machine = _machines[MachineGuid];
+ }
+ });
+ }
+
+ public Machine Machine { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/RmlModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/RmlModel.cs
new file mode 100644
index 000000000..789779e42
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/RmlModel.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.MachineStudio.Statistics.Models
+{
+ public class RmlModel
+ {
+ public string Guid { get; set; }
+
+ public string Name { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/StatisticsValueCollection.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/StatisticsValueCollection.cs
new file mode 100644
index 000000000..ef5527406
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/StatisticsValueCollection.cs
@@ -0,0 +1,312 @@
+using LiveCharts;
+using LiveCharts.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using System.Windows.Media;
+using Tango.BL.Enumerations;
+using Tango.BL.ValueObjects;
+using Tango.Core;
+using System.Windows.Media;
+using System.Windows;
+
+namespace Tango.MachineStudio.Statistics.Models
+{
+ public class StatisticsValue
+ {
+ public string Name { get; set; }
+
+ public object Value { get; set; }
+
+ public string Unit { get; set; }
+ }
+ public class MoreValue
+ {
+ public string Text { get; set; }
+ }
+
+ public class StatisticsValueCollection: ExtendedObject
+ {
+ private List<Color> _pieColors;
+
+ #region Properties
+
+ private ObservableCollection<StatisticsValue> _statisticsCollection;
+
+ /// <summary>
+ /// Gets or sets the statistics collection of StatisticsValue object.
+ /// </summary>
+ public ObservableCollection<StatisticsValue> StatisticsCollection
+ {
+ get { return _statisticsCollection; }
+ set { _statisticsCollection = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private List<StatisticsValue> _threadConsumptionPerThread;
+ /// <summary>
+ /// Gets or sets the thread consumption per thread list.
+ /// </summary>
+ public List<StatisticsValue> ThreadConsumptionPerThread
+ {
+ get { return _threadConsumptionPerThread; }
+ set { _threadConsumptionPerThread = value; RaisePropertyChangedAuto(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the thread consumption per thread collection.
+ /// </summary>
+ public CompositeCollection ThreadConsumptionPerThreadCollection { get; set; }
+
+ private LabeledSeriesCollection _pieJobSource;
+
+ /// <summary>
+ /// Gets or sets the pie job source.
+ /// </summary>
+ public LabeledSeriesCollection PieJobSource
+ {
+ get { return _pieJobSource; }
+ set { _pieJobSource = value; RaisePropertyChangedAuto(); }
+ }
+
+ private LabeledSeriesCollection _pieJobRunStatus;
+
+ /// <summary>
+ /// Gets or sets the pie job run status.
+ /// </summary>
+ public LabeledSeriesCollection PieJobRunStatus
+ {
+ get { return _pieJobRunStatus; }
+ set { _pieJobRunStatus = value; RaisePropertyChangedAuto(); }
+ }
+
+ private LabeledSeriesCollection _pieGradientSolid;
+
+ /// <summary>
+ /// Gets or sets the pie gradient solid.
+ /// </summary>
+ public LabeledSeriesCollection PieGradientSolid
+ {
+ get { return _pieGradientSolid; }
+ set { _pieGradientSolid = value; RaisePropertyChangedAuto(); }
+ }
+
+ private List<JobRunLiquidQuantity> _liquidQuantities;
+
+ /// <summary>
+ /// Gets or sets the liquid quantities.
+ /// </summary>
+ public List<JobRunLiquidQuantity> LiquidQuantities
+ {
+ get
+ {
+ if (_liquidQuantities == null)
+ {
+ _liquidQuantities = new List<JobRunLiquidQuantity>();
+ }
+ return _liquidQuantities;
+ }
+ set
+ { _liquidQuantities = value; RaisePropertyChangedAuto(); }
+ }
+
+ private int _totalLiquidQuantities;
+
+ /// <summary>
+ /// Gets or sets the total liquid quantities.
+ /// </summary>
+ public int TotalLiquidQuantities
+ {
+ get { return _totalLiquidQuantities; }
+ set { _totalLiquidQuantities = value; RaisePropertyChangedAuto(); }
+ }
+
+ #endregion
+
+ public StatisticsValueCollection()
+ {
+ StatisticsCollection = new ObservableCollection<StatisticsValue>();
+ ThreadConsumptionPerThread = new List<StatisticsValue>();
+ ThreadConsumptionPerThreadCollection = new CompositeCollection();
+
+ _pieColors = new List<Color>();
+ _pieColors.Add(((SolidColorBrush)Application.Current.Resources["RedBrush500"]).Color);
+ _pieColors.Add(((SolidColorBrush)Application.Current.Resources["OrangeBrush"]).Color);
+ _pieColors.Add(((SolidColorBrush)Application.Current.Resources["GreenBrush"]).Color);
+ _pieColors.Add(((SolidColorBrush)Application.Current.Resources["BlueBrush100"]).Color);
+ _pieColors.Add(Colors.Yellow);
+
+
+ PieJobSource = new LabeledSeriesCollection()
+ {
+ Title = "PPC/MS",
+ SeriesColors = _pieColors,
+ };
+ PieJobRunStatus = new LabeledSeriesCollection()
+ {
+ Title = "Failed/Aborted/Completed",
+ SeriesColors = _pieColors,
+ };
+ PieGradientSolid = new LabeledSeriesCollection()
+ {
+ Title = "Gradient/Solid",
+ SeriesColors = _pieColors,
+ };
+ }
+
+ /// <summary>
+ /// Cleans all values.
+ /// </summary>
+ public void Clean()
+ {
+ StatisticsCollection.Clear();
+ ThreadConsumptionPerThreadCollection.Clear();
+ ThreadConsumptionPerThread.Clear();
+ PieJobSource.SeriesCollection.Clear();
+ PieJobRunStatus.SeriesCollection.Clear();
+ PieGradientSolid.SeriesCollection.Clear();
+ }
+
+ /// <summary>
+ /// Adds the statistics value.
+ /// </summary>
+ public void AddStatisticsValue(string name, object value, string unit)
+ {
+ StatisticsCollection.Add(new StatisticsValue() { Name = name, Value = value, Unit = unit });
+ RaisePropertyChanged("StatisticsCollection");
+ }
+
+ /// <summary>
+ /// Creates the thread consumption per thread.
+ /// </summary>
+ public void CreateThreadConsumptionPerThread(List<StatisticsValue> threads)
+ {
+ ThreadConsumptionPerThreadCollection.Add(new CollectionContainer() { Collection = threads.Take(threads.Count() > 2 ? 2 : threads.Count()) });
+ if (threads.Count() > 2)
+ {
+ ThreadConsumptionPerThreadCollection.Add(new CollectionContainer() { Collection = new List<MoreValue>() { new MoreValue() { Text = "More threads ..." } } });
+ ThreadConsumptionPerThread = threads.Skip(2).ToList();
+ }
+
+ RaisePropertyChanged("ThreadConsumptionPerThreadCollection");
+ }
+
+ #region GeneratePieChart
+ Func<ChartPoint, string> labelPoint = chartPoint =>
+ string.Format("{0} ({1:P})", chartPoint.Y, chartPoint.Participation);
+
+ public void GeneratePieJobSource(int PPCCount, int MSCount)
+ {
+ var series = new PieSeries()
+ {
+ Title = "PPC",
+ Values = new ChartValues<int>() { PPCCount },
+ Fill = new SolidColorBrush(_pieColors[4]),
+ DataLabels = true,
+ ToolTip = "",
+ LabelPoint = labelPoint
+
+ };
+
+ PieJobSource.SeriesCollection.Add(series);
+
+ series = new PieSeries()
+ {
+ Title = "MS",
+ Values = new ChartValues<int>() { MSCount },
+ Fill = new SolidColorBrush(_pieColors[3]),
+ DataLabels = true,
+ ToolTip = "",
+ LabelPoint = labelPoint
+ };
+ PieJobSource.SeriesCollection.Add(series);
+ RaisePropertyChanged("PieJobSource");
+ }
+
+ public void GeneratePieJobRunStatus(int failedCount, int abortedCount, int completedCount)
+ {
+ var series = new PieSeries()
+ {
+ Title = "Failed",
+ Values = new ChartValues<int>() { failedCount },
+ Fill = new SolidColorBrush(_pieColors[0]),
+ DataLabels = true,
+ ToolTip = "",
+ LabelPoint = labelPoint
+ };
+
+ PieJobRunStatus.SeriesCollection.Add(series);
+
+ series = new PieSeries()
+ {
+ Title = "Aborted",
+ Values = new ChartValues<int>() { abortedCount },
+ Fill = new SolidColorBrush(_pieColors[1]),
+ DataLabels = true,
+ ToolTip = "",
+ LabelPoint = labelPoint,
+
+ };
+ PieJobRunStatus.SeriesCollection.Add(series);
+
+ series = new PieSeries()
+ {
+ Title = "Completed",
+ Values = new ChartValues<int>() { completedCount },
+ Fill = new SolidColorBrush(_pieColors[2]),
+ DataLabels = true,
+ ToolTip = "",
+ LabelPoint = labelPoint
+ };
+ PieJobRunStatus.SeriesCollection.Add(series);
+
+ RaisePropertyChanged("PieJobRunStatus");
+ }
+
+ public void GeneratePieGradientSolid(int gradientCount, int solidCount)
+ {
+ var series = new PieSeries()
+ {
+ Title = "Solid",
+ Values = new ChartValues<int>() { solidCount },
+ Fill = new SolidColorBrush(_pieColors[4]),
+ DataLabels = true,
+ ToolTip = "",
+ LabelPoint = labelPoint
+ };
+ PieGradientSolid.SeriesCollection.Add(series);
+
+ series = new PieSeries()
+ {
+ Title = "Gradient",
+ Values = new ChartValues<int>() { gradientCount },
+ Fill = new SolidColorBrush(_pieColors[3]),
+ DataLabels = true,
+ ToolTip = "",
+ LabelPoint = labelPoint
+
+ };
+
+ PieGradientSolid.SeriesCollection.Add(series);
+
+
+ RaisePropertyChanged("PieGradientSolid");
+ }
+ #endregion
+
+ /// <summary>
+ /// Generates the statistics liquid quantity and TotalLiquidQuantities.
+ /// </summary>
+ public void GenerateStatisticsLiquidQuantity(List<JobRunLiquidQuantity> liquidQuantities)
+ {
+ LiquidQuantities = liquidQuantities;
+ TotalLiquidQuantities = liquidQuantities.Sum(x => x.Quantity);
+ }
+
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj
index 36c371165..adac4bb9f 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj
@@ -38,6 +38,9 @@
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
</Reference>
+ <Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
<Reference Include="LiveCharts, Version=0.9.7.0, Culture=neutral, PublicKeyToken=0bc1f845d1ebb8df, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\LiveCharts.0.9.7\lib\net45\LiveCharts.dll</HintPath>
</Reference>
@@ -73,14 +76,33 @@
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Converters\CollectionConverter .cs" />
+ <Compile Include="Converters\DateTimeToStringFormatConverter.cs" />
+ <Compile Include="Converters\JobLengthConverter.cs" />
+ <Compile Include="Converters\LiquidTypeToColorConverter.cs" />
+ <Compile Include="Converters\MidTankLevelToElementHeightConverter.cs" />
+ <Compile Include="Converters\NanoLiterToLiterFormatConverter.cs" />
+ <Compile Include="Converters\StringToBoolYesNoNullConverter.cs" />
+ <Compile Include="Converters\StringToFirstLetterConverter.cs" />
<Compile Include="Models\JobRunModel.cs" />
+ <Compile Include="Models\JobRunStatisticsModel.cs" />
<Compile Include="Models\LabeledSeriesCollection.cs" />
+ <Compile Include="Models\RmlModel.cs" />
+ <Compile Include="Models\StatisticsValueCollection.cs" />
<Compile Include="Tooltips\PieChartTooltipControl.xaml.cs">
<DependentUpon>PieChartTooltipControl.xaml</DependentUpon>
</Compile>
<Compile Include="StatisticsModule.cs" />
<Compile Include="ViewModelLocator.cs" />
+ <Compile Include="ViewModels\ChartsViewVM.cs" />
+ <Compile Include="ViewModels\JobRunsViewVM.cs" />
<Compile Include="ViewModels\MainViewVM.cs" />
+ <Compile Include="Views\ChartsView.xaml.cs">
+ <DependentUpon>ChartsView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\JobRunsView.xaml.cs">
+ <DependentUpon>JobRunsView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Views\MainView.xaml.cs">
<DependentUpon>MainView.xaml</DependentUpon>
</Compile>
@@ -95,6 +117,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\ChartsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\JobRunsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Views\MainView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -129,6 +159,10 @@
<Resource Include="Images\statistics.png" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj">
+ <Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project>
+ <Name>Tango.AutoComplete</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\..\Tango.BL\Tango.BL.csproj">
<Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project>
<Name>Tango.BL</Name>
@@ -141,6 +175,10 @@
<Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project>
<Name>Tango.Logging</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.PMR\Tango.PMR.csproj">
+ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project>
+ <Name>Tango.PMR</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\..\Tango.Serialization\Tango.Serialization.csproj">
<Project>{22f87980-e990-4686-be81-be63d562c4d5}</Project>
<Name>Tango.Serialization</Name>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs
new file mode 100644
index 000000000..38c1cc24a
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs
@@ -0,0 +1,413 @@
+using LiveCharts;
+using LiveCharts.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Media;
+using Tango.BL.Enumerations;
+using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Statistics.Models;
+using Tango.BL.Entities;
+using Tango.SharedUI;
+using Tango.BL;
+using Tango.MachineStudio.Common.Notifications;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+
+namespace Tango.MachineStudio.Statistics.ViewModels
+{
+ public class ChartsViewVM : ViewModel
+ {
+ private INotificationProvider _notification;
+ //private ObservablesContext _context;
+ private List<JobRunStatisticsModel> _job_runs;
+ private bool _loaded;
+
+ #region Properties
+ private LabeledSeriesCollection _timelineJobStatusSeries;
+ public LabeledSeriesCollection TimelineJobStatusSeries
+ {
+ get { return _timelineJobStatusSeries; }
+ set { _timelineJobStatusSeries = value; RaisePropertyChangedAuto(); }
+ }
+
+ private LabeledSeriesCollection _pieJobFailedReasons;
+ public LabeledSeriesCollection PieJobFailedReasons
+ {
+ get { return _pieJobFailedReasons; }
+ set { _pieJobFailedReasons = value; RaisePropertyChangedAuto(); }
+ }
+
+ private LabeledSeriesCollection _printPerWeekSeries;
+ public LabeledSeriesCollection PrintPerWeekSeries
+ {
+ get { return _printPerWeekSeries; }
+ set { _printPerWeekSeries = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _startDate;
+ public DateTime StartDate
+ {
+ get { return _startDate; }
+ set { _startDate = value; RaisePropertyChangedAuto();}
+ }
+
+ private DateTime _endDate;
+ public DateTime EndDate
+ {
+ get { return _endDate; }
+ set { _endDate = value; RaisePropertyChangedAuto();}
+ }
+
+ private DateTime _minDate;
+ public DateTime MinDate
+ {
+ get { return _minDate; }
+ set { _minDate = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _maxDate;
+ public DateTime MaxDate
+ {
+ get { return _maxDate; }
+ set { _maxDate = value; RaisePropertyChangedAuto(); }
+ }
+
+ public RelayCommand LoadJobRunsCommand { get; set; }
+ #endregion
+
+ public ChartsViewVM(INotificationProvider notificationProvider)
+ {
+ _notification = notificationProvider;
+ StartDate = DateTime.Now.AddMonths(-1);
+ EndDate = DateTime.Now;
+ LoadJobRunsCommand = new RelayCommand(async () => await LoadJobRuns(), () => IsFree);
+ }
+
+ #region Generate Charts
+
+ //public async void Init()
+ //{
+ //using (_notification.PushTaskItem("Loading statistics..."))
+ //{
+ // IsFree = false;
+
+ // await Task.Factory.StartNew(() =>
+ // {
+ // _context = ObservablesContext.CreateDefault();
+ // //_job_runs = _context.JobRuns.OrderBy(x => x.StartDate).ToList().Select(x => new JobRunStatisticsModel(x)).ToList();
+ // //foreach (var run in _job_runs)
+ // //{
+ // // run.LoadMachine(_context).GetAwaiter().GetResult();
+ // //}
+ // });
+
+ // if (_job_runs.Count > 0)
+ // {
+ // MinDate = _job_runs.Min(x => x.StartDate);
+ // MaxDate = _job_runs.Max(x => x.StartDate);
+ // }
+
+ // InvokeUIOnIdle(() =>
+ // {
+ // if (_loaded)
+ // {
+ // OnDateRangeChanged();
+ // }
+ // });
+
+ // _loaded = true;
+ // IsFree = true;
+ //}
+ //}
+ private async Task LoadJobRuns()
+ {
+ using (_notification.PushTaskItem("Loading statistics..."))
+ {
+ try
+ {
+ IsFree = false;
+
+ await Task.Factory.StartNew(() =>
+ {
+ using (var db = ObservablesContext.CreateDefault())
+ {
+ _job_runs = db.JobRuns.OrderBy(x => x.StartDate).ToList().Select(x => new JobRunStatisticsModel(x)).ToList();
+ foreach (var run in _job_runs)
+ {
+ run.LoadMachine(db).GetAwaiter().GetResult();
+ }
+
+ }
+ });
+ if (_job_runs.Count > 0)
+ {
+ MinDate = _job_runs.Min(x => x.StartDate);
+ MaxDate = _job_runs.Max(x => x.StartDate);
+ }
+
+ InvokeUIOnIdle(() =>
+ {
+ if (_loaded)
+ {
+ OnDateRangeChanged();
+ }
+ });
+
+ _loaded = true;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading statistics.");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ }
+
+
+ private List<JobRunStatisticsModel> GetJobRunsByDateRange(DateTime startDate, DateTime endTime, JobRunStatus? status = null)
+ {
+ return _job_runs.Where(x => x.StartDate.ToLocalTime() >= startDate && x.StartDate.ToLocalTime() <= endTime && (status == null || x.JobRunStatus == status)).ToList();
+ }
+
+ private List<JobRunStatisticsModel> GetJobRunsByDate(DateTime date, JobRunStatus? status = null)
+ {
+ return _job_runs.Where(x => x.StartDate.ToLocalTime().Date == date.Date && (status == null || x.JobRunStatus == status)).ToList();
+ }
+
+ private IEnumerable<DateTime> CreateDates(DateTime start, DateTime end)
+ {
+ for (DateTime date = start.Date; date.Date <= end.Date; date = date.AddDays(1))
+ {
+ yield return date;
+ }
+ }
+
+ private void GenerateTimelineJobStatusChart()
+ {
+ TimelineJobStatusSeries = new LabeledSeriesCollection()
+ {
+ Title = "Job Runs Status",
+ ChartTitle = "Number Of Runs",
+ LabelsTitle = "Date",
+ SeriesColors = new List<Color>()
+ {
+ Colors.Green,
+ Colors.Orange,
+ Colors.Red,
+ },
+ };
+
+ Series completed_job_runs = new ColumnSeries()
+ {
+ Title = "Completed",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Green,
+ MinWidth = 1,
+
+ };
+ Series aborted_job_runs = new ColumnSeries()
+ {
+ Title = "Aborted",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Orange,
+ MinWidth = 1,
+ };
+ Series failed_job_runs = new ColumnSeries()
+ {
+ Title = "Failed",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Red,
+ MinWidth = 1,
+ };
+
+ if (EndDate - StartDate > TimeSpan.FromDays(40))
+ {
+ completed_job_runs = new LineSeries()
+ {
+ Title = "Completed",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Green) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+
+ };
+ aborted_job_runs = new LineSeries()
+ {
+ Title = "Aborted",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Orange) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+ };
+ failed_job_runs = new LineSeries()
+ {
+ Title = "Failed",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+ };
+ }
+
+ foreach (var date in CreateDates(StartDate, EndDate))
+ {
+ completed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Completed).Count());
+ aborted_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Aborted).Count());
+ failed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Failed).Count());
+
+ TimelineJobStatusSeries.Labels.Add(date.ToShortDateString());
+ }
+
+
+
+ TimelineJobStatusSeries.SeriesCollection.Add(failed_job_runs);
+ TimelineJobStatusSeries.SeriesCollection.Add(aborted_job_runs);
+ TimelineJobStatusSeries.SeriesCollection.Add(completed_job_runs);
+ }
+
+ private void GeneratePieFailedReasonsChart()
+ {
+ var groups = GetJobRunsByDateRange(StartDate, EndDate, JobRunStatus.Failed).GroupBy(x => x.FailedMessage).OrderBy(x => x.Count());
+
+ List<Color> colors = new List<Color>();
+
+ int max = groups.Count() > 0 ? groups.Max(x => x.Count()) : 0;
+
+ for (int i = 0; i < groups.Count(); i++)
+ {
+ int count = groups.ElementAt(i).Count();
+ double alpha = Math.Max(((double)(count) / max * 200), 20);
+ colors.Add(Color.FromArgb((byte)alpha, 200, 0, 0));
+ }
+
+ PieJobFailedReasons = new LabeledSeriesCollection()
+ {
+ Title = "Job Failure Reasons",
+ SeriesColors = colors,
+ };
+
+ int index = 0;
+
+ foreach (var group in groups)
+ {
+ int count = group.Count();
+
+ var series = new PieSeries()
+ {
+ Title = group.First().FailedMessage,
+ Values = new ChartValues<int>() { count },
+ Fill = new SolidColorBrush(colors[index++]),
+ DataLabels = true,
+ ToolTip = group.First().FailedMessage,
+ };
+
+ PieJobFailedReasons.SeriesCollection.Add(series);
+ }
+ }
+
+ private void GeneratePrintPerWeekChart()
+ {
+ List<JobRunStatisticsModel> range_job_runs = GetJobRunsByDateRange(StartDate, EndDate);
+
+ Dictionary<Machine, List<double>> weeks_print_avg = new Dictionary<Machine, List<double>>();
+
+ //Init machines weeks averages dictionary.
+ foreach (var machine in range_job_runs.Select(x => x.Machine).OrderBy(x => x.Name).DistinctBy(x => x.Guid))
+ {
+ weeks_print_avg[machine] = new List<double>();
+ }
+
+ //Create all available dates
+ List<DateTime> all_dates = range_job_runs.Select(x => x.StartDate).ToList();
+
+ //get first Sunday.
+ DateTime current_sunday = all_dates.FirstOrDefault(x => x.DayOfWeek == DayOfWeek.Sunday);
+
+ if (current_sunday != null && all_dates.Count > 0)
+ {
+ //Iterate over each week starting from the earliest Sunday.
+ while (current_sunday <= all_dates.Last())
+ {
+ var week_job_runs = range_job_runs.Where(x => x.EndPosition > 10 && x.StartDate >= current_sunday && x.StartDate <= current_sunday.AddDays(7)).ToList();
+
+ foreach (var machine_job_runs in week_job_runs.GroupBy(x => x.Machine))
+ {
+ weeks_print_avg[machine_job_runs.Key].Add(machine_job_runs.Select(x => x.EndPosition).Average());
+ }
+
+ current_sunday = current_sunday.AddDays(8);
+ }
+ }
+
+ Dictionary<Machine, double> week_print_avg = new Dictionary<Machine, double>();
+
+ //Init machines week average dictionary.
+ foreach (var machine in weeks_print_avg)
+ {
+ if (machine.Value.Count > 0)
+ {
+ week_print_avg[machine.Key] = machine.Value.Average();
+ }
+ }
+
+ //Init chart series
+ PrintPerWeekSeries = new LabeledSeriesCollection()
+ {
+ Title = "Average Printed Thread Per Week (m)",
+ ChartTitle = "Average Print Per Week (m)",
+ LabelsTitle = "Date",
+ SeriesColors = new List<Color>()
+ {
+
+ },
+ };
+
+ //Init series colors intensity by number of prints.
+ double max = week_print_avg.Count > 0 ? week_print_avg.Max(x => x.Value) : 0;
+ foreach (var machine in week_print_avg)
+ {
+ double a = (machine.Value / max);
+ PrintPerWeekSeries.SeriesColors.Add(Color.FromArgb((byte)(255d * (machine.Value / max)), 0, 200, 0));
+ }
+
+ //Init columns.
+ int index = 0;
+
+ foreach (var machine in week_print_avg)
+ {
+ var series = new ColumnSeries()
+ {
+ Title = machine.Key.Name,
+ Values = new ChartValues<int>() { (int)machine.Value },
+ Fill = new SolidColorBrush(PrintPerWeekSeries.SeriesColors[index++]),
+ DataLabels = true,
+ ToolTip = machine.Key.SerialNumber,
+ };
+
+ PrintPerWeekSeries.SeriesCollection.Add(series);
+ }
+ }
+
+ #endregion
+
+ #region Filter by Date
+ public void OnDateRangeChanged()
+ {
+ if (_job_runs != null && _job_runs.Count > 0)// && _loaded)
+ {
+ GenerateTimelineJobStatusChart();
+ GeneratePieFailedReasonsChart();
+ GeneratePrintPerWeekChart();
+ }
+ }
+ #endregion
+
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs
new file mode 100644
index 000000000..94d06a178
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs
@@ -0,0 +1,486 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.Entity;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.Builders;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.Core.Commands;
+using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Statistics.Models;
+using Tango.SharedUI;
+using Tango.SharedUI.Components;
+using Tango.AutoComplete.Editors;
+using System.Windows.Media;
+using LiveCharts.Wpf;
+using LiveCharts;
+using Tango.BL.ValueObjects;
+
+namespace Tango.MachineStudio.Statistics.ViewModels
+{
+ public class JobRunsViewVM : ViewModel
+ {
+ private INotificationProvider _notification;
+ private List<Machine> _allMachines;
+ private List<User> _allUsers;
+ private List<RmlModel> _rmlsModels;
+
+ #region Properties
+
+ private ObservableCollection<JobRunModel> _jobRuns;
+ /// <summary>
+ /// Gets or sets the job runs. Contains filtered data of JobRunModel.
+ /// </summary>
+ public ObservableCollection<JobRunModel> JobRuns
+ {
+ get { return _jobRuns; }
+ set
+ {
+ _jobRuns = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private JobRunModel _selectedJobRun = null;
+ /// <summary>
+ /// Gets or sets the JobRunModel. Binding to selected item of grid items.
+ /// </summary>
+ public JobRunModel SelectedJobRun
+ {
+ get { return _selectedJobRun; }
+ set
+ {
+ _selectedJobRun = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private SelectedObjectCollection<Machine> _selectedMachines;
+ /// <summary>
+ /// Gets or sets the selected machines. Contains all available machines and selected machines. Binding to ComboBox Machines.
+ /// </summary>
+ public SelectedObjectCollection<Machine> SelectedMachines
+ {
+ get { return _selectedMachines; }
+ set
+ {
+ _selectedMachines = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private DateTime _startSelectedDate;
+ /// <summary>
+ /// Gets or sets the start selected date.
+ /// </summary>
+ public DateTime StartSelectedDate
+ {
+ get { return _startSelectedDate; }
+ set { _startSelectedDate = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _endSelectedDate;
+ /// <summary>
+ /// Gets or sets the end selected date.
+ /// </summary>
+ public DateTime EndSelectedDate
+ {
+ get { return _endSelectedDate; }
+ set { _endSelectedDate = value; RaisePropertyChangedAuto(); }
+ }
+
+ protected Double _lengthLowerValue;
+ /// <summary>
+ /// Gets or sets the length lower value of Range Slider
+ /// </summary>
+ public Double LengthLowerValue
+ {
+ get { return _lengthLowerValue; }
+ set
+ {
+ _lengthLowerValue = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ protected Double _lengthUpperValue;
+ /// <summary>
+ /// Gets or sets the length upper value of Range Slider.
+ /// </summary>
+ public Double LengthUpperValue
+ {
+ get { return _lengthUpperValue; }
+ set
+ {
+ _lengthUpperValue = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private SelectedObjectCollection<JobSource> _jobRunSelectedSources;
+ /// <summary>
+ /// Gets or sets the job run selected sources. Binding to ComboBox "Source".
+ /// </summary>
+ public SelectedObjectCollection<JobSource> JobRunSelectedSources
+ {
+ get { return _jobRunSelectedSources; }
+ set { _jobRunSelectedSources = value; RaisePropertyChangedAuto(); }
+ }
+
+ private SelectedObjectCollection<JobRunStatus> _jobRunSelectedStatuses;
+ /// <summary>
+ /// Gets or sets the job run selected statuses. Binding to ComboBox "Status".
+ /// </summary>
+ public SelectedObjectCollection<JobRunStatus> JobRunSelectedStatuses
+ {
+ get { return _jobRunSelectedStatuses; }
+ set { _jobRunSelectedStatuses = value; RaisePropertyChangedAuto(); }
+ }
+
+ public SelectedObjectCollection<bool> _isGradientSelection;
+ /// <summary>
+ /// Gets or sets the is gradient selection. Binding to ComboBox "IsGradient".
+ /// </summary>
+ public SelectedObjectCollection<bool> IsGradientSelection
+ {
+ get { return _isGradientSelection; }
+ set
+ {
+ _isGradientSelection = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private SelectedObjectCollection<RmlModel> _selectedThreads;
+ /// <summary>
+ /// Gets or sets the selected threads. Contains all available threads and selected threads. Binding to ComboBox "Thread".
+ /// </summary>
+ public SelectedObjectCollection<RmlModel> SelectedThreads
+ {
+ get { return _selectedThreads; }
+ set
+ {
+ _selectedThreads = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the JobRuns providers.
+ /// </summary>
+ public ISuggestionProvider JobsProvider { get; set; }
+
+ private Job _selectedJob;
+ /// <summary>
+ /// Gets or sets the job.
+ /// </summary>
+ public Job SelectedJob
+ {
+ get { return _selectedJob; }
+ set
+ {
+ _selectedJob = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the statistics value collection. Class - container included calculated statistic values.
+ /// </summary>
+ public StatisticsValueCollection StatisticsValueCollection { get; set; }
+
+ #endregion
+
+ public RelayCommand LoadJobRunsCommand { get; set; }
+
+ public JobRunsViewVM(INotificationProvider notificationProvider)
+ {
+ _notification = notificationProvider;
+ JobRuns = new ObservableCollection<JobRunModel>();
+ LoadJobRunsCommand = new RelayCommand(async () => await LoadJobRuns(), () => IsFree);
+ LengthUpperValue = 5000.0;
+ LengthLowerValue = 0.0;
+ DateTime now = DateTime.Now;
+ StartSelectedDate = now.AddMonths(-1);
+ EndSelectedDate = now;
+
+ JobRunSelectedSources = new SelectedObjectCollection<JobSource>(new ObservableCollection<JobSource>()
+ {
+ JobSource.Local,
+ JobSource.Remote
+ }, new ObservableCollection<JobSource>()
+ {
+ JobSource.Local,
+ JobSource.Remote
+ });
+ JobRunSelectedSources.SelectionChanged -= (x, y) => RaisePropertyChanged(nameof(JobRunSelectedSources));
+ JobRunSelectedSources.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(JobRunSelectedSources));
+
+ JobRunSelectedStatuses = new SelectedObjectCollection<JobRunStatus>(new ObservableCollection<JobRunStatus>()
+ {
+ JobRunStatus.Aborted,
+ JobRunStatus.Completed,
+ JobRunStatus.Failed,
+
+ }, new ObservableCollection<JobRunStatus>()
+ {
+ JobRunStatus.Aborted,
+ JobRunStatus.Completed,
+ JobRunStatus.Failed,
+
+ });
+ JobRunSelectedStatuses.SelectionChanged -= (x, y) => RaisePropertyChanged(nameof(JobRunSelectedStatuses));
+ JobRunSelectedStatuses.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(JobRunSelectedStatuses));
+
+ IsGradientSelection = new SelectedObjectCollection<bool>(new ObservableCollection<bool>
+ {
+ true,
+ false
+ }, new ObservableCollection<bool>
+ {
+ true,
+ false
+ });
+ IsGradientSelection.SelectionChanged -= (x, y) => RaisePropertyChanged(nameof(IsGradientSelection));
+ IsGradientSelection.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(IsGradientSelection));
+ JobsProvider = new SuggestionProvider((filter) =>
+ {
+ try
+ {
+ if (filter != null)
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ return db.Jobs.Where(x => x.Name != null && x.Name.ToLower().Contains(filter.ToLower())).ToList();
+ }
+ }
+ else
+ {
+ return new List<Job>();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading jobs.");
+ return null;
+ }
+ });
+
+ StatisticsValueCollection = new StatisticsValueCollection();
+ }
+
+ /// <summary>
+ /// Initializes this instance. Called form main view VM in OnApplicationReady
+ /// </summary>
+ public async void Init()
+ {
+ using (_notification.PushTaskItem("Loading job runs..."))
+ {
+ try
+ {
+ IsFree = false;
+
+ using (var db = ObservablesContext.CreateDefault())
+ {
+ _allMachines = await db.Machines.ToListAsync();
+ _allUsers = await db.Users.Include(x => x.Contact).ToListAsync();
+ _rmlsModels = await db.Rmls.Select(x => new RmlModel() { Name = x.Name, Guid = x.Guid }).ToListAsync();
+ SelectedMachines = new SelectedObjectCollection<Machine>(_allMachines.ToObservableCollection(), new ObservableCollection<Machine>());
+ SelectedThreads = new SelectedObjectCollection<RmlModel>(_rmlsModels.ToObservableCollection(), new ObservableCollection<RmlModel>());
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading job runs.");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Loads the job runs by filters.
+ /// </summary>
+ private async Task LoadJobRuns()
+ {
+ using (_notification.PushTaskItem("Loading job runs..."))
+ {
+ try
+ {
+ IsFree = false;
+
+ using (var db = ObservablesContext.CreateDefault())
+ {
+ DateTime startUtc = StartSelectedDate.ToUniversalTime();
+ TimeSpan offsetTime = (EndSelectedDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(23, 59, 59);
+ DateTime endUtc = EndSelectedDate.ToUniversalTime() + offsetTime;
+ string jobName = SelectedJob == null ? "" : SelectedJob.Name;
+
+ var runs = await new JobRunsCollectionBuilder(db).Set(x => x.StartDate <= DbFunctions.TruncateTime(endUtc) && x.StartDate >= DbFunctions.TruncateTime(startUtc.Date))
+ .WithMachines(SelectedMachines.SynchedSource.ToList())
+ .WithJobSource(JobRunSelectedSources.SynchedSource)
+ .WithJobStatus(JobRunSelectedStatuses.SynchedSource)
+ .WithGradient(IsGradientSelection.SynchedSource)
+ .WithRmls(SelectedThreads.SynchedSource.Select(x => x.Guid).ToList())
+ .Query(y => y.Where(x => (String.IsNullOrEmpty(jobName) || x.JobName.ToLower().StartsWith(jobName.ToLower()))
+ && (x.JobLength < LengthUpperValue && x.JobLength >= LengthLowerValue)))
+ .BuildListAsync();
+
+ var modelList = runs.Select(x => new JobRunModel()
+ {
+ JobRun = x,
+ Machine = _allMachines.FirstOrDefault(y => y.Guid == x.MachineGuid),
+ User = _allUsers.SingleOrDefault(y => y.Guid == x.UserGuid),
+ Rml = _rmlsModels.SingleOrDefault(y => y.Guid == x.RmlGuid),
+ }).OrderByDescending(x => x.JobRun.StartDate).ToList();
+
+ modelList.ForEach(x => x.Init());
+ JobRuns = modelList.ToObservableCollection();
+ GenerateStatistics();
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading job runs.");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ }
+
+ #region GenerateS_StatisticsValueCollection
+
+ /// <summary>
+ /// Generates the statistics.
+ /// </summary>
+ protected void GenerateStatistics()
+ {
+ StatisticsValueCollection.Clean();
+ GenerateTotalRunsCount();
+ GenerateTotalRunsLength();
+ GenerateTotalThreadConsumption();
+ GenerateRunsDuration();
+ GenerateAverageUploadDuration();
+ GenerateAverageHeatingDuration();
+
+ GeneratePieCharts();
+ CreateThreadConsumptionPerThread();
+ GenerateAllLiquidQuantities();
+ }
+
+ protected void GenerateTotalRunsCount()
+ {//Total Runs:
+ int val =JobRuns.Where(z => z.JobRun.EndPosition > 0).Count();
+ StatisticsValueCollection.AddStatisticsValue("Total Runs ", val, " ");
+ }
+
+ /// <summary>
+ /// Generates the total length of the job runs.
+ /// </summary>
+ protected void GenerateTotalRunsLength()
+ {
+ double val = JobRuns.Where(z => z.JobRun.EndPosition > 0).Sum(x => x.JobRun.JobLength);
+ StatisticsValueCollection.AddStatisticsValue("Total Runs Length", val, " m");
+ }
+
+ /// <summary>
+ /// Generates the duration and average of the job runs.
+ /// </summary>
+ protected void GenerateRunsDuration()
+ {
+ var selection = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.JobRun.EndDate != null && z.JobRun.ActualStartDate != null);
+ double val = selection.Sum(x => (x.JobRun.EndDate - x.JobRun.ActualStartDate).Value.TotalHours);
+ StatisticsValueCollection.AddStatisticsValue("Total Runs Duration", val, " hours");
+ double average = selection.Average(x => (x.JobRun.EndDate - x.JobRun.ActualStartDate).Value.TotalMilliseconds);
+ StatisticsValueCollection.AddStatisticsValue("Average Runs Duration", Math.Max(TimeSpan.FromMilliseconds(average).TotalHours, 0), " hours");
+ }
+
+ /// <summary>
+ /// Generates the average upload duration of the job runs.
+ /// </summary>
+ protected void GenerateAverageUploadDuration()
+ {
+ var average = (long)JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.UploadDuration != null).Average(x => x.UploadDuration.Value.TotalMilliseconds);
+ StatisticsValueCollection.AddStatisticsValue("Average Upload Duration", Math.Max(TimeSpan.FromMilliseconds(average).TotalMinutes, 0), " minutes");
+ }
+
+ /// <summary>
+ /// Generates the average duration heating of the job runs.
+ /// </summary>
+ protected void GenerateAverageHeatingDuration()
+ {
+ var average = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.HeatingDuration != null && z.HeatingDuration.Value.Ticks > 0).Average(x => x.HeatingDuration.Value.TotalMilliseconds);
+ StatisticsValueCollection.AddStatisticsValue("Average Heating Duration", Math.Max(TimeSpan.FromMilliseconds(average).TotalMinutes, 0), " minutes");
+ }
+
+ /// <summary>
+ /// Generates the total thread consumption by EndPosition.
+ /// </summary>
+ protected void GenerateTotalThreadConsumption()
+ {
+ double val = JobRuns.Where(z => z.JobRun.EndPosition > 0).Sum(x => x.JobRun.EndPosition);
+ StatisticsValueCollection.AddStatisticsValue("Actual Total Runs Length", val, " m");
+ }
+
+ /// <summary>
+ /// Generates the pie charts in percentage: JobSource, JobRunStatus, Gradient.
+ /// </summary>
+ protected void GeneratePieCharts()
+ {
+ int PPCCount = JobRuns.Count(x => x.JobRun.Source == JobSource.Local);
+ int MSCount = JobRuns.Count(x => x.JobRun.Source == JobSource.Remote);
+ StatisticsValueCollection.GeneratePieJobSource(PPCCount, MSCount);
+
+ int failedCount = JobRuns.Count(x => x.JobRun.JobRunStatus == JobRunStatus.Failed);
+ int abortedCount = JobRuns.Count(x => x.JobRun.JobRunStatus == JobRunStatus.Aborted);
+ int completedCount = JobRuns.Count(x => x.JobRun.JobRunStatus == JobRunStatus.Completed);
+ StatisticsValueCollection.GeneratePieJobRunStatus(failedCount, abortedCount, completedCount);
+
+ int gradientCount = JobRuns.Count(x => x.JobRun.IsGradient == true);
+ int solidCount = JobRuns.Count(x => x.JobRun.IsGradient == false);
+ StatisticsValueCollection.GeneratePieGradientSolid(gradientCount, solidCount);
+
+ }
+
+ /// <summary>
+ /// Creates the thread consumption per thread.
+ /// </summary>
+ protected void CreateThreadConsumptionPerThread()
+ {
+ var temp = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.Rml != null).GroupBy(x => x.Rml.Name);
+ List<StatisticsValue> result = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.Rml != null && !String.IsNullOrEmpty(z.Rml.Name)).GroupBy(x => x.Rml.Name).Select(y => new StatisticsValue { Name = y.Key, Value = y.Sum(x => x.JobRun.EndPosition), Unit = "m" }).ToList();
+ StatisticsValueCollection.CreateThreadConsumptionPerThread(result);
+ }
+
+ /// <summary>
+ /// Generates all liquid quantities.
+ /// </summary>
+ protected void GenerateAllLiquidQuantities()
+ {
+ var db_liquidQuantities = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.JobRun.LiquidQuantities.Count > 0).Select(y => y.JobRun.LiquidQuantities).ToList();
+ List<JobRunLiquidQuantity> allLiquidQuantities = new List<JobRunLiquidQuantity>();
+
+ foreach (LiquidTypes ltype in (LiquidTypes[])Enum.GetValues(typeof(LiquidTypes)))
+ {
+ var liquidQuantityByTypeList = db_liquidQuantities.Select(x => x.FirstOrDefault(y => y.LiquidType == ltype)).Where(x => x != null);
+ var count = liquidQuantityByTypeList != null ? liquidQuantityByTypeList.Sum(x => x.Quantity) : 0;
+ JobRunLiquidQuantity lq = new JobRunLiquidQuantity() { LiquidType = ltype, Quantity = count };
+ allLiquidQuantities.Add(lq);
+ }
+ StatisticsValueCollection.GenerateStatisticsLiquidQuantity(allLiquidQuantities);
+ }
+ #endregion
+
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
index dfbfe2648..e7e2013c5 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
@@ -19,349 +19,37 @@ namespace Tango.MachineStudio.Statistics.ViewModels
{
public class MainViewVM : StudioViewModel
{
- private ObservablesContext _context;
- private List<JobRunModel> _job_runs;
- private bool rendered;
private INotificationProvider _notification;
- private bool _loaded;
- private LabeledSeriesCollection _timelineJobStatusSeries;
- public LabeledSeriesCollection TimelineJobStatusSeries
+ private ChartsViewVM _chartsViewVM;
+ public ChartsViewVM ChartsViewVM
{
- get { return _timelineJobStatusSeries; }
- set { _timelineJobStatusSeries = value; RaisePropertyChangedAuto(); }
+ get { return _chartsViewVM; }
+ set { _chartsViewVM = value; RaisePropertyChangedAuto(); }
}
- private LabeledSeriesCollection _pieJobFailedReasons;
- public LabeledSeriesCollection PieJobFailedReasons
+ private JobRunsViewVM _jobRunsViewVM;
+ public JobRunsViewVM JobRunsViewVM
{
- get { return _pieJobFailedReasons; }
- set { _pieJobFailedReasons = value; RaisePropertyChangedAuto(); }
+ get { return _jobRunsViewVM; }
+ set { _jobRunsViewVM = value; RaisePropertyChangedAuto(); }
}
-
- private LabeledSeriesCollection _printPerWeekSeries;
- public LabeledSeriesCollection PrintPerWeekSeries
- {
- get { return _printPerWeekSeries; }
- set { _printPerWeekSeries = value; RaisePropertyChangedAuto(); }
- }
-
- private DateTime _startDate;
- public DateTime StartDate
- {
- get { return _startDate; }
- set { _startDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
- }
-
- private DateTime _endDate;
- public DateTime EndDate
- {
- get { return _endDate; }
- set { _endDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
- }
-
- private DateTime _minDate;
- public DateTime MinDate
- {
- get { return _minDate; }
- set { _minDate = value; RaisePropertyChangedAuto(); }
- }
-
- private DateTime _maxDate;
- public DateTime MaxDate
- {
- get { return _maxDate; }
- set { _maxDate = value; RaisePropertyChangedAuto(); }
- }
-
+
public MainViewVM(INotificationProvider notificationProvider)
{
_notification = notificationProvider;
-
- StartDate = DateTime.Now.AddMonths(-1);
- EndDate = DateTime.Now;
+ ChartsViewVM = new ChartsViewVM(_notification);
+ JobRunsViewVM = new JobRunsViewVM(_notification);
}
public override void OnApplicationReady()
{
-
- }
-
- private List<JobRunModel> GetJobRunsByDateRange(DateTime startDate, DateTime endTime, JobRunStatus? status = null)
- {
- return _job_runs.Where(x => x.StartDate.ToLocalTime() >= startDate && x.StartDate.ToLocalTime() <= endTime && (status == null || x.JobRunStatus == status)).ToList();
- }
-
- private List<JobRunModel> GetJobRunsByDate(DateTime date, JobRunStatus? status = null)
- {
- return _job_runs.Where(x => x.StartDate.ToLocalTime().Date == date.Date && (status == null || x.JobRunStatus == status)).ToList();
- }
-
- private IEnumerable<DateTime> CreateDates(DateTime start, DateTime end)
- {
- for (DateTime date = start.Date; date.Date <= end.Date; date = date.AddDays(1))
- {
- yield return date;
- }
+ JobRunsViewVM.Init();
}
- public override async void OnNavigatedTo()
+ public override void OnNavigatedTo()
{
base.OnNavigatedTo();
-
- if (rendered) return;
-
- rendered = true;
-
-
- using (_notification.PushTaskItem("Loading statistics..."))
- {
- IsFree = false;
-
- await Task.Factory.StartNew(() =>
- {
- _context = ObservablesContext.CreateDefault();
- _job_runs = _context.JobRuns.OrderBy(x => x.StartDate).ToList().Select(x => new JobRunModel(x)).ToList();
- foreach (var run in _job_runs)
- {
- run.LoadMachine(_context).GetAwaiter().GetResult();
- }
- });
-
- if (_job_runs.Count > 0)
- {
- MinDate = _job_runs.Min(x => x.StartDate);
- MaxDate = _job_runs.Max(x => x.StartDate);
- }
-
- InvokeUIOnIdle(() =>
- {
- OnDateRangeChanged();
- });
-
- _loaded = true;
-
- IsFree = true;
- }
- }
-
- private void OnDateRangeChanged()
- {
- if (_job_runs != null && _job_runs.Count > 0 && _loaded)
- {
- GenerateTimelineJobStatusChart();
- GeneratePieFailedReasonsChart();
- GeneratePrintPerWeekChart();
- }
- }
-
- private void GenerateTimelineJobStatusChart()
- {
- TimelineJobStatusSeries = new LabeledSeriesCollection()
- {
- Title = "Job Runs Status",
- ChartTitle = "Number Of Runs",
- LabelsTitle = "Date",
- SeriesColors = new List<Color>()
- {
- Colors.Green,
- Colors.Orange,
- Colors.Red,
- },
- };
-
- Series completed_job_runs = new ColumnSeries()
- {
- Title = "Completed",
- Values = new ChartValues<int>(),
- Fill = Brushes.Green,
- MinWidth = 1,
-
- };
- Series aborted_job_runs = new ColumnSeries()
- {
- Title = "Aborted",
- Values = new ChartValues<int>(),
- Fill = Brushes.Orange,
- MinWidth = 1,
- };
- Series failed_job_runs = new ColumnSeries()
- {
- Title = "Failed",
- Values = new ChartValues<int>(),
- Fill = Brushes.Red,
- MinWidth = 1,
- };
-
- if (EndDate - StartDate > TimeSpan.FromDays(40))
- {
- completed_job_runs = new LineSeries()
- {
- Title = "Completed",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Green) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
-
- };
- aborted_job_runs = new LineSeries()
- {
- Title = "Aborted",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Orange) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
- };
- failed_job_runs = new LineSeries()
- {
- Title = "Failed",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
- };
- }
-
- foreach (var date in CreateDates(StartDate, EndDate))
- {
- completed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Completed).Count());
- aborted_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Aborted).Count());
- failed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Failed).Count());
-
- TimelineJobStatusSeries.Labels.Add(date.ToShortDateString());
- }
-
-
-
- TimelineJobStatusSeries.SeriesCollection.Add(failed_job_runs);
- TimelineJobStatusSeries.SeriesCollection.Add(aborted_job_runs);
- TimelineJobStatusSeries.SeriesCollection.Add(completed_job_runs);
- }
-
- private void GeneratePieFailedReasonsChart()
- {
- var groups = GetJobRunsByDateRange(StartDate, EndDate, JobRunStatus.Failed).GroupBy(x => x.FailedMessage).OrderBy(x => x.Count());
-
- List<Color> colors = new List<Color>();
-
- int max = groups.Count() > 0 ? groups.Max(x => x.Count()) : 0;
-
- for (int i = 0; i < groups.Count(); i++)
- {
- int count = groups.ElementAt(i).Count();
- double alpha = Math.Max(((double)(count) / max * 200), 20);
- colors.Add(Color.FromArgb((byte)alpha, 200, 0, 0));
- }
-
- PieJobFailedReasons = new LabeledSeriesCollection()
- {
- Title = "Job Failure Reasons",
- SeriesColors = colors,
- };
-
- int index = 0;
-
- foreach (var group in groups)
- {
- int count = group.Count();
-
- var series = new PieSeries()
- {
- Title = group.First().FailedMessage,
- Values = new ChartValues<int>() { count },
- Fill = new SolidColorBrush(colors[index++]),
- DataLabels = true,
- ToolTip = group.First().FailedMessage,
- };
-
- PieJobFailedReasons.SeriesCollection.Add(series);
- }
- }
-
- private void GeneratePrintPerWeekChart()
- {
- List<JobRunModel> range_job_runs = GetJobRunsByDateRange(StartDate, EndDate);
-
- Dictionary<Machine, List<double>> weeks_print_avg = new Dictionary<Machine, List<double>>();
-
- //Init machines weeks averages dictionary.
- foreach (var machine in range_job_runs.Select(x => x.Machine).OrderBy(x => x.Name).DistinctBy(x => x.Guid))
- {
- weeks_print_avg[machine] = new List<double>();
- }
-
- //Create all available dates
- List<DateTime> all_dates = range_job_runs.Select(x => x.StartDate).ToList();
-
- //get first Sunday.
- DateTime current_sunday = all_dates.FirstOrDefault(x => x.DayOfWeek == DayOfWeek.Sunday);
-
- if (current_sunday != null && all_dates.Count > 0)
- {
- //Iterate over each week starting from the earliest Sunday.
- while (current_sunday <= all_dates.Last())
- {
- var week_job_runs = range_job_runs.Where(x => x.EndPosition > 10 && x.StartDate >= current_sunday && x.StartDate <= current_sunday.AddDays(7)).ToList();
-
- foreach (var machine_job_runs in week_job_runs.GroupBy(x => x.Machine))
- {
- weeks_print_avg[machine_job_runs.Key].Add(machine_job_runs.Select(x => x.EndPosition).Average());
- }
-
- current_sunday = current_sunday.AddDays(8);
- }
- }
-
- Dictionary<Machine, double> week_print_avg = new Dictionary<Machine, double>();
-
- //Init machines week average dictionary.
- foreach (var machine in weeks_print_avg)
- {
- if (machine.Value.Count > 0)
- {
- week_print_avg[machine.Key] = machine.Value.Average();
- }
- }
-
- //Init chart series
- PrintPerWeekSeries = new LabeledSeriesCollection()
- {
- Title = "Average Printed Thread Per Week (m)",
- ChartTitle = "Average Print Per Week (m)",
- LabelsTitle = "Date",
- SeriesColors = new List<Color>()
- {
-
- },
- };
-
- //Init series colors intensity by number of prints.
- double max = week_print_avg.Count > 0 ? week_print_avg.Max(x => x.Value) : 0;
- foreach (var machine in week_print_avg)
- {
- double a = (machine.Value / max);
- PrintPerWeekSeries.SeriesColors.Add(Color.FromArgb((byte)(255d * (machine.Value / max)), 0, 200, 0));
- }
-
- //Init columns.
- int index = 0;
-
- foreach (var machine in week_print_avg)
- {
- var series = new ColumnSeries()
- {
- Title = machine.Key.Name,
- Values = new ChartValues<int>() { (int)machine.Value },
- Fill = new SolidColorBrush(PrintPerWeekSeries.SeriesColors[index++]),
- DataLabels = true,
- ToolTip = machine.Key.SerialNumber,
- };
-
- PrintPerWeekSeries.SeriesCollection.Add(series);
- }
}
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml
new file mode 100644
index 000000000..ae4bf1d46
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml
@@ -0,0 +1,113 @@
+<UserControl x:Class="Tango.MachineStudio.Statistics.Views.ChartsView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:vm="clr-namespace:Tango.MachineStudio.Statistics.ViewModels"
+ xmlns:global="clr-namespace:Tango.MachineStudio.Statistics"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Statistics.Views"
+ xmlns:tooltips="clr-namespace:Tango.MachineStudio.Statistics.Tooltips"
+ xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
+ mc:Ignorable="d"
+ d:DesignHeight="450" d:DesignWidth="800">
+ <Grid IsEnabled="{Binding IsFree}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="80"/>
+ <RowDefinition Height="337*"/>
+ </Grid.RowDefinitions>
+
+
+ <StackPanel Margin="60 20 0 0" VerticalAlignment="Center" HorizontalAlignment="Left" Orientation="Horizontal" DockPanel.Dock="Left">
+ <StackPanel>
+ <TextBlock FontSize="10">Start Date:</TextBlock>
+ <DatePicker DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" SelectedDate="{Binding StartDate}" materialDesign:HintAssist.Hint="Pick start date" Width="200" VerticalAlignment="Bottom" FontSize="16"></DatePicker>
+ </StackPanel>
+
+ <StackPanel Margin="40 0 0 0">
+ <TextBlock FontSize="10">End Date:</TextBlock>
+ <DatePicker DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" SelectedDate="{Binding EndDate}" materialDesign:HintAssist.Hint="Pick end date" Width="200" VerticalAlignment="Bottom" FontSize="16"></DatePicker>
+ </StackPanel>
+ <Button Width="100" Margin="60 0 0 0" Command="{Binding LoadJobRunsCommand}" VerticalAlignment="Bottom" HorizontalAlignment="Right">LOAD</Button>
+ </StackPanel>
+
+
+ <UniformGrid Columns="3" Margin="50 20 50 50" Rows="2" Grid.Row="1">
+ <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding TimelineJobStatusSeries.Title}"></TextBlock>
+ <lvc:CartesianChart Series="{Binding TimelineJobStatusSeries.SeriesCollection}" LegendLocation="Bottom">
+ <lvc:CartesianChart.DataTooltip>
+ <lvc:DefaultTooltip BulletSize="20" Background="{StaticResource TransparentBackgroundBrush450}" Foreground="{StaticResource Dialog.Foreground}"/>
+ </lvc:CartesianChart.DataTooltip>
+ <lvc:CartesianChart.AxisX>
+ <lvc:Axis Title="{Binding TimelineJobStatusSeries.LabelsTitle}" Labels="{Binding TimelineJobStatusSeries.Labels}" Foreground="{StaticResource DarkGrayBrush200}">
+ <lvc:Axis.Separator>
+ <lvc:Separator Stroke="#A5A5A5" />
+ </lvc:Axis.Separator>
+ </lvc:Axis>
+ </lvc:CartesianChart.AxisX>
+ <lvc:CartesianChart.AxisY>
+ <lvc:Axis Title="{Binding TimelineJobStatusSeries.ChartTitle}" MinValue="0" Foreground="{StaticResource DarkGrayBrush200}" >
+ <lvc:Axis.Separator>
+ <lvc:Separator Stroke="#B0B0B0" />
+ </lvc:Axis.Separator>
+ </lvc:Axis>
+ </lvc:CartesianChart.AxisY>
+ </lvc:CartesianChart>
+ </DockPanel>
+ </Border>
+
+ <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding PieJobFailedReasons.Title}"></TextBlock>
+ <UniformGrid Columns="2">
+ <lvc:PieChart DataHover="PieChart_DataHover" Series="{Binding PieJobFailedReasons.SeriesCollection}" LegendLocation="None" Background="Transparent">
+ <lvc:PieChart.Resources>
+ <Style TargetType="lvc:PieSeries">
+ <Setter Property="Stroke" Value="#99F9F9F9"></Setter>
+ <Setter Property="StrokeThickness" Value="2"/>
+ </Style>
+ </lvc:PieChart.Resources>
+ <lvc:PieChart.DataTooltip>
+ <tooltips:PieChartTooltipControl Visibility="Hidden" />
+ </lvc:PieChart.DataTooltip>
+ </lvc:PieChart>
+
+ <TextBlock x:Name="txtPieTitle" TextWrapping="Wrap"></TextBlock>
+ </UniformGrid>
+ </DockPanel>
+ </Border>
+
+ <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding PrintPerWeekSeries.Title}"></TextBlock>
+ <lvc:CartesianChart Series="{Binding PrintPerWeekSeries.SeriesCollection}" LegendLocation="Bottom" >
+ <lvc:CartesianChart.Resources>
+ <Style TargetType="lvc:ColumnSeries">
+ <Setter Property="Foreground" Value="{StaticResource DarkGrayBrush200}"></Setter>
+ </Style>
+ </lvc:CartesianChart.Resources>
+ <lvc:CartesianChart.AxisX>
+ <lvc:Axis Title="{Binding PrintPerWeekSeries.LabelsTitle}" Labels="{Binding PrintPerWeekSeries.Labels}" Foreground="{StaticResource DarkGrayBrush200}">
+ <lvc:Axis.Separator>
+ <lvc:Separator Stroke="#A5A5A5" />
+ </lvc:Axis.Separator>
+ </lvc:Axis>
+ </lvc:CartesianChart.AxisX>
+ <lvc:CartesianChart.AxisY>
+ <lvc:Axis Title="{Binding PrintPerWeekSeries.ChartTitle}" MinValue="0" Foreground="{StaticResource DarkGrayBrush200}" >
+ <lvc:Axis.Separator>
+ <lvc:Separator Stroke="#6F6F6F" />
+ </lvc:Axis.Separator>
+ </lvc:Axis>
+ </lvc:CartesianChart.AxisY>
+ <lvc:CartesianChart.DataTooltip>
+ <lvc:DefaultTooltip BulletSize="20" Background="{StaticResource TransparentBackgroundBrush450}" Foreground="{StaticResource Dialog.Foreground}"/>
+ </lvc:CartesianChart.DataTooltip>
+ </lvc:CartesianChart>
+ </DockPanel>
+ </Border>
+ </UniformGrid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml.cs
new file mode 100644
index 000000000..d79d88281
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml.cs
@@ -0,0 +1,35 @@
+using LiveCharts;
+using LiveCharts.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.Statistics.Views
+{
+ /// <summary>
+ /// Interaction logic for ChartsView.xaml
+ /// </summary>
+ public partial class ChartsView : UserControl
+ {
+ public ChartsView()
+ {
+ InitializeComponent();
+ }
+ private void PieChart_DataHover(object sender, ChartPoint chartPoint)
+ {
+ var tooltip = ((chartPoint.ChartView as PieChart).DataTooltip as Tooltips.PieChartTooltipControl).Title;
+ txtPieTitle.Text = tooltip;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml
new file mode 100644
index 000000000..af363b32a
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml
@@ -0,0 +1,699 @@
+<UserControl x:Class="Tango.MachineStudio.Statistics.Views.JobRunsView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:sharedConverters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:localConverters="clr-namespace:Tango.MachineStudio.Statistics.Converters"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:autoComplete="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete"
+ xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
+ xmlns:tooltips="clr-namespace:Tango.MachineStudio.Statistics.Tooltips"
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
+ xmlns:enumerations="clr-namespace:Tango.BL.Enumerations;assembly=Tango.BL"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Statistics.Views"
+ xmlns:model="clr-namespace:Tango.MachineStudio.Statistics.Models"
+ xmlns:wellknowntypes="clr-namespace:Google.Protobuf.WellKnownTypes;assembly=Google.Protobuf"
+ mc:Ignorable="d"
+ d:DesignHeight="450" d:DesignWidth="1800" Foreground="{StaticResource JobFieldForeground}">
+ <UserControl.Resources>
+ <sharedConverters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
+ <sharedConverters:BooleanToYesNoConverter x:Key="BooleanToYesNoConverter"/>
+ <sharedConverters:EnumToDescriptionConverter x:Key="EnumToDescriptionConverter" />
+ <localConverters:DateTimeToStringFormatConverter x:Key="DateTimeToStringFormatConverter" />
+ <sharedConverters:DateTimeUTCToShortDateTimeConverter x:Key="DateTimeUTCToShortDateTimeConverter"/>
+ <localConverters:StringToBoolYesNoNullConverter x:Key="StringToBoolYesNoNullConverter"/>
+ <localConverters:LiquidTypeToColorConverter x:Key="LiquidTypeToColorConverter"/>
+ <localConverters:CollectionConverter x:Key="CollectionConverter"/>
+ <localConverters:StringToFirstLetterConverter x:Key="StringToFirstLetterConverter"/>
+ <localConverters:MidTankLevelToElementHeightConverter x:Key="MidTankLevelToElementHeightConverter"/>
+ <localConverters:JobLengthConverter x:Key="JobLengthConverter"/>
+ <localConverters:NanoLiterToLiterFormatConverter x:Key="NanoLiterToLiterFormatConverter"/>
+
+ <ResourceDictionary x:Key="SelectAllTextBoxResource">
+ <Style TargetType="TextBox">
+ <EventSetter Event="GotFocus" Handler="TextBox_GotFocus"></EventSetter>
+ <EventSetter Event="MouseDown" Handler="TextBox_PreviewMouseUp"></EventSetter>
+ </Style>
+ </ResourceDictionary>
+
+ <Style TargetType="{x:Type TextBlock}" x:Key="WrapText">
+ <Setter Property="TextWrapping" Value="Wrap"/>
+ </Style>
+
+ <Style TargetType="lvc:PieSeries">
+ <Setter Property="Stroke" Value="#99F9F9F9"></Setter>
+ <Setter Property="StrokeThickness" Value="2"/>
+ <Setter Property="Foreground" Value="#FF1C1C1F" />
+ </Style>
+ <Style TargetType="lvc:PieChart">
+ <Setter Property="Background" Value="Transparent"/>
+ <Setter Property="LegendLocation" Value="None"/>
+ </Style>
+
+ <DataTemplate x:Key="PopUpDataTemplate">
+ <CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}">
+ <CheckBox.Content>
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data}"></TextBlock>
+ </CheckBox.Content>
+ </CheckBox>
+ </DataTemplate>
+
+ <DataTemplate x:Key="PopUpSNDataTemplate">
+ <CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}" >
+ <CheckBox.Content>
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data.SerialNumber}" ToolTip="{Binding Data.SerialNumber}" FontFamily="{StaticResource FontName}"></TextBlock>
+ </CheckBox.Content>
+ </CheckBox>
+ </DataTemplate>
+
+ <DataTemplate x:Key="PopupBoolDataTemplate">
+ <CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}">
+ <CheckBox.Content>
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data, Converter={StaticResource BooleanToYesNoConverter}}"/>
+ </CheckBox.Content>
+ </CheckBox>
+ </DataTemplate>
+
+ <DataTemplate x:Key="PopupThreadDataTemplate">
+ <CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}" >
+ <CheckBox.Content>
+ <TextBlock Margin="5 0 5 0" VerticalAlignment="Center" Text="{Binding Data.Name}" ToolTip="{Binding Data.Name}" FontFamily="{StaticResource FontName}" FontSize="11"></TextBlock>
+ </CheckBox.Content>
+ </CheckBox>
+ </DataTemplate>
+
+
+ <Style x:Key="{x:Type ToolTip}" TargetType="{x:Type ToolTip}" BasedOn="{StaticResource MaterialDesignToolTip}">
+ <Setter Property="Background" Value="{StaticResource Logging.Background}" />
+ <Setter Property="Foreground" Value="{StaticResource MainWindow.Foreground}" />
+ </Style>
+
+ </UserControl.Resources>
+
+ <Grid IsEnabled="{Binding IsFree}" >
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="3*"/>
+ <ColumnDefinition Width="1*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid Grid.Row="0" Background="{StaticResource WhiteBackgroundBrush}" Width="Auto" Margin="20 0 0 1" >
+ <Border Padding="14 14 12 14" BorderBrush="DimGray" BorderThickness="0" Background="{StaticResource Logging.Background}" HorizontalAlignment="Stretch" CornerRadius="2" >
+ <Border.Effect>
+ <DropShadowEffect ShadowDepth="4" BlurRadius="10" Opacity="0.5"/>
+ </Border.Effect>
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+
+ <Grid >
+ <Grid.RowDefinitions>
+ <RowDefinition Height="1*"/>
+ <RowDefinition Height="1*"/>
+ </Grid.RowDefinitions>
+ <StackPanel Orientation="Horizontal" Grid.Row="0">
+ <StackPanel Margin="10 5 0 0" Orientation="Vertical" HorizontalAlignment="Center">
+ <TextBlock Text="Machine:" VerticalAlignment="Center" FontSize="11"></TextBlock>
+ <ToggleButton Width="140" Margin="0 10 0 0" x:Name="selectMachineButton" HorizontalAlignment="Left" FontSize="16" VerticalAlignment="Center">
+ <ToggleButton.Template>
+ <ControlTemplate>
+ <Grid>
+ <Border CornerRadius="3" BorderBrush="{StaticResource borderBrush}" BorderThickness="1" TextElement.Foreground="Black" Height="24">
+ <DockPanel>
+ <Button x:Name="selectMachineButton" Width="18" Padding="0" Height="16" DockPanel.Dock="Right" BorderBrush="{x:Null}" HorizontalAlignment="Left" Click="Button_Click" Style="{StaticResource MaterialDesignFlatButton}" Foreground="{StaticResource MainWindow.Foreground}">
+ <materialDesign:PackIcon Width="16" Height="16" Kind="ChevronDown" VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" HorizontalAlignment="Right"/>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" FontSize="11" Margin="5">
+ <TextBlock.Style>
+ <Style TargetType="{x:Type TextBlock}">
+ <Setter Property="Text" Value="{Binding SelectedMachines.SynchedSource.Count, StringFormat={}Selected Machines({0})}">
+ </Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding SelectedMachines.SynchedSource.Count}" Value="0">
+ <Setter Property="Text" Value="All machines"/>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ </TextBlock>
+ </DockPanel>
+ </Border>
+ <Popup AllowsTransparency="True" StaysOpen="False" IsOpen="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=IsChecked }">
+ <Border Padding="3" CornerRadius="0 0 3 3" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=Width}" Margin="5" Background="#F6F6F6" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}" >
+ <Border.Effect>
+ <DropShadowEffect Opacity="0.2" />
+ </Border.Effect>
+ <ScrollViewer MaxHeight="600" Background="#F6F6F6" >
+ <ItemsControl ItemsSource="{Binding SelectedMachines}" Foreground="{StaticResource MainWindow.Foreground}" ItemTemplate="{StaticResource PopUpSNDataTemplate}"/>
+ </ScrollViewer>
+ </Border>
+ </Popup>
+ </Grid>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
+ </StackPanel>
+
+ <StackPanel Margin="50 10 0 0" HorizontalAlignment="Center">
+ <TextBlock FontSize="11">Start Date:</TextBlock>
+ <DatePicker x:Name="startdatePicker" Margin="0 5 0 0" SelectedDate="{Binding StartSelectedDate}" materialDesign:HintAssist.Hint="Pick start date" Width="130" VerticalAlignment="Center" FontSize="11" />
+ </StackPanel>
+ <StackPanel Margin="50 10 0 0" HorizontalAlignment="Center">
+ <TextBlock FontSize="11">End Date:</TextBlock>
+ <DatePicker x:Name="endDatePicker" Margin="0 5 0 0" SelectedDate="{Binding EndSelectedDate}" materialDesign:HintAssist.Hint="Pick end date" Width="130" VerticalAlignment="Center" FontSize="11" />
+ </StackPanel>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" Grid.Row="1">
+ <StackPanel Margin="10 10 0 0" Orientation="Vertical" HorizontalAlignment="Center">
+ <TextBlock Text="Job Name:" VerticalAlignment="Center" FontSize="11"></TextBlock>
+ <autoComplete:AutoCompleteTextBox Margin="0 10 0 0" Provider="{Binding JobsProvider}" Width="140" FontSize="11" LoadingContent="Loading..." SelectedItem="{Binding SelectedJob,Mode=TwoWay}" materialDesign:HintAssist.Hint="All" DisplayMember="Name" materialDesign:HintAssist.IsFloating="False">
+ <autoComplete:AutoCompleteTextBox.ItemTemplate>
+ <DataTemplate>
+ <StackPanel>
+ <TextBlock Text="{Binding Name}" FontWeight="Bold" FontStyle="Italic"></TextBlock>
+ </StackPanel>
+ </DataTemplate>
+ </autoComplete:AutoCompleteTextBox.ItemTemplate>
+ </autoComplete:AutoCompleteTextBox>
+ </StackPanel>
+ <StackPanel Margin="50 10 0 0" Orientation="Vertical" HorizontalAlignment="Center">
+ <TextBlock Text="Source:" VerticalAlignment="Center" FontSize="11"></TextBlock>
+ <ToggleButton Width="130" Height="24" Margin="0 10 0 0" x:Name="selectJobRunSources" HorizontalAlignment="Left" FontSize="16" VerticalAlignment="Center">
+ <ToggleButton.Template>
+ <ControlTemplate>
+ <Grid>
+ <Border CornerRadius="3" BorderBrush="{StaticResource borderBrush}" BorderThickness="1" TextElement.Foreground="Black" >
+ <DockPanel>
+ <Button x:Name="jobRunSourcesButton" Width="18" Padding="0" Height="16" DockPanel.Dock="Right" BorderBrush="{x:Null}" HorizontalAlignment="Left" Click="JobRunSourcesButton_Click" Style="{StaticResource MaterialDesignFlatButton}" Foreground="{StaticResource MainWindow.Foreground}">
+ <materialDesign:PackIcon Width="16" Height="16" Kind="ChevronDown" VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" HorizontalAlignment="Right"/>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" FontSize="11" Margin="5" Text="{Binding JobRunSelectedSources.SynchedSource, Converter={StaticResource CollectionConverter}}"/>
+ </DockPanel>
+ </Border>
+ <Popup AllowsTransparency="True" StaysOpen="False" IsOpen="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=IsChecked }">
+ <Border Padding="3" CornerRadius="0 0 3 3" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=Width}" Margin="5" Background="#F6F6F6" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}" >
+ <Border.Effect>
+ <DropShadowEffect Opacity="0.2" />
+ </Border.Effect>
+ <ItemsControl ItemsSource="{Binding JobRunSelectedSources}" Foreground="{StaticResource MainWindow.Foreground}" ItemTemplate="{StaticResource PopUpDataTemplate}"/>
+
+ </Border>
+ </Popup>
+ </Grid>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
+ </StackPanel>
+ <StackPanel Margin="50 10 0 0" Orientation="Vertical" HorizontalAlignment="Center">
+ <TextBlock Text="Gradient:" VerticalAlignment="Center" FontSize="11"></TextBlock>
+ <ToggleButton Height="24" Width="130" Margin="0 10 0 0" x:Name="selectIsGradient" HorizontalAlignment="Left" FontSize="16" VerticalAlignment="Center">
+ <ToggleButton.Template>
+ <ControlTemplate>
+ <Grid>
+ <Border CornerRadius="3" BorderBrush="{StaticResource borderBrush}" BorderThickness="1" TextElement.Foreground="Black" >
+ <DockPanel>
+ <Button x:Name="isGradientButton" Width="18" Padding="0" Height="16" DockPanel.Dock="Right" BorderBrush="{x:Null}" HorizontalAlignment="Left" Click="IsGradientButton_Click" Style="{StaticResource MaterialDesignFlatButton}" Foreground="{StaticResource MainWindow.Foreground}">
+ <materialDesign:PackIcon Width="16" Height="16" Kind="ChevronDown" VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" HorizontalAlignment="Right"/>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" FontSize="11" Margin="5 0 2 0">
+ <Run Text="{Binding IsGradientSelection.SynchedSource, Converter={StaticResource CollectionConverter}}"></Run>
+ </TextBlock>
+ </DockPanel>
+ </Border>
+ <Popup AllowsTransparency="True" StaysOpen="False" IsOpen="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=IsChecked }">
+ <Border Padding="3" CornerRadius="0 0 3 3" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=Width}" Margin="5" Background="#F6F6F6" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}">
+ <Border.Effect>
+ <DropShadowEffect Opacity="0.2" />
+ </Border.Effect>
+ <ItemsControl ItemsSource="{Binding IsGradientSelection}" Foreground="{StaticResource MainWindow.Foreground}" ItemTemplate="{StaticResource PopupBoolDataTemplate}"/>
+
+ </Border>
+ </Popup>
+ </Grid>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
+ </StackPanel>
+ <StackPanel Margin="40 10 0 0" Orientation="Vertical" HorizontalAlignment="Center">
+ <TextBlock Text="Length:" VerticalAlignment="Center" FontSize="11"></TextBlock>
+ <Border BorderThickness="1" CornerRadius="3" BorderBrush="{StaticResource borderBrush}" Margin="0 10 0 0" Height="24" Padding="10 0">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Text="{Binding LengthLowerValue, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" FontSize="11" Width="30"></TextBlock>
+ <mahapps:RangeSlider Focusable="True" Height="40" Margin="5 5 5 5" Minimum="0" Maximum="5000" Width="140" ExtendedMode="True"
+ LowerValue="{Binding LengthLowerValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+ UpperValue="{Binding LengthUpperValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+ VerticalAlignment="Center" IsSnapToTickEnabled="True" FontSize="8"/>
+ <TextBlock Text="{Binding LengthUpperValue}" VerticalAlignment="Center" FontSize="11" Width="30"></TextBlock>
+ </StackPanel>
+ </Border>
+ </StackPanel>
+ <StackPanel Margin="40 10 0 0" Orientation="Vertical" HorizontalAlignment="Center">
+ <TextBlock Text="Status:" VerticalAlignment="Center" FontSize="11"></TextBlock>
+ <ToggleButton Height="24" Width="170" Margin="0 10 0 0" x:Name="selectJobRunStatus" HorizontalAlignment="Left" FontSize="16" VerticalAlignment="Center">
+ <ToggleButton.Template>
+ <ControlTemplate>
+ <Grid>
+ <Border CornerRadius="3" BorderBrush="{StaticResource borderBrush}" BorderThickness="1" TextElement.Foreground="Black" >
+ <DockPanel>
+ <Button x:Name="jobRunStatusButton" Width="18" Padding="0" Height="16" DockPanel.Dock="Right" BorderBrush="{x:Null}" HorizontalAlignment="Left" Click="JobRunStatusButton_Click" Style="{StaticResource MaterialDesignFlatButton}" Foreground="{StaticResource MainWindow.Foreground}">
+ <materialDesign:PackIcon Width="16" Height="16" Kind="ChevronDown" VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" HorizontalAlignment="Right"/>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" FontSize="11" Margin="5" Text="{Binding JobRunSelectedStatuses.SynchedSource, Converter={StaticResource CollectionConverter}}"/>
+ </DockPanel>
+ </Border>
+ <Popup AllowsTransparency="True" StaysOpen="False" IsOpen="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=IsChecked }">
+ <Border Padding="3" CornerRadius="0 0 3 3" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=Width}" Margin="5" Background="#F6F6F6" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}" >
+ <Border.Effect>
+ <DropShadowEffect Opacity="0.2" />
+ </Border.Effect>
+ <ItemsControl ItemsSource="{Binding JobRunSelectedStatuses}" Foreground="{StaticResource MainWindow.Foreground}" ItemTemplate="{StaticResource PopUpDataTemplate}"/>
+ </Border>
+ </Popup>
+ </Grid>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
+ </StackPanel>
+ <StackPanel Margin="40 10 0 0" Orientation="Vertical" HorizontalAlignment="Center">
+ <TextBlock Text="Threads:" VerticalAlignment="Center" FontSize="11"></TextBlock>
+ <ToggleButton Width="140" Margin="0 10 0 0" x:Name="selectThreadsButton" HorizontalAlignment="Left" FontSize="16" VerticalAlignment="Center">
+ <ToggleButton.Template>
+ <ControlTemplate>
+ <Grid>
+ <Border CornerRadius="3" BorderBrush="{StaticResource borderBrush}" BorderThickness="1" TextElement.Foreground="Black" Height="24">
+ <DockPanel>
+ <Button x:Name="selectThreadButton" Width="18" Padding="0" Height="16" DockPanel.Dock="Right" BorderBrush="{x:Null}" HorizontalAlignment="Left" Click="SelectMachineButton_Click" Style="{StaticResource MaterialDesignFlatButton}" Foreground="{StaticResource MainWindow.Foreground}">
+ <materialDesign:PackIcon Width="16" Height="16" Kind="ChevronDown" VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" HorizontalAlignment="Right"/>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" FontSize="11" Margin="5" >
+ <TextBlock.Style>
+ <Style TargetType="{x:Type TextBlock}">
+ <Setter Property="Text" Value="{Binding SelectedThreads.SynchedSource.Count, StringFormat={}Selected Threads({0})}">
+ </Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding SelectedThreads.SynchedSource.Count}" Value="0">
+ <Setter Property="Text" Value="All threads"/>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ </TextBlock>
+ </DockPanel>
+ </Border>
+ <Popup AllowsTransparency="True" StaysOpen="False" IsOpen="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=IsChecked }">
+ <Border Padding="3" CornerRadius="0 0 3 3" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=Width}" Margin="5" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}" >
+ <Border.Effect>
+ <DropShadowEffect Opacity="0.2" />
+ </Border.Effect>
+ <ScrollViewer MaxHeight="600" Background="#F6F6F6">
+ <ItemsControl ItemsSource="{Binding SelectedThreads}" Foreground="{StaticResource MainWindow.Foreground}" ItemTemplate="{StaticResource PopupThreadDataTemplate}"/>
+
+ </ScrollViewer>
+ </Border>
+ </Popup>
+ </Grid>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
+ </StackPanel>
+ </StackPanel>
+ </Grid>
+ <Button Grid.Column="1" HorizontalAlignment="Right" Command="{Binding LoadJobRunsCommand}" Margin="0 0 10 0" Padding="70 15" Height="Auto" VerticalAlignment="Center">RUN</Button>
+ </Grid>
+ </Border>
+ </Grid>
+
+ <DataGrid x:Name="ItemsGrid" GridLinesVisibility="None" Grid.Row="1" Margin="20 0 0 10" SelectionMode="Single" SelectionUnit="FullRow" BorderBrush="{StaticResource borderBrush}" IsReadOnly="True" BorderThickness="1" RowHeight="80"
+ Background="{StaticResource TransparentBackgroundBrush}" AlternatingRowBackground="{StaticResource Transparent200}" AutoGenerateColumns="False" CanUserReorderColumns="False"
+ CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{Binding JobRuns}" HorizontalScrollBarVisibility="Disabled" CanUserResizeColumns="False" CanUserResizeRows="False"
+ SelectedItem="{Binding SelectedJobRun}" CanUserSortColumns="True" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" FontSize="11">
+
+ <DataGrid.Resources>
+ <Style TargetType="DataGridColumnHeader" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
+ <Setter Property="HorizontalAlignment" Value="Left"></Setter>
+ <Setter Property="HorizontalContentAlignment" Value="Left"></Setter>
+ <Setter Property="Padding" Value="0 8 0 8"></Setter>
+ <Setter Property="Margin" Value="0 0 0 0"></Setter>
+ <Setter Property="FontWeight" Value="SemiBold"/>
+ </Style>
+ </DataGrid.Resources>
+
+ <DataGrid.CellStyle>
+ <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
+ <Setter Property="VerticalContentAlignment" Value="Center"></Setter>
+ <Setter Property="VerticalAlignment" Value="Center"/>
+ <Setter Property="HorizontalAlignment" Value="Left"/>
+ <Setter Property="Margin" Value="0 0 10 0"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type DataGridCell}">
+ <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGrid.CellStyle>
+ <DataGrid.RowStyle>
+ <Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
+ <Setter Property="BorderThickness" Value="0 0 0 1"/>
+ <Setter Property="BorderBrush" Value="LightGray"/>
+ <Style.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" />
+ <Setter Property="Cursor" Value="Hand"></Setter>
+ </Trigger>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ </Trigger>
+ <Trigger Property="IsFocused" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGrid.RowStyle>
+
+ <DataGrid.Columns>
+ <DataGridTemplateColumn Header="" Width="50">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <materialDesign:PackIcon Width="24" Height="24" Margin="8 -5 0 0">
+ <materialDesign:PackIcon.Style>
+ <Style TargetType="materialDesign:PackIcon">
+ <Setter Property="Kind" Value="Check"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding JobRun.JobRunStatus}" Value="Completed">
+ <Setter Property="Kind" Value="Check"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource GreenOpenFileBrush}"></Setter>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding JobRun.JobRunStatus}" Value="Aborted">
+ <Setter Property="Kind" Value="Alert"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource OrangeBrush}"></Setter>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding JobRun.JobRunStatus}" Value="Failed">
+ <Setter Property="Kind" Value="AlertOctagon"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource RedBrush100}"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </materialDesign:PackIcon.Style>
+ </materialDesign:PackIcon>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ <DataGridTextColumn Header="ID" Binding="{Binding JobRun.ID}" Width="50" ElementStyle="{StaticResource WrapText}"/>
+ <DataGridTextColumn Header="Machine" Binding="{Binding Machine.SerialNumber}" Width="100" ></DataGridTextColumn>
+ <DataGridTextColumn Header="User" Binding="{Binding User.Contact.FullName}" Width="100" ElementStyle="{StaticResource WrapText}" />
+ <DataGridTextColumn Header="Job Name" Binding="{Binding JobRun.JobName}" Width="100" ElementStyle="{StaticResource WrapText}"/>
+ <DataGridTextColumn Header="Thread" Binding="{Binding Rml.Name}" Width="80" ElementStyle="{StaticResource WrapText}"/>
+ <DataGridTextColumn Header="Length" Binding="{Binding JobRun.JobLength, StringFormat={}{0:0.00}}" Width="60" />
+ <DataGridTextColumn Header="Source" Binding="{Binding JobRun.Source, Converter={StaticResource EnumToDescriptionConverter}}" Width="60" />
+ <DataGridTextColumn Header="Upload &#10;Duration" Binding="{Binding UploadDuration, Converter={StaticResource DateTimeToStringFormatConverter}, FallbackValue='N/A',TargetNullValue='N/A'}" Width="80"/>
+ <DataGridTextColumn Header="Heating &#10;Duration" Binding="{Binding HeatingDuration, Converter={StaticResource DateTimeToStringFormatConverter}, FallbackValue='N/A',TargetNullValue='N/A'}" Width="80" />
+ <DataGridTextColumn Header="Start Time" Binding="{Binding JobRun.ActualStartDate, Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" Width="95" />
+ <DataGridTextColumn Header="IsGradient" Binding="{Binding JobRun.IsGradient}" Width="70" />
+ <DataGridTextColumn Header="GR" Binding="{Binding JobRun.GradientResolutionCm}" Width="30" />
+ <DataGridTextColumn Header="Status" Binding="{Binding JobRun.JobRunStatus, Converter={StaticResource EnumToDescriptionConverter}}" Width="70"/>
+ <DataGridTextColumn Header="End Time" Binding="{Binding JobRun.EndDate, Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" Width="95" />
+ <DataGridTextColumn Header="End &#10;Position" Binding="{Binding JobRun.EndPosition, StringFormat={}{0:0.00}}" Width="70" />
+ <DataGridTemplateColumn Header="Liquid Quantities" Width="1*">
+ <DataGridTemplateColumn.CellStyle>
+ <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
+ <Setter Property="VerticalContentAlignment" Value="Center"></Setter>
+ <Setter Property="VerticalAlignment" Value="Center"/>
+ <Setter Property="HorizontalAlignment" Value="Stretch"/>
+ <Setter Property="Margin" Value="0 0 10 0"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type DataGridCell}">
+ <ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGridTemplateColumn.CellStyle>
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="1*"/>
+ <RowDefinition Height="20"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="1*" MaxWidth="200"/>
+ </Grid.ColumnDefinitions>
+ <ItemsControl ItemsSource="{Binding JobRun.LiquidQuantities,Mode=OneWay}" Margin="0 0 0 0" Height="70">
+ <ItemsControl.ItemContainerStyle>
+ <Style TargetType="ContentPresenter">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Quantity}" Value="0">
+ <Setter Property="Visibility" Value="Collapsed"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </ItemsControl.ItemContainerStyle>
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <StackPanel Orientation="Horizontal" IsItemsHost="True"></StackPanel>
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <DockPanel ToolTip="{Binding Quantity}" ToolTipService.Placement="Center" ToolTipService.VerticalOffset="10">
+ <Grid DockPanel.Dock="Top" Height="40" Margin="0 5 8 0" Width="16">
+ <Border x:Name="LiquidTypeBorder" BorderThickness="1" BorderBrush="{StaticResource borderBrush}" CornerRadius="2">
+ <Canvas x:Name="LiquidCanvas" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0" ClipToBounds="True" ToolTip="{Binding Quantity}" ToolTipService.Placement="Left" ToolTipService.VerticalOffset="10">
+ <Border Height="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualHeight }" Width="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth }">
+ <Border.Background>
+ <SolidColorBrush Color="{Binding LiquidType,Converter={StaticResource LiquidTypeToColorConverter}}" />
+ </Border.Background>
+ <Border.Style>
+ <Style>
+ <Setter Property="Canvas.Top" >
+ <Setter.Value>
+ <MultiBinding Converter="{StaticResource MidTankLevelToElementHeightConverter}">
+ <Binding RelativeSource="{RelativeSource Self}" Path="ActualHeight" />
+ <Binding Path="Quantity" />
+ </MultiBinding>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Border.Style>
+ </Border>
+ </Canvas>
+ </Border>
+ </Grid>
+ <TextBlock DockPanel.Dock="Bottom" FontSize="9" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0 0 10 0" Text="{Binding LiquidType,Converter={StaticResource StringToFirstLetterConverter}}" Foreground="Gray"/>
+ </DockPanel>
+
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ <Border Grid.Row="1" Grid.Column="0" Background="Transparent" HorizontalAlignment="Stretch" Height="8" BorderThickness="1" BorderBrush="{StaticResource borderBrush}">
+ <Rectangle Margin="0 0 -1 0" Fill="{StaticResource AccentColorBrush}" HorizontalAlignment="Left" VerticalAlignment="Stretch" ToolTip="{Binding JobRun.EndPosition}">
+ <Rectangle.Width>
+ <MultiBinding Converter="{StaticResource JobLengthConverter}">
+ <Binding Path="JobRun.JobLength" />
+ <Binding Path="JobRun.EndPosition"/>
+ <Binding Path="ActualWidth" RelativeSource="{RelativeSource AncestorType=Border}"/>
+ </MultiBinding>
+ </Rectangle.Width>
+ </Rectangle>
+ </Border>
+ </Grid>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ </DataGrid.Columns>
+ </DataGrid>
+ <Border Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Margin="20, 0, 20, 20" BorderBrush="{StaticResource borderBrush}" Background="{StaticResource TransparentBackgroundBrush}" BorderThickness="1">
+
+ <StackPanel>
+ <TextBlock Margin="10" Text="{Binding SelectedJobName}"></TextBlock>
+ </StackPanel>
+ </Border>
+ <Border Grid.Row="2" Margin="20, 0, 0, 20" Height="200" BorderBrush="{StaticResource borderBrush}" Background="{StaticResource TransparentBackgroundBrush}" BorderThickness="1">
+ <Grid >
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="2"/>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="2"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Border Grid.Column="0" BorderBrush="{StaticResource borderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <StackPanel Orientation="Vertical" Margin="5">
+ <ItemsControl ItemsSource="{Binding StatisticsValueCollection.StatisticsCollection}">
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <StackPanel Orientation="Horizontal" Margin="0 3">
+ <TextBlock Text="{Binding Name}" FontWeight="SemiBold"/>
+ <TextBlock Text=": "/>
+ <TextBlock Text="{Binding Value, StringFormat={}{0:#,0.##}}"/>
+ <TextBlock Text="{Binding Unit}"/>
+ </StackPanel>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ <TextBlock Visibility="Collapsed" Margin="0 10 0 0" Text="Total Thread Consumption per thread:" FontWeight="SemiBold">
+ <TextBlock.Style>
+ <Style TargetType="TextBlock">
+ <Setter Property="Visibility" Value="Visible" />
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding StatisticsValueCollection.ThreadConsumptionPerThreadCollection.Count}" Value="0">
+ <Setter Property="Visibility" Value="Collapsed" />
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ </TextBlock>
+ <ItemsControl Visibility="Collapsed" ItemsSource="{Binding StatisticsValueCollection.ThreadConsumptionPerThreadCollection}">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <UniformGrid Rows="3" />
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.Resources>
+ <DataTemplate DataType="{x:Type model:StatisticsValue}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Text="{Binding Name}" FontWeight="SemiBold"/>
+ <TextBlock Text=": "/>
+ <TextBlock Text="{Binding Value, StringFormat={}{0:0.0}}"/>
+ <TextBlock Text="{Binding Unit}"/>
+ </StackPanel>
+ </DataTemplate>
+ <DataTemplate DataType="{x:Type model:MoreValue}">
+ <Border BorderThickness="0">
+ <TextBlock Text="{Binding Text}" Tag="{Binding Path=DataContext.StatisticsValueCollection.ThreadConsumptionPerThread, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}}" HorizontalAlignment="Left" VerticalAlignment="Center" >
+ <TextBlock.ToolTip >
+ <ToolTip DataContext="{Binding RelativeSource={RelativeSource Self},Path=PlacementTarget.Tag}" Placement="Right" Background="{StaticResource Logging.Background}">
+ <Border CornerRadius="5">
+ <ItemsControl ItemsSource="{Binding }">
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <StackPanel Orientation="Horizontal" Margin="2">
+ <TextBlock Margin="5 0 0 0" Text="{Binding Name}" FontWeight="SemiBold"/>
+ <TextBlock Text=": "/>
+ <TextBlock Text="{Binding Value, StringFormat={}{0:0.0}}"/>
+ <TextBlock Text="{Binding Unit}"/>
+ </StackPanel>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </Border>
+ </ToolTip>
+ </TextBlock.ToolTip>
+ </TextBlock>
+ </Border>
+ </DataTemplate>
+ </ItemsControl.Resources>
+ </ItemsControl>
+ </StackPanel>
+ </Border>
+ <Border Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="2" Background="{StaticResource borderBrush}" Margin="0 4" Visibility="Visible"></Border>
+ <Border Grid.Column="2" BorderBrush="{StaticResource borderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <DockPanel>
+ <UniformGrid Columns="3">
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="12" FontWeight="Bold" HorizontalAlignment="Center" Padding="2" Text="PPC/MS"></TextBlock>
+ <lvc:PieChart Series="{Binding StatisticsValueCollection.PieJobSource.SeriesCollection}" >
+ <lvc:PieChart.DataTooltip>
+ <tooltips:PieChartTooltipControl Visibility="Visible" />
+ </lvc:PieChart.DataTooltip>
+ </lvc:PieChart>
+ </DockPanel>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="12" FontWeight="Bold" HorizontalAlignment="Center" Padding="2" Text="Failed/Aborted/Completed"></TextBlock>
+ <lvc:PieChart Series="{Binding StatisticsValueCollection.PieJobRunStatus.SeriesCollection}">
+ <lvc:PieChart.DataTooltip>
+ <tooltips:PieChartTooltipControl Visibility="Visible" />
+ </lvc:PieChart.DataTooltip>
+ </lvc:PieChart>
+ </DockPanel>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="12" FontWeight="Bold" HorizontalAlignment="Center" Padding="2" Text="Gradient/Solid"></TextBlock>
+ <lvc:PieChart Series="{Binding StatisticsValueCollection.PieGradientSolid.SeriesCollection}" >
+ <lvc:PieChart.DataTooltip>
+ <tooltips:PieChartTooltipControl Visibility="Visible" />
+ </lvc:PieChart.DataTooltip>
+ </lvc:PieChart>
+ </DockPanel>
+ </UniformGrid>
+ </DockPanel>
+ </Border>
+
+ <Border Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="2" Background="{StaticResource borderBrush}" Margin="0 6" CornerRadius="1"/>
+
+ <Border Grid.Column="4" BorderBrush="{StaticResource borderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <DockPanel>
+ <ItemsControl DockPanel.Dock="Top" ItemsSource="{Binding StatisticsValueCollection.LiquidQuantities}">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <UniformGrid Columns="3"/>
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <StackPanel Orientation="Horizontal" Margin="4">
+ <Ellipse Width="30" Height="30">
+ <Ellipse.Fill>
+ <SolidColorBrush Color="{Binding LiquidType,Converter={StaticResource LiquidTypeToColorConverter}}" />
+ </Ellipse.Fill>
+ </Ellipse>
+ <StackPanel Orientation="Vertical" Margin="4">
+ <TextBlock Text="{Binding LiquidType,Converter={StaticResource EnumToDescriptionConverter}}" FontWeight="SemiBold"></TextBlock>
+ <TextBlock >
+ <Run Text="{Binding Quantity, Converter={StaticResource NanoLiterToLiterFormatConverter}}"></Run>
+ <Run Text=" liters"></Run>
+ </TextBlock>
+ </StackPanel>
+ </StackPanel>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ <TextBlock DockPanel.Dock="Bottom" Margin="4 10 0 0 ">
+ <Run Text="Total liquid quantities for all: " FontWeight="SemiBold"/>
+ <Run Text="{Binding StatisticsValueCollection.TotalLiquidQuantities, Converter={StaticResource NanoLiterToLiterFormatConverter}}"></Run>
+ <Run Text=" liters"></Run>
+ <TextBlock.Style>
+ <Style TargetType="TextBlock">
+ <Setter Property="Visibility" Value="Visible" />
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding StatisticsValueCollection.LiquidQuantities.Count}" Value="0">
+ <Setter Property="Visibility" Value="Collapsed" />
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ </TextBlock>
+ </DockPanel>
+ </Border>
+ </Grid>
+ </Border>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs
new file mode 100644
index 000000000..2b3ed79ca
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs
@@ -0,0 +1,86 @@
+using LiveCharts;
+using LiveCharts.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.MachineStudio.Statistics.Views
+{
+ /// <summary>
+ /// Interaction logic for JobRunsView.xaml
+ /// </summary>
+ public partial class JobRunsView : UserControl
+ {
+ private int _lastSelectedGridItemIndex;
+ public JobRunsView()
+ {
+ InitializeComponent();
+ _lastSelectedGridItemIndex = -1;
+ }
+ private void Button_Click(object sender, RoutedEventArgs e)
+ {
+ selectMachineButton.IsChecked = true;
+ e.Handled = true;
+ }
+
+ private void JobRunSourcesButton_Click(object sender, RoutedEventArgs e)
+ {
+ selectJobRunSources.IsChecked = true;
+ e.Handled = true;
+ }
+ private void IsGradientButton_Click(object sender, RoutedEventArgs e)
+ {
+ selectIsGradient.IsChecked = true;
+ e.Handled = true;
+ }
+ private void JobRunStatusButton_Click(object sender, RoutedEventArgs e)
+ {
+ selectJobRunStatus.IsChecked = true;
+ e.Handled = true;
+ }
+
+ private async void TextBox_GotFocus(object sender, RoutedEventArgs e)
+ {
+ await Task.Delay(200);
+ TextBox txtBox = sender as TextBox;
+ txtBox.SelectAll();
+ }
+
+ private void TextBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ e.Handled = true;
+ }
+
+ private void SelectMachineButton_Click(object sender, RoutedEventArgs e)
+ {
+ selectThreadsButton.IsChecked = true;
+ e.Handled = true;
+ }
+
+ private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ DataGrid dataGrid = sender as DataGrid;
+ _lastSelectedGridItemIndex = -1;
+ if (e.AddedItems != null && e.AddedItems.Count > 0)
+ {
+ DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromItem(e.AddedItems[0]);
+ if (row != null)
+ {
+ _lastSelectedGridItemIndex = row.GetIndex();
+ }
+ }
+ }
+
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml
index 55804c7b3..170d3276a 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml
@@ -11,100 +11,28 @@
xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
mc:Ignorable="d"
d:DesignHeight="1080" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
- <Grid IsEnabled="{Binding IsFree}">
+ <Grid>
<Grid.RowDefinitions>
- <RowDefinition Height="80"/>
- <RowDefinition Height="337*"/>
+ <RowDefinition Height="1*"/>
+ <RowDefinition Height="20"/>
</Grid.RowDefinitions>
-
- <StackPanel Margin="60 20 0 0" VerticalAlignment="Center" HorizontalAlignment="Left" Orientation="Horizontal">
- <StackPanel>
- <TextBlock FontSize="10">Start Date:</TextBlock>
- <DatePicker DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" SelectedDate="{Binding StartDate}" materialDesign:HintAssist.Hint="Pick start date" Width="200" VerticalAlignment="Bottom" FontSize="16"></DatePicker>
- </StackPanel>
-
- <StackPanel Margin="40 0 0 0">
- <TextBlock FontSize="10">End Date:</TextBlock>
- <DatePicker DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" SelectedDate="{Binding EndDate}" materialDesign:HintAssist.Hint="Pick end date" Width="200" VerticalAlignment="Bottom" FontSize="16"></DatePicker>
- </StackPanel>
- </StackPanel>
-
- <UniformGrid Columns="3" Margin="50 20 50 50" Rows="2" Grid.Row="1">
- <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
- <DockPanel>
- <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding TimelineJobStatusSeries.Title}"></TextBlock>
- <lvc:CartesianChart Series="{Binding TimelineJobStatusSeries.SeriesCollection}" LegendLocation="Bottom" SeriesColors="{Binding TimelineJobStatusSeries.SeriesColors}">
- <lvc:CartesianChart.DataTooltip>
- <lvc:DefaultTooltip BulletSize="20" Background="{StaticResource TransparentBackgroundBrush450}" Foreground="{StaticResource Dialog.Foreground}"/>
- </lvc:CartesianChart.DataTooltip>
- <lvc:CartesianChart.AxisX>
- <lvc:Axis Title="{Binding TimelineJobStatusSeries.LabelsTitle}" Labels="{Binding TimelineJobStatusSeries.Labels}" Foreground="{StaticResource DarkGrayBrush200}">
- <lvc:Axis.Separator>
- <lvc:Separator Stroke="#A5A5A5" />
- </lvc:Axis.Separator>
- </lvc:Axis>
- </lvc:CartesianChart.AxisX>
- <lvc:CartesianChart.AxisY>
- <lvc:Axis Title="{Binding TimelineJobStatusSeries.ChartTitle}" MinValue="0" Foreground="{StaticResource DarkGrayBrush200}" >
- <lvc:Axis.Separator>
- <lvc:Separator Stroke="#B0B0B0" />
- </lvc:Axis.Separator>
- </lvc:Axis>
- </lvc:CartesianChart.AxisY>
- </lvc:CartesianChart>
- </DockPanel>
- </Border>
-
- <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
- <DockPanel>
- <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding PieJobFailedReasons.Title}"></TextBlock>
- <UniformGrid Columns="2">
- <lvc:PieChart DataHover="PieChart_DataHover" Series="{Binding PieJobFailedReasons.SeriesCollection}" LegendLocation="None" SeriesColors="{Binding PieJobFailedReasons.SeriesColors}" Background="Transparent">
- <lvc:PieChart.Resources>
- <Style TargetType="lvc:PieSeries">
- <Setter Property="Stroke" Value="#99F9F9F9"></Setter>
- <Setter Property="StrokeThickness" Value="2"/>
- </Style>
- </lvc:PieChart.Resources>
- <lvc:PieChart.DataTooltip>
- <tooltips:PieChartTooltipControl Visibility="Hidden" />
- </lvc:PieChart.DataTooltip>
- </lvc:PieChart>
-
- <TextBlock x:Name="txtPieTitle" TextWrapping="Wrap"></TextBlock>
- </UniformGrid>
- </DockPanel>
- </Border>
-
- <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
- <DockPanel>
- <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding PrintPerWeekSeries.Title}"></TextBlock>
- <lvc:CartesianChart Series="{Binding PrintPerWeekSeries.SeriesCollection}" LegendLocation="Bottom" SeriesColors="{Binding PrintPerWeekSeries.SeriesColors}" >
- <lvc:CartesianChart.Resources>
- <Style TargetType="lvc:ColumnSeries">
- <Setter Property="Foreground" Value="{StaticResource DarkGrayBrush200}"></Setter>
- </Style>
- </lvc:CartesianChart.Resources>
- <lvc:CartesianChart.AxisX>
- <lvc:Axis Title="{Binding PrintPerWeekSeries.LabelsTitle}" Labels="{Binding PrintPerWeekSeries.Labels}" Foreground="{StaticResource DarkGrayBrush200}">
- <lvc:Axis.Separator>
- <lvc:Separator Stroke="#A5A5A5" />
- </lvc:Axis.Separator>
- </lvc:Axis>
- </lvc:CartesianChart.AxisX>
- <lvc:CartesianChart.AxisY>
- <lvc:Axis Title="{Binding PrintPerWeekSeries.ChartTitle}" MinValue="0" Foreground="{StaticResource DarkGrayBrush200}" >
- <lvc:Axis.Separator>
- <lvc:Separator Stroke="#6F6F6F" />
- </lvc:Axis.Separator>
- </lvc:Axis>
- </lvc:CartesianChart.AxisY>
- <lvc:CartesianChart.DataTooltip>
- <lvc:DefaultTooltip BulletSize="20" Background="{StaticResource TransparentBackgroundBrush450}" Foreground="{StaticResource Dialog.Foreground}"/>
- </lvc:CartesianChart.DataTooltip>
- </lvc:CartesianChart>
- </DockPanel>
- </Border>
- </UniformGrid>
+ <Grid Grid.Row="0" IsEnabled="{Binding IsFree}">
+ <TabControl Background="Transparent" Margin="0,40,0,0" x:Name="chartsTabControl" Padding="0 25 0 0">
+ <TabControl.Resources>
+ <Style TargetType="TabPanel">
+ <Setter Property="HorizontalAlignment" Value="Center"/>
+ </Style>
+ <Style TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">
+ <Setter Property="Padding" Value="20,2"></Setter>
+ </Style>
+ </TabControl.Resources>
+ <TabItem Header="STATS" Margin="-100 0 0 0 ">
+ <local:ChartsView x:Name="processParametersView" DataContext="{Binding ChartsViewVM}"/>
+ </TabItem>
+ <TabItem Header="JOB RUNS" Margin="-100 0 0 0 ">
+ <local:JobRunsView x:Name="jobRunsView" DataContext="{Binding JobRunsViewVM}"/>
+ </TabItem>
+ </TabControl>
+ </Grid>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs
index 3948c4e5a..f0d1c39a7 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs
@@ -28,10 +28,6 @@ namespace Tango.MachineStudio.Statistics.Views
InitializeComponent();
}
- private void PieChart_DataHover(object sender, ChartPoint chartPoint)
- {
- var tooltip = ((chartPoint.ChartView as PieChart).DataTooltip as Tooltips.PieChartTooltipControl).Title;
- txtPieTitle.Text = tooltip;
- }
+
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/packages.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/packages.config
index 31c5f029f..6938c8a4b 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/packages.config
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/packages.config
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.2.0" targetFramework="net461" />
+ <package id="Google.Protobuf" version="3.4.1" targetFramework="net461" />
<package id="LiveCharts" version="0.9.7" targetFramework="net461" />
<package id="LiveCharts.Wpf" version="0.9.7" targetFramework="net461" />
<package id="MahApps.Metro" version="1.5.0" targetFramework="net461" />