aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/FSE/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Software/Visual_Studio/FSE/Modules')
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj8
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs9
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/LogsViewVM.cs288
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs1
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml225
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml5
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/UpdatesView.xaml2
8 files changed, 563 insertions, 3 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
index 783dfa9fe..287273015 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
@@ -113,10 +113,14 @@
<Compile Include="PPCConsoleModule.cs" />
<Compile Include="ViewModels\ConsoleViewVM.cs" />
<Compile Include="ViewModels\FileSystemViewVM.cs" />
+ <Compile Include="ViewModels\LogsViewVM.cs" />
<Compile Include="ViewModels\MainViewVM.cs" />
<Compile Include="ViewModels\MonitoringViewVM.cs" />
<Compile Include="ViewModels\RemoteDesktopViewVM.cs" />
<Compile Include="ViewModels\UpdatesViewVM.cs" />
+ <Compile Include="Views\LogsView.xaml.cs">
+ <DependentUpon>LogsView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Views\UpdatesView.xaml.cs">
<DependentUpon>UpdatesView.xaml</DependentUpon>
</Compile>
@@ -252,6 +256,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\LogsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Views\UpdatesView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs
index 4faa72e8e..a3b800b22 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs
@@ -18,6 +18,7 @@ namespace Tango.FSE.PPCConsole
TangoIOC.Default.Register<MonitoringViewVM>();
TangoIOC.Default.Register<FileSystemViewVM>();
TangoIOC.Default.Register<UpdatesViewVM>();
+ TangoIOC.Default.Register<LogsViewVM>();
}
public static MainViewVM MainViewVM
@@ -67,5 +68,13 @@ namespace Tango.FSE.PPCConsole
return TangoIOC.Default.GetInstance<UpdatesViewVM>();
}
}
+
+ public static LogsViewVM LogsViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<LogsViewVM>();
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/LogsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/LogsViewVM.cs
new file mode 100644
index 000000000..52955e18a
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/LogsViewVM.cs
@@ -0,0 +1,288 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using Tango.Core;
+using Tango.Core.Commands;
+using Tango.Core.Helpers;
+using Tango.FSE.Common;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Dialogs;
+using Tango.FSE.Common.FileSystem;
+using Tango.FSE.Common.Logging;
+using Tango.Logging;
+using Tango.PPC.Shared.Logs;
+using Tango.SharedUI.Components;
+using static Tango.SharedUI.Controls.NavigationControl;
+
+namespace Tango.FSE.PPCConsole.ViewModels
+{
+ public class LogsViewVM : FSEViewModel, INavigationViewModel
+ {
+ private bool _loaded;
+
+ private List<RemoteLogFileModel<LogItemBase>> _logFiles;
+ /// <summary>
+ /// Gets or sets the remote log files.
+ /// </summary>
+ public List<RemoteLogFileModel<LogItemBase>> LogFiles
+ {
+ get { return _logFiles; }
+ set { _logFiles = value; RaisePropertyChangedAuto(); }
+ }
+
+ private RemoteLogFileModel<LogItemBase> _selectedLogFile;
+ /// <summary>
+ /// Gets or sets the selected remote log file.
+ /// </summary>
+ public RemoteLogFileModel<LogItemBase> SelectedLogFile
+ {
+ get { return _selectedLogFile; }
+ set { _selectedLogFile = value; RaisePropertyChangedAuto(); OnSelectedLogFileChanged(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the application logs.
+ /// </summary>
+ public ObservableCollection<LogItemBase> ApplicationLogs { get; set; }
+
+ /// <summary>
+ /// Gets or sets the application logs view.
+ /// </summary>
+ public ICollectionView ApplicationLogsView { get; set; }
+
+ /// <summary>
+ /// Gets or sets the selected application logs categories.
+ /// </summary>
+ public SelectedObjectCollection<LogCategory> SelectedApplicationLogsCategories { get; set; }
+
+ private String _applicationLogsFilter;
+ /// <summary>
+ /// Gets or sets the application logs filter.
+ /// </summary>
+ public String ApplicationLogsFilter
+ {
+ get { return _applicationLogsFilter; }
+ set { _applicationLogsFilter = value; RaisePropertyChangedAuto(); ApplicationLogsView.Refresh(); }
+ }
+
+ /// <summary>
+ /// Opens the detailed application log dialog.
+ /// </summary>
+ public RelayCommand<LogItemBase> OpenApplicationLogItemCommand { get; set; }
+
+ /// <summary>
+ /// Exports the selected log file to local disk.
+ /// </summary>
+ public RelayCommand ExportLogFileCommand { get; set; }
+
+ /// <summary>
+ /// Exports all the downloaded log files to disk.
+ /// </summary>
+ public RelayCommand ExportAllDownloadedLogFilesCommand { get; set; }
+
+ /// <summary>
+ /// Downloads all the available log files.
+ /// </summary>
+ public RelayCommand DownloadAllLogFilesCommand { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="LogsViewVM"/> class.
+ /// </summary>
+ public LogsViewVM()
+ {
+ ApplicationLogs = new ObservableCollection<LogItemBase>();
+ ApplicationLogsView = CollectionViewSource.GetDefaultView(ApplicationLogs);
+ ApplicationLogsView.Filter = FilterApplicationLogs;
+ SelectedApplicationLogsCategories = new SelectedObjectCollection<LogCategory>(new ObservableCollection<LogCategory>()
+ {
+ LogCategory.Info,
+ LogCategory.Warning,
+ LogCategory.Error,
+ LogCategory.Critical,
+ }, new ObservableCollection<LogCategory>()
+ {
+ LogCategory.Info,
+ LogCategory.Warning,
+ LogCategory.Error,
+ LogCategory.Critical,
+ });
+
+ SelectedApplicationLogsCategories.SynchedSource.CollectionChanged += (_, __) => ApplicationLogsView.Refresh();
+
+ OpenApplicationLogItemCommand = new RelayCommand<LogItemBase>(OpenApplicationLogItem);
+
+ ExportLogFileCommand = new RelayCommand(ExportSelectedLogFile);
+ ExportAllDownloadedLogFilesCommand = new RelayCommand(ExportAllDownloadedLogFiles);
+ DownloadAllLogFilesCommand = new RelayCommand(DownloadAllLogFiles);
+ }
+
+ public override void OnApplicationStarted()
+ {
+ base.OnApplicationStarted();
+ MachineProvider.MachineConnected += MachineProvider_MachineConnected;
+ }
+
+ private void MachineProvider_MachineConnected(object sender, MachineConnectedEventArgs e)
+ {
+ if (e.DifferentFromPrevious)
+ {
+ _loaded = false;
+
+ if (MachineProvider.ConnectionType.IsRemote() && IsVisible)
+ {
+ LoadLogFiles();
+ }
+ }
+ }
+
+ public override void OnNavigatedTo()
+ {
+ base.OnNavigatedTo();
+
+ if (!_loaded)
+ {
+ LoadLogFiles();
+ }
+ }
+
+ private async void LoadLogFiles()
+ {
+ if (!MachineProvider.ConnectionType.IsRemote() || !IsFree) return;
+
+ try
+ {
+ IsFree = false;
+ var logFiles = await LoggingProvider.GetApplicationLogFiles();
+ LogFiles = logFiles.Select(x =>
+ {
+
+ var model = new RemoteLogFileModel<LogItemBase>(new ApplicationLogFileParser());
+ model.RemoteLogFile = x;
+ model.DownloadCompleted += OnRemoteLogFileDownloadCompleted;
+ return model;
+
+ }).ToList();
+ SelectedLogFile = LogFiles.FirstOrDefault();
+ _loaded = true;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading log files.");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+
+ private void OnRemoteLogFileDownloadCompleted(object sender, EventArgs e)
+ {
+ if (SelectedLogFile == sender)
+ {
+ OnSelectedLogFileChanged();
+ }
+ }
+
+ private void OnSelectedLogFileChanged()
+ {
+ if (SelectedLogFile == null) return;
+
+ InvokeUI(() =>
+ {
+ ApplicationLogs.Clear();
+ foreach (var logItem in SelectedLogFile.LogItems)
+ {
+ ApplicationLogs.Add(logItem);
+ }
+
+ ApplicationLogsView.Refresh();
+ });
+ }
+
+ private async void OpenApplicationLogItem(LogItemBase logItem)
+ {
+ await NotificationProvider.ShowDialog(new ApplicationLogItemViewVM() { LogItem = logItem });
+ }
+
+ private bool FilterApplicationLogs(object obj)
+ {
+ var log = obj as LogItemBase;
+ return SelectedApplicationLogsCategories.SynchedSource.Contains(log.Category) && (String.IsNullOrWhiteSpace(ApplicationLogsFilter) || log.Message.ToLower().Contains(ApplicationLogsFilter.ToLower()));
+ }
+
+ private async void ExportSelectedLogFile()
+ {
+ if (SelectedLogFile != null && SelectedLogFile.Status == RemoteLogFileStatus.Downloaded)
+ {
+ var result = await StorageProvider.SaveFile("Export Log File", "Application Log Files|*.log", SelectedLogFile.RemoteLogFile.Name, ".log");
+ if (result)
+ {
+ using (NotificationProvider.PushTaskItem("Exporting log file..."))
+ {
+ try
+ {
+ File.Copy(SelectedLogFile.TemporaryFile, result.SelectedItem, true);
+ await NotificationProvider.ShowSuccess("Log file exported successfully.");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error exporting application log file.");
+ await NotificationProvider.ShowError($"Could not export the log file.\n{ex.FlattenMessage()}");
+ }
+ }
+ }
+ }
+ }
+
+ private async void ExportAllDownloadedLogFiles()
+ {
+ var result = await StorageProvider.SelectFolder("Export Log Files");
+ if (result)
+ {
+ var toExport = LogFiles.Where(x => x.Status == RemoteLogFileStatus.Downloaded).ToList();
+ var count = toExport.Count;
+
+ using (var task = NotificationProvider.PushTaskItem("Exporting log files..."))
+ {
+ foreach (var logFile in toExport.ToList())
+ {
+ try
+ {
+ await Task.Delay(500);
+ File.Copy(logFile.TemporaryFile, Path.Combine(result.SelectedItem, logFile.RemoteLogFile.Name), true);
+ toExport.Remove(logFile);
+ task.UpdateProgress("Exporting log files...", count - toExport.Count, count, false);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error exporting application log file '{logFile.RemoteLogFile.Name}'.");
+ await NotificationProvider.ShowError($"Could not export '{logFile.RemoteLogFile.Name}'.\n{ex.FlattenMessage()}");
+ }
+ }
+ }
+
+ await NotificationProvider.ShowSuccess($"Successfully exported {count - toExport.Count} out of {count} log files.");
+ }
+ }
+
+ private async void DownloadAllLogFiles()
+ {
+ var toDownload = LogFiles.Where(x => x.Status == RemoteLogFileStatus.None);
+ var totalSize = FileHelper.GetFriendlyFileSize(toDownload.Select(x => x.RemoteLogFile.Length).Sum());
+
+ if (await NotificationProvider.ShowWarningQuestion($"Are you sure you wish to download the entire history of log files?\nTotal size: {totalSize}", "DOWNLOAD", "CANCEL"))
+ {
+ foreach (var logFile in toDownload)
+ {
+ logFile.DownloadLogFile();
+ }
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs
index e18a75ef6..f4614ccf1 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs
@@ -20,6 +20,7 @@ namespace Tango.FSE.PPCConsole.ViewModels
MonitoringView,
FileSystemView,
UpdatesView,
+ LogsView,
}
private NavigationView _selectedView;
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml
new file mode 100644
index 000000000..81258e971
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml
@@ -0,0 +1,225 @@
+<UserControl x:Class="Tango.FSE.PPCConsole.Views.LogsView"
+ 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:global="clr-namespace:Tango.FSE.PPCConsole"
+ xmlns:helpers="clr-namespace:Tango.SharedUI.Helpers;assembly=Tango.SharedUI"
+ xmlns:vm="clr-namespace:Tango.FSE.PPCConsole.ViewModels"
+ xmlns:components="clr-namespace:Tango.SharedUI.Components;assembly=Tango.SharedUI"
+ xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
+ xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:local="clr-namespace:Tango.FSE.PPCConsole.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:LogsViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.LogsViewVM}" x:Name="control">
+
+ <UserControl.Resources>
+
+ <Style x:Key="LogsGridCellStyle" 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>
+
+ <Style x:Key="LogsGridStyle" TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource FSE_GrayBrush}"></Setter>
+ <Setter Property="AutoGenerateColumns" Value="False"></Setter>
+ <Setter Property="CanUserAddRows" Value="False"></Setter>
+ <Setter Property="CanUserDeleteRows" Value="False"></Setter>
+ <Setter Property="CanUserReorderColumns" Value="False"></Setter>
+ <Setter Property="CanUserResizeColumns" Value="False"></Setter>
+ <Setter Property="CanUserResizeRows" Value="False"></Setter>
+ <Setter Property="CanUserSortColumns" Value="False"></Setter>
+ <Setter Property="IsReadOnly" Value="True"></Setter>
+ <Setter Property="SelectionMode" Value="Single"></Setter>
+ <Setter Property="SelectionUnit" Value="FullRow"></Setter>
+ <Setter Property="RowHeight" Value="35"></Setter>
+ <Setter Property="HorizontalGridLinesBrush" Value="{StaticResource FSE_PrimaryBackgroundBrush}"></Setter>
+ <Setter Property="HorizontalScrollBarVisibility" Value="Disabled"></Setter>
+ <Setter Property="CellStyle" Value="{StaticResource LogsGridCellStyle}" />
+ </Style>
+ </UserControl.Resources>
+
+ <Grid IsEnabled="{Binding IsFree}">
+ <Grid Margin="0 20 0 0">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="270"/>
+ <ColumnDefinition Width="303*"/>
+ </Grid.ColumnDefinitions>
+
+ <Grid>
+ <Border Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderBrush="{StaticResource FSE_PrimaryBackgroundLightBrush}" BorderThickness="3" CornerRadius="3" Padding="5 5">
+ <ListBox Background="Transparent" BorderThickness="0" ItemsSource="{Binding LogFiles}" SelectedItem="{Binding SelectedLogFile}">
+ <ListBox.InputBindings>
+ <KeyBinding Key="Return" Command="{Binding SelectedLogFile.DownloadCommand}" />
+ </ListBox.InputBindings>
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <DockPanel>
+ <DockPanel.Style>
+ <Style TargetType="DockPanel">
+ <Setter Property="Opacity" Value="0.6"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Status}" Value="Downloaded">
+ <Setter Property="Opacity" Value="1"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </DockPanel.Style>
+ <material:PackIcon Kind="FileDocument" Width="Auto" Height="35" />
+ <StackPanel Margin="5 0 0 0">
+ <TextBlock Text="{Binding RemoteLogFile.DateCreated,Converter={StaticResource DateTimeUtcToLocalDateTime},StringFormat='MM/dd/yyyy HH:mm'}"></TextBlock>
+ <TextBlock Margin="0 5 0 0" Foreground="{StaticResource FSE_GrayBrush}" FontSize="{StaticResource FSE_SmallFontSize}">
+ <Run Text="{Binding RemoteLogFile.Length,Converter={StaticResource ByteArrayToFileSizeConverter}}"></Run>
+ <Run>|</Run>
+ <Run Text="{Binding Duration,Mode=OneWay,StringFormat='hh\\:mm'}"></Run>
+ </TextBlock>
+ </StackPanel>
+ </DockPanel>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
+ </Border>
+ </Grid>
+
+ <Border Grid.Column="1" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderBrush="{StaticResource FSE_PrimaryBackgroundLightBrush}" BorderThickness="3" CornerRadius="3" Padding="2" Margin="10 0 0 0">
+ <Grid>
+ <Grid>
+ <DockPanel Margin="10 0 10 10">
+ <Grid DockPanel.Dock="Top" Margin="12 10 0 0" Panel.ZIndex="100">
+ <TextBlock Foreground="{StaticResource FSE_PrimaryAccentBrush}" FontWeight="SemiBold">
+ <Run Text="{Binding SelectedLogFile.RemoteLogFile.DateCreated,Converter={StaticResource DateTimeUtcToLocalDateTime},StringFormat='MM/dd/yyyy HH:mm'}"></Run>
+ <Run>-</Run>
+ <Run Text="{Binding SelectedLogFile.RemoteLogFile.DateModified,Converter={StaticResource DateTimeUtcToLocalDateTime},StringFormat='HH:mm'}"></Run>
+ </TextBlock>
+ <StackPanel Margin="0 0 0 -70" HorizontalAlignment="Right" >
+ <StackPanel Margin="0 30 0 0" Orientation="Horizontal">
+ <ItemsControl VerticalAlignment="Center" ItemsSource="{Binding SelectedApplicationLogsCategories}" Visibility="{Binding ResolutionService.IsHighResolution,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <StackPanel Orientation="Horizontal" />
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <StackPanel Orientation="Horizontal" Margin="10 0 0 0">
+ <CheckBox FocusVisualStyle="{x:Null}" IsChecked="{Binding IsSelected,Delay=200}" VerticalAlignment="Center">
+ <CheckBox.Content>
+ <TextBlock Text="{Binding Data}" VerticalAlignment="Center"></TextBlock>
+ </CheckBox.Content>
+ </CheckBox>
+ </StackPanel>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+
+ <DockPanel Margin="20 0 0 0" VerticalAlignment="Center">
+ <material:PackIcon Kind="Search" VerticalAlignment="Center" Width="18" Height="18" />
+ <TextBox Margin="5 0 0 0" Style="{StaticResource FSE_Rounded_Corners_TextBox}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" FontSize="{StaticResource FSE_SmallFontSize}" material:HintAssist.Hint="filter" material:TextFieldAssist.RippleOnFocusEnabled="True" Text="{Binding ApplicationLogsFilter,UpdateSourceTrigger=PropertyChanged,Delay=1000}" Width="200"/>
+ </DockPanel>
+ </StackPanel>
+ </StackPanel>
+ </Grid>
+
+ <DataGrid Margin="0 5 0 0" Style="{StaticResource LogsGridStyle}" ItemsSource="{Binding ApplicationLogs}" CellStyle="{StaticResource LogsGridCellStyle}" helpers:DataGridHelper.DoubleClickCommand="{Binding OpenApplicationLogItemCommand}">
+ <DataGrid.Resources>
+ <components:BindingProxy x:Key="proxy" Data="{Binding}" />
+ </DataGrid.Resources>
+ <DataGrid.Columns>
+ <DataGridTemplateColumn Header="#" Width="40" CellTemplate="{StaticResource FSE_LogIcon_Cell}"/>
+ <DataGridTextColumn Header="DATE TIME" Binding="{Binding TimeStamp,StringFormat='HH:mm:ss.ff'}" Width="100" />
+ <DataGridTextColumn Visibility="{Binding Source={StaticResource proxy},Path=Data.ResolutionService.IsHighResolution,Converter={StaticResource BooleanToVisibilityConverter}}" Header="SERVICE" Binding="{Binding ClassName}" Width="200" />
+ <DataGridTemplateColumn Header="MESSAGE" Width="1*" >
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <TextBlock TextWrapping="NoWrap" Text="{Binding Message,Converter={StaticResource StringToOneLineConverter},ConverterParameter='120'}"></TextBlock>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ </DataGrid.Columns>
+ </DataGrid>
+ </DockPanel>
+ </Grid>
+
+ <Grid Background="{StaticResource FSE_SemiTransparentBrush}">
+ <Grid.Style>
+ <Style TargetType="Grid">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding SelectedLogFile.Status}" Value="Downloaded">
+ <Setter Property="Visibility" Value="Hidden"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Grid.Style>
+
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+ <StackPanel.Style>
+ <Style TargetType="StackPanel">
+ <Setter Property="Visibility" Value="Hidden"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding SelectedLogFile.Status}" Value="None">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </StackPanel.Style>
+ <material:PackIcon Kind="FileDocument" Width="100" Height="100" HorizontalAlignment="Center" />
+ <TextBlock Margin="0 20 0 0">Download this log file from the remote machine in order to display its content</TextBlock>
+ <controls:TextIconButton Style="{StaticResource FSE_TextIconButton_Dark}" Margin="0 100 0 0" Height="45" Icon="Download" HorizontalAlignment="Center" Width="180" Command="{Binding SelectedLogFile.DownloadCommand}">DOWNLOAD</controls:TextIconButton>
+ </StackPanel>
+
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+ <StackPanel.Style>
+ <Style TargetType="StackPanel">
+ <Setter Property="Visibility" Value="Hidden"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding SelectedLogFile.Status}" Value="Failed">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </StackPanel.Style>
+ <material:PackIcon Kind="AlertOutline" Width="100" Height="100" HorizontalAlignment="Center" Foreground="{StaticResource FSE_ErrorBrush}" />
+ <TextBlock Margin="0 20 0 0">Error occurred while trying to download this log file</TextBlock>
+ <controls:TextIconButton Style="{StaticResource FSE_TextIconButton_Dark}" Margin="0 100 0 0" Height="45" Icon="Download" HorizontalAlignment="Center" Width="180" Command="{Binding SelectedLogFile.DownloadCommand}">TRY AGAIN</controls:TextIconButton>
+ </StackPanel>
+
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+ <StackPanel.Style>
+ <Style TargetType="StackPanel">
+ <Setter Property="Visibility" Value="Hidden"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding SelectedLogFile.Status}" Value="Downloading">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </StackPanel.Style>
+ <material:PackIcon Kind="FileDownload" Width="100" Height="100" HorizontalAlignment="Center" />
+ <TextBlock Margin="0 20 0 0" HorizontalAlignment="Center">Downloading log file, please wait...</TextBlock>
+ <ProgressBar Margin="0 140 0 0" Width="600" Height="5" Minimum="0" Maximum="{Binding SelectedLogFile.Handler.Length}" Value="{Binding SelectedLogFile.Handler.Position}"></ProgressBar>
+ </StackPanel>
+ </Grid>
+
+ <StackPanel Margin="0 0 40 20" HorizontalAlignment="Right" VerticalAlignment="Bottom">
+ <material:PopupBox PopupMode="Click" Style="{StaticResource MaterialDesignMultiFloatingActionPopupBox}" PlacementMode="TopAndAlignCentres" FocusVisualStyle="{x:Null}">
+ <StackPanel>
+ <Button ToolTip="Download all log files" Command="{Binding DownloadAllLogFilesCommand}">
+ <material:PackIcon Kind="DownloadMultiple" />
+ </Button>
+ <Button ToolTip="Export all downloaded log files" Command="{Binding ExportAllDownloadedLogFilesCommand}">
+ <material:PackIcon Kind="DatabaseExport" />
+ </Button>
+ <Button ToolTip="Export selected log file" Command="{Binding ExportLogFileCommand}">
+ <material:PackIcon Kind="FileExportOutline" />
+ </Button>
+ </StackPanel>
+ </material:PopupBox>
+ </StackPanel>
+ </Grid>
+ </Border>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml.cs
new file mode 100644
index 000000000..d08f18326
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.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.FSE.PPCConsole.Views
+{
+ /// <summary>
+ /// Interaction logic for LogsView.xaml
+ /// </summary>
+ public partial class LogsView : UserControl
+ {
+ public LogsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml
index 1efc0516f..b8932be95 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml
@@ -29,19 +29,20 @@
</Style.Triggers>
</Style>
</Grid.Style>
- <commonControls:FSETabControl TabsWidth="900" x:Name="tabs" SelectedObject="{Binding SelectedView,Mode=TwoWay}">
+ <commonControls:FSETabControl TabsWidth="1000" x:Name="tabs" SelectedObject="{Binding SelectedView,Mode=TwoWay}">
<local:MonitoringView Tag="MONITORING" />
<local:RemoteDesktopView Tag="REMOTE DESKTOP" />
<local:ConsoleView Tag="COMMAND PROMPT" />
<local:FileSystemView Tag="FILE SYSTEM" />
<local:UpdatesView Tag="UPDATES" />
+ <local:LogsView Tag="LOGS" />
</commonControls:FSETabControl>
<TextBlock resolution:ResolutionHelper.MinWidth="1500" Margin="10 0 0 0" FontFamily="{StaticResource hand}" FontSize="{StaticResource FSE_ModuleHeaderFontSize}" Foreground="{StaticResource FSE_PrimaryAccentDarkBrush}" VerticalAlignment="Top" HorizontalAlignment="Left" Text="{Binding ElementName=tabs,Path=SelectedElement.Tag,Converter={StaticResource StringToTitleCaseConverter}}"></TextBlock>
</Grid>
</Grid>
- <Grid Background="#DE202020" Visibility="{Binding MachineProvider.IsPPCAvailable,Converter={StaticResource BooleanToVisibilityInverseConverter}}">
+ <Grid Background="#DE202020" Visibility="{Binding MachineProvider.IsPPCAvailable,Converter={StaticResource BooleanToVisibilityInverseConverter},FallbackValue='Visible',TargetNullValue='Visible'}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<material:PackIcon HorizontalAlignment="Center" Kind="AlertOutline" Width="100" Height="100" />
<TextBlock Margin="0 20 0 0" HorizontalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}">
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/UpdatesView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/UpdatesView.xaml
index 037fa6d96..8a8e6546e 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/UpdatesView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/UpdatesView.xaml
@@ -60,7 +60,7 @@
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
- <DataGridTextColumn Header="STARTED" Binding="{Binding StartDate,Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" Width="Auto" />
+ <DataGridTextColumn Header="STARTED" Binding="{Binding StartDate,Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" Width="120" />
<DataGridTextColumn Header="APPLICATION" Binding="{Binding ApplicationVersion}" Width="Auto" />
<DataGridTextColumn Header="FIRMWARE" Binding="{Binding FirmwareVersion}" Width="Auto" />
<DataGridTextColumn Header="ENDED" Binding="{Binding EndDate,TargetNullValue='Never',FallbackValue='Never',Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" Width="Auto" />