diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-04-11 00:54:54 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-04-11 00:54:54 +0300 |
| commit | cb1b51c238c64f570d73b7dca6a2eee205b2da01 (patch) | |
| tree | dae3c0d5da9d003cb6860431d763eaad0dd5caf7 /Software/Visual_Studio | |
| parent | b4682a3abfe299c19b24752b2fb1ce2477611ec3 (diff) | |
| download | Tango-cb1b51c238c64f570d73b7dca6a2eee205b2da01.tar.gz Tango-cb1b51c238c64f570d73b7dca6a2eee205b2da01.zip | |
Implemented FSE bug reporting !!!
Diffstat (limited to 'Software/Visual_Studio')
49 files changed, 1290 insertions, 162 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs index 6fb46320b..6dea5c146 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs @@ -211,7 +211,14 @@ namespace Tango.FSE.PPCConsole.ViewModels { if (e.DifferentFromPrevious) { - await Navigate(null); + try + { + await Navigate(null, null, true); + } + catch (Exception ex) + { + NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Could not initialize the remote file system provider."); + } } } } @@ -406,7 +413,7 @@ namespace Tango.FSE.PPCConsole.ViewModels await Navigate(null, specialFolder); } - private async Task Navigate(String path, Environment.SpecialFolder? specialFolder = null) + private async Task Navigate(String path, Environment.SpecialFolder? specialFolder = null, bool throwError = false) { try { @@ -439,7 +446,14 @@ namespace Tango.FSE.PPCConsole.ViewModels { IsFree = true; Mouse.OverrideCursor = null; - await NotificationProvider.ShowError($"Error navigating to the specified path.\n{ex.FlattenMessage()}"); + if (!throwError) + { + await NotificationProvider.ShowError($"Error navigating to the specified path.\n{ex.FlattenMessage()}"); + } + else + { + throw ex; + } } finally { 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 index 52955e18a..a78e52ebe 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/LogsViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/LogsViewVM.cs @@ -174,6 +174,7 @@ namespace Tango.FSE.PPCConsole.ViewModels catch (Exception ex) { LogManager.Log(ex, "Error loading log files."); + NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Could not initialize the remote PPC logs history."); } finally { diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MonitoringViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MonitoringViewVM.cs index 4b37e6b31..6c0c3f05f 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MonitoringViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MonitoringViewVM.cs @@ -265,7 +265,7 @@ namespace Tango.FSE.PPCConsole.ViewModels { FetchingSystemInfo = false; LogManager.Log(ex, "Error retrieving system information from remote machine."); - await NotificationProvider.ShowWarning("Error retrieving the remote machine PPC system information."); + NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Error retrieving the remote machine PPC system information."); } finally { diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/UpdatesViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/UpdatesViewVM.cs index d97824fe9..81307ffd1 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/UpdatesViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/UpdatesViewVM.cs @@ -47,7 +47,7 @@ namespace Tango.FSE.PPCConsole.ViewModels get { return _packages; } set { _packages = value; RaisePropertyChangedAuto(); } } - + private String _filter; /// <summary> /// Gets or sets the search filter. @@ -141,7 +141,7 @@ namespace Tango.FSE.PPCConsole.ViewModels private async void LoadMachineUpdates() { - if (!MachineProvider.ConnectionType.IsRemote()) return; + if (!MachineProvider.IsConnected || !MachineProvider.ConnectionType.IsRemote()) return; if (!_loaded) { @@ -167,6 +167,7 @@ namespace Tango.FSE.PPCConsole.ViewModels catch (Exception ex) { LogManager.Log(ex, "Error retrieving machine updates."); + NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Error occurred while trying to retrieve the machine software updates history."); } finally { diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml index 1aad6fa58..63fa5f5cd 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml @@ -10,7 +10,7 @@ xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:ConsoleViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.ConsoleViewVM}"> - <Grid> + <Grid IsEnabled="{Binding MachineProvider.IsConnected}"> <Border Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1" CornerRadius="5"> <console:ConsoleControl Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" Margin="10" BorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsBackground="{StaticResource FSE_PrimaryBackgroundBrush}" SuggestionsBorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsForeground="Silver" DataContext="{Binding ConsoleVM}"> <console:ConsoleControl.BusyTemplate> 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 index 81258e971..dde14d6c7 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml @@ -42,7 +42,7 @@ </UserControl.Resources> <Grid IsEnabled="{Binding IsFree}"> - <Grid Margin="0 20 0 0"> + <Grid Margin="0 20 0 0" IsEnabled="{Binding MachineProvider.IsConnected}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="270"/> <ColumnDefinition Width="303*"/> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml index 919bbb14e..9aa8cab3c 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml @@ -12,8 +12,8 @@ xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:RemoteDesktopViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.RemoteDesktopViewVM}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}" Focusable="False"> - <Grid> - <DockPanel> + <Grid IsEnabled="{Binding IsFree}"> + <DockPanel IsEnabled="{Binding MachineProvider.IsConnected}"> <Border DockPanel.Dock="Right" CornerRadius="15" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1"> <Grid> <Border CornerRadius="1" BorderThickness="30"> 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 8a8e6546e..29d370507 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 @@ -12,112 +12,114 @@ xmlns:dragablz="http://dragablz.net/winfx/xaml/dragablz" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:UpdatesViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.UpdatesViewVM}"> - <Grid> - <dragablz:TabablzControl FixedHeaderCount="2" Margin="0 20 0 0"> - <TabItem Header="SOFTWARE UPDATES"> - <Border Margin="0 10 0 0" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1" CornerRadius="3" Padding="5" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}"> - <DataGrid Style="{StaticResource FSE_DataGrid}" CellStyle="{StaticResource FSE_DataGrid_Cell}" ItemsSource="{Binding Updates}" helpers:DataGridHelper.DoubleClickCommand="{Binding OpenUpdateCommand}"> - <DataGrid.Columns> - <DataGridTemplateColumn Header=""> - <DataGridTemplateColumn.CellTemplate> - <DataTemplate> - <material:PackIcon Width="20" Height="20"> - <material:PackIcon.Style> - <Style TargetType="material:PackIcon"> - <Setter Property="Kind" Value="Information"></Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding IsSetup}" Value="True"> - <Setter Property="Kind" Value="Settings"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding IsUpdate}" Value="True"> - <Setter Property="Kind" Value="CloudDownload"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding IsDataBase}" Value="True"> - <Setter Property="Kind" Value="Database"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding IsSynchronization}" Value="True"> - <Setter Property="Kind" Value="Sync"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding IsOfflineUpdate}" Value="True"> - <Setter Property="Kind" Value="Sd"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding IsOfflineFirmwareUpgrade}" Value="True"> - <Setter Property="Kind" Value="Chip"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding IsStarted}" Value="True"> - <Setter Property="Foreground" Value="{StaticResource FSE_OrangeBrush}"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding IsCompleted}" Value="True"> - <Setter Property="Foreground" Value="{StaticResource FSE_GreenBrush}"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding IsFailed}" Value="True"> - <Setter Property="Foreground" Value="{StaticResource FSE_RedBrush}"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </material:PackIcon.Style> - </material:PackIcon> - </DataTemplate> - </DataGridTemplateColumn.CellTemplate> - </DataGridTemplateColumn> - <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" /> - <DataGridTextColumn Header="STATUS" Binding="{Binding UpdateStatus,Converter={StaticResource EnumToDescriptionConverter}}" Width="Auto" /> - <DataGridTextColumn Header="FAILED REASON" Binding="{Binding FailedReason,Converter={StaticResource StringToOneLineConverter},ConverterParameter='80'}" Width="*" /> - </DataGrid.Columns> - </DataGrid> - </Border> - </TabItem> - <TabItem Header="INSTALLED PACKAGES"> - <Border Margin="0 10 0 0" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1" CornerRadius="3" Padding="5" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}"> - <DataGrid Style="{StaticResource FSE_DataGrid}" CellStyle="{StaticResource FSE_DataGrid_Cell}" ItemsSource="{Binding Packages}" SelectedItem="{Binding SelectedPackage}"> - <DataGrid.Columns> - <DataGridTemplateColumn Header=""> - <DataGridTemplateColumn.CellTemplate> - <DataTemplate> - <material:PackIcon Width="20" Height="20"> - <material:PackIcon.Style> - <Style TargetType="material:PackIcon"> - <Setter Property="Kind" Value="Pause"></Setter> - <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding State}" Value="Failed"> - <Setter Property="Kind" Value="Alert"></Setter> - <Setter Property="Foreground" Value="{StaticResource FSE_ErrorBrush}"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding State}" Value="Installed"> - <Setter Property="Kind" Value="Check"></Setter> - <Setter Property="Foreground" Value="{StaticResource FSE_SuccessBrush}"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </material:PackIcon.Style> - </material:PackIcon> - </DataTemplate> - </DataGridTemplateColumn.CellTemplate> - </DataGridTemplateColumn> - <DataGridTextColumn Header="Type" Width="60" Binding="{Binding Type}" /> - <DataGridTextColumn Header="Date" Width="120" Binding="{Binding InstallationDate,Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" /> - <DataGridTextColumn Header="Name" Width="*" Binding="{Binding PackageName}" /> - </DataGrid.Columns> - </DataGrid> - </Border> - </TabItem> - </dragablz:TabablzControl> + <Grid IsEnabled="{Binding IsFree}"> + <Grid IsEnabled="{Binding MachineProvider.IsConnected}"> + <dragablz:TabablzControl FixedHeaderCount="2" Margin="0 20 0 0"> + <TabItem Header="SOFTWARE UPDATES"> + <Border Margin="0 10 0 0" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1" CornerRadius="3" Padding="5" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}"> + <DataGrid Style="{StaticResource FSE_DataGrid}" CellStyle="{StaticResource FSE_DataGrid_Cell}" ItemsSource="{Binding Updates}" helpers:DataGridHelper.DoubleClickCommand="{Binding OpenUpdateCommand}"> + <DataGrid.Columns> + <DataGridTemplateColumn Header=""> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <material:PackIcon Width="20" Height="20"> + <material:PackIcon.Style> + <Style TargetType="material:PackIcon"> + <Setter Property="Kind" Value="Information"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding IsSetup}" Value="True"> + <Setter Property="Kind" Value="Settings"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsUpdate}" Value="True"> + <Setter Property="Kind" Value="CloudDownload"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsDataBase}" Value="True"> + <Setter Property="Kind" Value="Database"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsSynchronization}" Value="True"> + <Setter Property="Kind" Value="Sync"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsOfflineUpdate}" Value="True"> + <Setter Property="Kind" Value="Sd"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsOfflineFirmwareUpgrade}" Value="True"> + <Setter Property="Kind" Value="Chip"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsStarted}" Value="True"> + <Setter Property="Foreground" Value="{StaticResource FSE_OrangeBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsCompleted}" Value="True"> + <Setter Property="Foreground" Value="{StaticResource FSE_GreenBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsFailed}" Value="True"> + <Setter Property="Foreground" Value="{StaticResource FSE_RedBrush}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </material:PackIcon.Style> + </material:PackIcon> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <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" /> + <DataGridTextColumn Header="STATUS" Binding="{Binding UpdateStatus,Converter={StaticResource EnumToDescriptionConverter}}" Width="Auto" /> + <DataGridTextColumn Header="FAILED REASON" Binding="{Binding FailedReason,Converter={StaticResource StringToOneLineConverter},ConverterParameter='80'}" Width="*" /> + </DataGrid.Columns> + </DataGrid> + </Border> + </TabItem> + <TabItem Header="INSTALLED PACKAGES"> + <Border Margin="0 10 0 0" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1" CornerRadius="3" Padding="5" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}"> + <DataGrid Style="{StaticResource FSE_DataGrid}" CellStyle="{StaticResource FSE_DataGrid_Cell}" ItemsSource="{Binding Packages}" SelectedItem="{Binding SelectedPackage}"> + <DataGrid.Columns> + <DataGridTemplateColumn Header=""> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <material:PackIcon Width="20" Height="20"> + <material:PackIcon.Style> + <Style TargetType="material:PackIcon"> + <Setter Property="Kind" Value="Pause"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding State}" Value="Failed"> + <Setter Property="Kind" Value="Alert"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_ErrorBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding State}" Value="Installed"> + <Setter Property="Kind" Value="Check"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_SuccessBrush}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </material:PackIcon.Style> + </material:PackIcon> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTextColumn Header="Type" Width="60" Binding="{Binding Type}" /> + <DataGridTextColumn Header="Date" Width="120" Binding="{Binding InstallationDate,Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" /> + <DataGridTextColumn Header="Name" Width="*" Binding="{Binding PackageName}" /> + </DataGrid.Columns> + </DataGrid> + </Border> + </TabItem> + </dragablz:TabablzControl> - <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 20 20 0"> - <material:PackIcon Kind="Search" VerticalAlignment="Center" Height="Auto" Width="25" /> - <TextBox Margin="5 0 0 0" Padding="7" material:HintAssist.Hint="Filter..." VerticalContentAlignment="Center" IsEnabled="{Binding IsFree}" Style="{StaticResource FSE_Rounded_Corners_TextBox}" Width="200" Text="{Binding Filter,UpdateSourceTrigger=PropertyChanged,Delay=500}"></TextBox> - <controls:IconButton Icon="Refresh" Margin="40 0 0 0" Command="{Binding RefreshCommand}" IsEnabled="{Binding IsFree}" ToolTip="Refresh updates"></controls:IconButton> - </StackPanel> - - <Grid Margin="4 74 4 4" Background="{StaticResource FSE_SemiTransparentBrush}" Visibility="{Binding IsBusy,Converter={StaticResource BooleanToVisibilityConverter},FallbackValue=Collapsed}"> - <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> - <ProgressBar Style="{StaticResource FSE_CircularProgressBar}" Width="100" Height="100" IsIndeterminate="True"></ProgressBar> - <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0">Loading machine updates...</TextBlock> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 20 20 0"> + <material:PackIcon Kind="Search" VerticalAlignment="Center" Height="Auto" Width="25" /> + <TextBox Margin="5 0 0 0" Padding="7" material:HintAssist.Hint="Filter..." VerticalContentAlignment="Center" IsEnabled="{Binding IsFree}" Style="{StaticResource FSE_Rounded_Corners_TextBox}" Width="200" Text="{Binding Filter,UpdateSourceTrigger=PropertyChanged,Delay=500}"></TextBox> + <controls:IconButton Icon="Refresh" Margin="40 0 0 0" Command="{Binding RefreshCommand}" IsEnabled="{Binding IsFree}" ToolTip="Refresh updates"></controls:IconButton> </StackPanel> + + <Grid Margin="4 74 4 4" Background="{StaticResource FSE_SemiTransparentBrush}" Visibility="{Binding IsBusy,Converter={StaticResource BooleanToVisibilityConverter},FallbackValue=Collapsed}"> + <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> + <ProgressBar Style="{StaticResource FSE_CircularProgressBar}" Width="100" Height="100" IsIndeterminate="True"></ProgressBar> + <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0">Loading machine updates...</TextBlock> + </StackPanel> + </Grid> </Grid> </Grid> </UserControl> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheEntities/CachedBugInfoResponse.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheEntities/CachedBugInfoResponse.cs new file mode 100644 index 000000000..73e142d78 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/CacheEntities/CachedBugInfoResponse.cs @@ -0,0 +1,17 @@ +using LiteDB; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FSE.Web.Messages; + +namespace Tango.FSE.BL.CacheEntities +{ + public class CachedBugInfoResponse + { + [BsonId] + public String EnvironmentID { get; set; } + public BugReportingInfoResponse Response { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs index 9aeefd4d0..f2eb0dbe1 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs @@ -23,6 +23,8 @@ namespace Tango.FSE.BL [TangoInject] protected FSEWebClient WebClient { get; set; } + protected FSEServicesContainer Services { get; set; } + protected User CurrentUser { get { return Authentication.CurrentUser; } @@ -34,6 +36,10 @@ namespace Tango.FSE.BL { TangoIOC.Default.Inject(this); DiskCache = CacheManager.Default; + TangoIOC.Default.GetInstanceWhenAvailable<FSEServicesContainer>((x) => + { + Services = x; + }); } public void Dispose() diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs index ef50bf036..2fa6cae53 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs @@ -33,6 +33,11 @@ namespace Tango.FSE.BL public AuthenticationService AuthenticationService { get; set; } /// <summary> + /// Gets or sets the bug reporting service. + /// </summary> + public BugReportingService BugReportingService { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="FSEServicesContainer"/> class. /// </summary> /// <param name="authentication">The authentication.</param> @@ -42,6 +47,7 @@ namespace Tango.FSE.BL UsersService = new UsersService(); GatewayService = new GatewayService(); AuthenticationService = new AuthenticationService(); + BugReportingService = new BugReportingService(); } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/IAuthenticationService.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/IAuthenticationService.cs index 0169c38b9..200831337 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.BL/IAuthenticationService.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/IAuthenticationService.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL.Entities; +using Tango.MachineService.Gateway; namespace Tango.FSE.BL { @@ -13,6 +14,11 @@ namespace Tango.FSE.BL public interface IAuthenticationService { /// <summary> + /// Gets the current environment configuration. + /// </summary> + EnvironmentConfiguration CurrentEnvironment { get; } + + /// <summary> /// Gets the global current user. /// </summary> User CurrentUser { get; } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/BugReportingService.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/BugReportingService.cs new file mode 100644 index 000000000..5650aeab8 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Services/BugReportingService.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FSE.BL.CacheEntities; +using Tango.FSE.Web.Messages; + +namespace Tango.FSE.BL.Services +{ + public class BugReportingService : FSEServiceBase + { + private const string BUG_INFO_RESPONSES_COLLECTION = "BugInfoResponses"; + + /// <summary> + /// Gets the necessary information required in order to initialize a TFS API client. + /// </summary> + /// <returns></returns> + public Task<BugReportingInfoResponse> GetBugReportingInfo() + { + LogManager.Log($"Retrieving bug reporting information for environment '{Authentication.CurrentEnvironment.Name}'..."); + + return DataResolver<BugReportingInfoResponse>.Builder.New() + .ConfigureCascade(DataResolverNode.Online, DataResolverNode.DiskCache) + .Online((context) => + { + var response = WebClient.GetBugReportInfo(new BugReportingInfoRequest()).Result; + + LogManager.Log("Bug reporting information retrieved successfully. Caching bug reporting information on disk..."); + + try + { + using (var cache = DiskCache.CreateContext()) + { + cache.GetCollection<CachedBugInfoResponse>(BUG_INFO_RESPONSES_COLLECTION).Upsert(new CachedBugInfoResponse() + { + Response = response, + EnvironmentID = Authentication.CurrentEnvironment.ID + }); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error caching online bug reporting information response."); + } + + return response; + }) + .DiskCache((context) => + { + using (var cache = DiskCache.CreateContext()) + { + var cachedResponse = cache.GetCollection<CachedBugInfoResponse>(BUG_INFO_RESPONSES_COLLECTION).FindOne(x => x.EnvironmentID == Authentication.CurrentEnvironment.ID); + + if (cachedResponse == null) + { + throw new KeyNotFoundException($"Could not locate cached bug reporting information for the current environment {Authentication.CurrentEnvironment.Name}."); + } + + return cachedResponse.Response; + } + }) + .BuildExecuteAsync(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj b/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj index 6e9863095..0eae2baa3 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj @@ -71,6 +71,7 @@ </Reference> </ItemGroup> <ItemGroup> + <Compile Include="CacheEntities\CachedBugInfoResponse.cs" /> <Compile Include="CacheEntities\CachedConfiguration.cs" /> <Compile Include="CacheEntities\CachedLoginResponse.cs" /> <Compile Include="CacheEntities\CachedMachine.cs" /> @@ -87,6 +88,7 @@ <Compile Include="InternetConnectionException.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Services\AuthenticationService.cs" /> + <Compile Include="Services\BugReportingService.cs" /> <Compile Include="Services\GatewayService.cs" /> <Compile Include="Services\MachinesService.cs" /> <Compile Include="Services\UsersService.cs" /> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs b/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs index e13ef73de..fbfd1e647 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs @@ -39,5 +39,14 @@ namespace Tango.FSE.BL.Web } + /// <summary> + /// Executes the GetBugReportInfo action and returns Tango.FSE.Web.Messages.BugReportingInfoResponse. + /// </summary> + /// <returns></returns> + public Task<Tango.FSE.Web.Messages.BugReportingInfoResponse> GetBugReportInfo(Tango.FSE.Web.Messages.BugReportingInfoRequest request) + { + return Post<Tango.FSE.Web.Messages.BugReportingInfoRequest, Tango.FSE.Web.Messages.BugReportingInfoResponse>("GetBugReportInfo", request); + } + } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/Bug.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/Bug.cs new file mode 100644 index 000000000..a1f5f3f86 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/Bug.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.BugReporting +{ + /// <summary> + /// Represents a bug report. + /// </summary> + public class Bug + { + /// <summary> + /// Gets or sets the bug type. + /// </summary> + public BugType Type { get; set; } + + /// <summary> + /// Gets or sets the title. + /// </summary> + public String Title { get; set; } + + /// <summary> + /// Gets or sets the description. + /// </summary> + public String Description { get; set; } + + /// <summary> + /// Gets or sets optional comments. + /// </summary> + public String Comments { get; set; } + + /// <summary> + /// Gets or sets optional exception. + /// </summary> + public Exception Exception { get; set; } + + /// <summary> + /// Gets or sets optional steps to reproduce. + /// </summary> + public String StepsToReproduce { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/BugType.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/BugType.cs new file mode 100644 index 000000000..fc03c1fd4 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/BugType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.BugReporting +{ + public enum BugType + { + FSE, + PPC + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/IBugReporter.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/IBugReporter.cs new file mode 100644 index 000000000..e0bafdb54 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/IBugReporter.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.BugReporting +{ + /// <summary> + /// Represents a bug reporting service. + /// </summary> + public interface IBugReporter + { + /// <summary> + /// Submits the specified bug. + /// </summary> + /// <param name="bug">The bug.</param> + /// <returns></returns> + Task SubmitBug(Bug bug); + + /// <summary> + /// Displays a bug submission dialog. When confirmed, will submit the specified bug. + /// </summary> + /// <param name="bug">The bug.</param> + /// <returns></returns> + Task ShowBugReportDialog(Bug bug); + + /// <summary> + /// Displays a bug submission dialog. When confirmed, will submit the new created bug. + /// </summary> + /// <returns></returns> + Task ShowBugReportDialog(); + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs index b3d867349..01b27c8ea 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs @@ -32,6 +32,7 @@ using Tango.Settings; using Tango.SharedUI; using static Tango.SharedUI.Controls.NavigationControl; using Tango.FSE.BL.Connectivity; +using Tango.FSE.Common.BugReporting; namespace Tango.FSE.Common { @@ -140,6 +141,12 @@ namespace Tango.FSE.Common public IConnectivityProvider ConnectivityProvider { get; set; } /// <summary> + /// Gets or sets the bug reporter. + /// </summary> + [TangoInject] + public IBugReporter BugReporter { get; set; } + + /// <summary> /// Gets or sets the FSE service. /// </summary> [TangoInject] diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs index 49402bd41..4bb844e5a 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs @@ -282,6 +282,23 @@ namespace Tango.FSE.Common.Notifications SnackbarItem PushSnackbarItem(MessageType type, String title, bool canClose, String message = null, TimeSpan? timeout = null, Action closeAction = null, Action pressAction = null); /// <summary> + /// Display a new error SnackBar. Pressing the snack bar will display the issue reporting dialog. + /// </summary> + /// <param name="exception">The exception.</param> + /// <param name="title">The title.</param> + /// <param name="message">The message.</param> + /// <returns></returns> + SnackbarItem PushErrorReportingSnackbar(Exception exception, String title, String message); + + /// <summary> + /// Displays a indeterminate progress Snackbar. Should use <see cref="SnackbarItem.ProgressCompleted(string, TimeSpan?)"/> and <see cref="SnackbarItem.ProgressFailed(string, TimeSpan?)"/>. + /// </summary> + /// <param name="title">The title.</param> + /// <param name="message">The message.</param> + /// <returns></returns> + SnackbarItem PushProgressSnackbar(String title, String message); + + /// <summary> /// Pops the snack bar item. /// </summary> /// <param name="snackbarItem">The snack bar item.</param> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/MessageType.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/MessageType.cs index c4090865e..43c0d83d0 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/MessageType.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/MessageType.cs @@ -12,6 +12,7 @@ namespace Tango.FSE.Common.Notifications Question, Warning, Error, - Success + Success, + Busy, } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/SnackbarItem.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/SnackbarItem.cs index 6246d0ce1..46f4484b0 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/SnackbarItem.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/SnackbarItem.cs @@ -15,15 +15,37 @@ namespace Tango.FSE.Common.Notifications private Action _pressAction; private bool _isClosed; - public MessageType Type { get; set; } + private MessageType _type; + public MessageType Type + { + get { return _type; } + set { _type = value; RaisePropertyChangedAuto(); } + } public String Title { get; set; } - public String Message { get; set; } + private String _message; + public String Message + { + get { return _message; } + set { _message = value; RaisePropertyChangedAuto(); } + } + + private bool _isProgress; + public bool IsProgress + { + get { return _isProgress; } + set { _isProgress = value; RaisePropertyChangedAuto(); } + } public TimeSpan? Timeout { get; set; } - public bool CanClose { get; set; } + private bool _canClose; + public bool CanClose + { + get { return _canClose; } + set { _canClose = value; RaisePropertyChangedAuto(); } + } public RelayCommand CloseCommand { get; private set; } @@ -46,6 +68,8 @@ namespace Tango.FSE.Common.Notifications _pressAction = () => { + if (IsProgress) return; + if (pressAction != null) { Close(); @@ -69,9 +93,41 @@ namespace Tango.FSE.Common.Notifications PressCommand = new RelayCommand(() => { _pressAction?.Invoke(); }); CloseCommand = new RelayCommand(() => { _closeAction?.Invoke(); }); - if (Timeout != null) + StartCloseTimeout(Timeout); + } + + public void Close() + { + if (!_isClosed) { - Task.Delay(Timeout.Value).ContinueWith((x) => + _isClosed = true; + TangoIOC.Default.GetInstance<INotificationProvider>().PopSnackbarItem(this); + } + } + + public void ProgressCompleted(String message, TimeSpan? timeout = null) + { + IsProgress = false; + CanClose = true; + Message = message; + Type = MessageType.Success; + StartCloseTimeout(timeout); + } + + public void ProgressFailed(String message, TimeSpan? timeout = null) + { + IsProgress = false; + CanClose = true; + Message = message; + Type = MessageType.Error; + StartCloseTimeout(timeout); + } + + private void StartCloseTimeout(TimeSpan? timeout) + { + if (timeout != null) + { + Task.Delay(timeout.Value).ContinueWith((x) => { if (!_isClosed) { @@ -84,14 +140,5 @@ namespace Tango.FSE.Common.Notifications }); } } - - public void Close() - { - if (!_isClosed) - { - _isClosed = true; - TangoIOC.Default.GetInstance<INotificationProvider>().PopSnackbarItem(this); - } - } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml index 462e2a976..bb3d6ebe8 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml @@ -495,6 +495,7 @@ <Setter Property="VerticalContentAlignment" Value="Center"></Setter> <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter> <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> + <Setter Property="CaretBrush" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> @@ -524,6 +525,42 @@ </Setter> </Style> + <Style x:Key="FSE_Rounded_Corners_TextBox_Multiline" TargetType="TextBox"> + <Setter Property="Background" Value="{StaticResource FSE_PrimaryBackgroundBrush}"></Setter> + <Setter Property="BorderBrush" Value="{StaticResource FSE_BorderBrush}"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Setter Property="VerticalContentAlignment" Value="Top"></Setter> + <Setter Property="HorizontalContentAlignment" Value="Left"></Setter> + <Setter Property="Height" Value="Auto"></Setter> + <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> + <Setter Property="FocusVisualStyle" Value="{x:Null}"/> + <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> + <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> + <Setter Property="AcceptsReturn" Value="True"></Setter> + <Setter Property="CaretBrush" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Setter Property="Padding" Value="3"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type TextBoxBase}"> + <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True" CornerRadius="5"> + <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto"/> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Foreground" Value="{StaticResource FSE_GrayBrush}"/> + </Trigger> + <Trigger Property="Width" Value="Auto"> + <Setter Property="MinWidth" Value="100"/> + </Trigger> + <Trigger Property="Height" Value="Auto"> + <Setter Property="MinHeight" Value="20"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + <Style x:Key="FSE_DataGrid_Cell" TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"> <Setter Property="BorderThickness" Value="0"/> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj index 1581bd25b..d9b61f425 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj @@ -88,6 +88,9 @@ <Compile Include="Authentication\AuthenticationResult.cs" /> <Compile Include="Authentication\IAuthenticationProvider.cs" /> <Compile Include="AutoComplete\AutoCompleteSource.cs" /> + <Compile Include="BugReporting\Bug.cs" /> + <Compile Include="BugReporting\BugType.cs" /> + <Compile Include="BugReporting\IBugReporter.cs" /> <Compile Include="Connection\IMachineProvider.cs" /> <Compile Include="Connection\MachineConnectedEventArgs.cs" /> <Compile Include="Connection\MachineConnectionTypes.cs" /> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs index 3d83b3979..3a0828d1f 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs @@ -11,6 +11,7 @@ using System.Windows; using Tango.Core.DI; using Tango.Core.Helpers; using Tango.FSE.Common; +using Tango.FSE.Common.BugReporting; using Tango.FSE.Common.Helpers; using Tango.FSE.Common.Notifications; using Tango.Integration.Operation; @@ -43,6 +44,8 @@ namespace Tango.FSE.UI { ThreadPool.SetMaxThreads(1000, 1000); + ThreadsHelper.SetDisptacher(Dispatcher); + //If no debugger is attached and the argument -debug was passed launch the debugger. if (e.Args.Contains("-debug") && !Debugger.IsAttached) { @@ -116,12 +119,22 @@ namespace Tango.FSE.UI { LogManager.Log("Trying to notify the user about the crash..."); INotificationProvider notificationProvider = TangoIOC.Default.GetInstance<INotificationProvider>(); + IBugReporter bugReporter = TangoIOC.Default.GetInstance<IBugReporter>(); if (notificationProvider != null) { - notificationProvider.PushSnackbarItem(MessageType.Error, "Application Error", true, "Unexpected error has occurred\nTap to see more details.", null, null, () => + notificationProvider.PushSnackbarItem(MessageType.Error, "Application Error", true, "Unexpected error has occurred\nTap to report this issue.", null, null, () => { - //TODO: display an application exception dialog with optional reporting. + if (bugReporter != null) + { + bugReporter.ShowBugReportDialog(new Bug() + { + Title = $"Unexpected Application Error", + Description = e.Exception.FlattenMessage(), + Type = BugType.FSE, + Exception = e.Exception + }); + } }); } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs index c76885bde..643537f30 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs @@ -68,6 +68,11 @@ namespace Tango.FSE.UI.Authentication } /// <summary> + /// Gets the current environment configuration. + /// </summary> + public EnvironmentConfiguration CurrentEnvironment { get; private set; } + + /// <summary> /// Logins the specified email. /// </summary> /// <param name="email">The email.</param> @@ -119,6 +124,8 @@ namespace Tango.FSE.UI.Authentication }).Result; + CurrentEnvironment = environment; + LogManager.Log($"Authentication response received:\n{response.ToJsonString()}"); settings.Save(); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs new file mode 100644 index 000000000..41e291a08 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Management; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Core; +using Tango.Core.DI; +using Tango.Core.ExtensionMethods; +using Tango.Core.Helpers; +using Tango.FSE.BL; +using Tango.FSE.Common.Authentication; +using Tango.FSE.Common.BugReporting; +using Tango.FSE.Common.Connection; +using Tango.FSE.Common.Connectivity; +using Tango.FSE.Common.FSEApplication; +using Tango.FSE.Common.Notifications; +using Tango.FSE.UI.Dialogs; +using Tango.FSE.Web.Messages; +using Tango.Integration.Operation; +using Tango.Logging; +using Tango.TFS; + +namespace Tango.FSE.UI.BugReporting +{ + [TangoCreateWhenRegistered] + public class DefaultBugReporter : ExtendedObject, IBugReporter + { + private bool _isInitialized; + private Project Project; + private TeamFoundationServiceClient _tfsClient; + private BugReportingInfoResponse _bugReportingInfoResponse; + + private IFSEApplicationManager ApplicationManager { get; set; } + + [TangoInject(TangoInjectMode.WhenAvailable)] + private INotificationProvider NotificationProvider { get; set; } + + [TangoInject(TangoInjectMode.WhenAvailable)] + private IMachineProvider MachineProvider { get; set; } + + [TangoInject(TangoInjectMode.WhenAvailable)] + private IAuthenticationProvider AuthenticationProvider { get; set; } + + [TangoInject(TangoInjectMode.WhenAvailable)] + private IConnectivityProvider ConnectivityProvider { get; set; } + + [TangoInject(TangoInjectMode.WhenAvailable)] + private FSEServicesContainer Services { get; set; } + + /// <summary> + /// Initializes a new instance of the <see cref="DefaultBugReporter"/> class. + /// </summary> + /// <param name="applicationManager">The application manager.</param> + public DefaultBugReporter(IFSEApplicationManager applicationManager) + { + ApplicationManager = applicationManager; + applicationManager.ApplicationReady += ApplicationManager_ApplicationReady; + } + + /// <summary> + /// Submits the specified bug. + /// </summary> + /// <param name="bug">The bug.</param> + /// <returns></returns> + public Task SubmitBug(Bug bug) + { + return Task.Factory.StartNew(() => + { + if (!_isInitialized) + { + Initialize().GetAwaiter().GetResult(); + } + else + { + if (!ConnectivityProvider.CheckOnline()) + { + throw new InternetConnectionException(); + } + } + + LogManager.Log("Submitting report..."); + WorkItem item = new WorkItem(); + var tempFolder = TemporaryManager.CreateFolder(); + + item.Title = bug.Title; + + item.Area = Project.GetAreaByName("FSE"); + item.Iteration = Project.Iterations.FirstOrDefault(); + + var fseMember = Project.Members.SingleOrDefault(x => x.Email.ToLower() == _bugReportingInfoResponse.UserEmail.ToLower()); + + if (fseMember == null) + { + throw new KeyNotFoundException("Could not locate FSE team member."); + } + + item.CreatedBy = fseMember; + item.ChangedBy = fseMember; + item.AuthorizedAs = fseMember; + item.AssignedTo = fseMember; + + item.StepsToReproduce = bug.StepsToReproduce.ToStringOrEmpty(); + + item.FoundInBuild = ApplicationManager.Version.ToString(); + item.Priority = Priority.Priority3; + item.Severity = Severity.Medium; + item.State = State.New; + item.Type = WorkItemType.Bug; + + FileLogger appFileLogger = LogManager.Default.RegisteredLoggers.FirstOrDefault(x => x.GetType() == typeof(FileLogger)) as FileLogger; + + if (appFileLogger != null) + { + LogManager.Log($"Attaching application log file ${appFileLogger.LogFile}"); + string[] logFiles = GetLogFiles(appFileLogger); + foreach (string file in logFiles) + { + var appLogFile = tempFolder.CreateImaginaryFile(); + File.Copy(file, appLogFile.Path); + item.Attachments.Add(new Attachment() + { + Description = "Application Log File", + FilePath = appLogFile.Path, + Name = Path.GetFileName(file), + }); + } + } + + if (MachineOperator.EnableSessionLogFile) + { + var file = MachineOperator.SessionLogger.LogFile; + + if (file != null && File.Exists(file)) + { + var sessionLogFile = tempFolder.CreateImaginaryFile(); + File.Copy(file, sessionLogFile.Path); + item.Attachments.Add(new Attachment() + { + Description = "Session Log File", + FilePath = sessionLogFile.Path, + Name = Path.GetFileName(file), + }); + } + } + + if (MachineProvider.IsConnected) + { + if (MachineProvider.MachineOperator.DeviceInformation != null) + { + item.EmbeddedVersion = MachineProvider.MachineOperator.DeviceInformation.Version; + } + + item.MachineSerialNumber = MachineProvider.Machine.SerialNumber; + } + + SystemInformationModel sysModel = new SystemInformationModel(); + sysModel.ApplicationVersion = ApplicationManager.Version.ToString(); + sysModel.EmbeddedVersion = "N/A"; + sysModel.HostName = Environment.MachineName; + sysModel.UserName = AuthenticationProvider.CurrentUser.Contact.FullName; + sysModel.OsVersion = GetOsVersion(); + sysModel.UserEmail = AuthenticationProvider.CurrentUser.Email; + sysModel.Description = bug.Description; + sysModel.Comments = bug.Comments != null ? bug.Comments : "No comments."; + sysModel.Exception = bug.Exception != null ? bug.Exception.FlattenException() : "No exception."; + + IMachineOperator op = MachineProvider.MachineOperator; + + LogManager.Log("Checking machine status..."); + + if (MachineProvider.IsConnected) + { + LogManager.Log("Machine is connected. Getting device information and configurations..."); + sysModel.Machine = MachineProvider.Machine; + sysModel.EmbeddedVersion = op.DeviceInformation.Version; + } + else + { + LogManager.Log("Machine is disconnected."); + } + + String html = String.Empty; + + LogManager.Log("Generating HTML system information from template..."); + + using (var stream = EmbeddedResourceHelper.GetEmbeddedResourceStream("Tango.FSE.UI.BugReporting.SystemInformationTemplate.cshtml")) + { + StreamReader reader = new StreamReader(stream); + html = reader.ReadToEnd(); + } + + item.SystemInformation = CodeGeneration.Helper.Parse(html, sysModel); + item.StepsToReproduce = String.Format("<div style=\"white-space:pre\">{0}</div>", item.StepsToReproduce); + + LogManager.Log("Uploading work item..."); + var workItem = _tfsClient.UploadWorkItem(Project, item).Result; + + LogManager.Log("Deleting temporary folder..."); + tempFolder.Delete(); + + LogManager.Log("Upload completed."); + }); + } + + /// <summary> + /// Displays a bug submission dialog. When confirmed, will submit the specified bug. + /// </summary> + /// <param name="bug">The bug.</param> + /// <returns></returns> + public async Task ShowBugReportDialog(Bug bug) + { + var vm = await NotificationProvider.ShowDialog(new BugReportViewVM(bug)); + if (vm.DialogResult) + { + var snackbar = NotificationProvider.PushProgressSnackbar("Report Issue", "Submitting report..."); + + try + { + await SubmitBug(vm.Bug); + snackbar.ProgressCompleted("Issue submitted successfully. Thank you!", TimeSpan.FromSeconds(5)); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error submitting bug report."); + snackbar.ProgressFailed("Error occurred while trying to submit the report.", TimeSpan.FromSeconds(2)); + await NotificationProvider.ShowError($"Error occurred while trying to submit the report.\n{ex.FlattenMessage()}"); + } + } + } + + /// <summary> + /// Displays a bug submission dialog. When confirmed, will submit the new created bug. + /// </summary> + /// <returns></returns> + public Task ShowBugReportDialog() + { + return ShowBugReportDialog(null); + } + + private async void ApplicationManager_ApplicationReady(object sender, EventArgs e) + { + if (!_isInitialized) + { + try + { + await Initialize(); + } + catch { } + } + } + + private async Task Initialize() + { + if (await ConnectivityProvider.CheckOnlineAsync()) + { + try + { + _bugReportingInfoResponse = await Services.BugReportingService.GetBugReportingInfo(); + _tfsClient = new TeamFoundationServiceClient(_bugReportingInfoResponse.CollectionUrl, String.Empty, _bugReportingInfoResponse.PersonalToken); + Project = await _tfsClient.GetProject("Tango"); + _isInitialized = true; + } + catch (Exception ex) + { + throw LogManager.Log(ex, "Error initializing bug reporter."); + } + } + else + { + throw LogManager.Log(new InternetConnectionException()); + } + } + + private string[] GetLogFiles(FileLogger logger) + { + string[] fileEntries = new string[1]; + fileEntries[0] = logger.LogFile; + string fileName = Path.GetFileNameWithoutExtension(logger.LogFile); + int indexPos = fileName.IndexOf(FileLogger.FILE_SET_EXTENSION); + if (indexPos > 0) + { + string extension = Path.GetExtension(logger.LogFile); + fileName = fileName.Substring(0, indexPos); + fileEntries = Directory.GetFiles(logger.Folder, $"{fileName}*{extension}").Where(x => Path.GetFileName(x).StartsWith(logger.Tag)).OrderBy(x => x.Length).ThenBy(x => x).ToArray(); + } + return fileEntries; + } + + private String GetOsVersion() + { + try + { + string r = ""; + using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem")) + { + ManagementObjectCollection information = searcher.Get(); + if (information != null) + { + foreach (ManagementObject obj in information) + { + r = obj["Caption"].ToString() + " - " + obj["OSArchitecture"].ToString(); + } + } + r = r.Replace("NT 5.1.2600", "XP"); + r = r.Replace("NT 5.2.3790", "Server 2003"); + return r; + } + } + catch + { + return Environment.OSVersion.ToString(); + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/SystemInformationModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/SystemInformationModel.cs new file mode 100644 index 000000000..fd1b4fdd8 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/SystemInformationModel.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; + +namespace Tango.FSE.UI.BugReporting +{ + public class SystemInformationModel + { + public String ApplicationVersion { get; set; } + public String EmbeddedVersion { get; set; } + public String UserName { get; set; } + public String UserEmail { get; set; } + public String HostName { get; set; } + public String OsVersion { get; set; } + public Machine Machine { get; set; } + public String Description { get; set; } + public String Comments { get; set; } + public String Exception { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/SystemInformationTemplate.cshtml b/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/SystemInformationTemplate.cshtml new file mode 100644 index 000000000..d63aa4f95 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/SystemInformationTemplate.cshtml @@ -0,0 +1,82 @@ +@{ + Tango.FSE.UI.BugReporting.SystemInformationModel vm = Model as Tango.FSE.UI.BugReporting.SystemInformationModel; +} + +<div> + + <div style="font-size:16pt;text-decoration:underline">Description</div> + <div style="margin-top:10px;font-size:8pt">@vm.Description</div> + + <div style="font-size:16pt;text-decoration:underline;margin-top:10px">Comments</div> + <div style="margin-top:10px;font-size:8pt">@vm.Comments</div> + + <div style="font-size:16pt;text-decoration:underline;margin-top:10px">Exception</div> + <div style="margin-top:10px;font-size:8pt">@vm.Exception</div> + + <div style="font-size:16pt;text-decoration:underline;margin-top:10px">System Information</div> + <table style="margin-top:10px"> + <tbody> + + <tr> + <td><b>Application Version:</b></td> + <td>@vm.ApplicationVersion</td> + </tr> + + <tr> + <td><b>Embedded Version:</b></td> + <td>@vm.EmbeddedVersion</td> + </tr> + + <tr> + <td><b>Windows Version:</b></td> + <td>@vm.OsVersion</td> + </tr> + + <tr> + <td><b>Host Name:</b></td> + <td>@vm.HostName</td> + </tr> + + <tr> + <td><b>User:</b></td> + <td>@vm.UserName (@vm.UserEmail)</td> + </tr> + + </tbody> + </table> + + <div style="font-size:16pt;text-decoration:underline;margin-top:10px">Machine</div> + + @if (vm.Machine != null) + { + <table style="margin-top:10px"> + <tbody> + + <tr> + <td><b>Organization:</b></td> + <td>@vm.Machine.Organization.Name</td> + </tr> + + <tr> + <td><b>Name:</b></td> + <td>@vm.Machine.Name</td> + </tr> + + <tr> + <td><b>S/N:</b></td> + <td>@vm.Machine.SerialNumber</td> + </tr> + + <tr> + <td><b>Version:</b></td> + <td>@vm.Machine.MachineVersion.Version</td> + </tr> + + </tbody> + </table> + } + else + { + <div style="color:Red;margin-top:10px">NOT CONNECTED</div> + } +</div>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Console/DefaultConsoleProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Console/DefaultConsoleProvider.cs index 09d37f617..730c36d45 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Console/DefaultConsoleProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Console/DefaultConsoleProvider.cs @@ -8,6 +8,7 @@ using Tango.Core; using Tango.Core.DI; using Tango.FSE.Common.Connection; using Tango.FSE.Common.Console; +using Tango.FSE.Common.Notifications; namespace Tango.FSE.UI.Console { @@ -21,6 +22,9 @@ namespace Tango.FSE.UI.Console { private IMachineProvider MachineProvider { get; set; } + [TangoInject] + private INotificationProvider NotificationProvider { get; set; } + #region Events /// <summary> @@ -109,6 +113,7 @@ namespace Tango.FSE.UI.Console catch (Exception ex) { LogManager.Log(ex, "Error getting remote machine current console directory. Console provider could not be initialized."); + NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Could not initialize the remote command prompt console."); } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportView.xaml new file mode 100644 index 000000000..ce365d828 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportView.xaml @@ -0,0 +1,48 @@ +<UserControl x:Class="Tango.FSE.UI.Dialogs.BugReportView" + 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:material="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:local="clr-namespace:Tango.FSE.UI.Dialogs" + mc:Ignorable="d" + Width="700" Height="600" d:DataContext="{d:DesignInstance Type=local:BugReportViewVM, IsDesignTimeCreatable=False}" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> + <DockPanel Margin="10"> + + <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> + <material:PackIcon Width="42" Height="42" VerticalAlignment="Center" Kind="Bug" Foreground="{StaticResource FSE_ErrorBrush}" /> + <TextBlock VerticalAlignment="Center" Text="Report Issue" Margin="10 0 0 0" FontSize="{StaticResource FSE_LargeFontSize}"></TextBlock> + </StackPanel> + + <Grid Margin="0 20 0 0" DockPanel.Dock="Top"> + <DockPanel> + <StackPanel DockPanel.Dock="Top"> + + <TextBlock Foreground="{StaticResource FSE_GrayBrush}" TextWrapping="Wrap"> + <Run>It looks like we have some internal issues.</Run> + <LineBreak/> + <Run>Help us improve your experience by submitting a report and our team will be notified.</Run> + </TextBlock> + + <TextBox Margin="0 20" IsReadOnly="{Binding IsEditable,Converter={StaticResource BooleanInverseConverter}}" Text="{Binding Bug.Title}" material:HintAssist.Hint="Title" material:HintAssist.IsFloating="True"></TextBox> + + <StackPanel Margin="0 10 0 0"> + <DockPanel> + <material:PackIcon Kind="Pencil" /> + <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_SmallFontSize}">What Happened ?</TextBlock> + </DockPanel> + <TextBox Background="{StaticResource FSE_PrimaryBackgroundBrush}" IsEnabled="{Binding IsEditable}" Text="{Binding Bug.Description,UpdateSourceTrigger=PropertyChanged}" Margin="0 3 0 0" Style="{StaticResource FSE_Rounded_Corners_TextBox_Multiline}" AcceptsReturn="True" Height="200"></TextBox> + </StackPanel> + </StackPanel> + + <DockPanel Margin="0 20 0 0"> + <DockPanel DockPanel.Dock="Top"> + <material:PackIcon Kind="UserAlertOutline" /> + <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_SmallFontSize}">Additional Comments</TextBlock> + </DockPanel> + <TextBox Text="{Binding Bug.Comments,UpdateSourceTrigger=PropertyChanged}" Margin="0 2 0 0" Style="{StaticResource FSE_Rounded_Corners_TextBox_Multiline}" AcceptsReturn="True"></TextBox> + </DockPanel> + </DockPanel> + </Grid> + </DockPanel> +</UserControl> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportView.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportView.xaml.cs new file mode 100644 index 000000000..08bd855e7 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportView.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.UI.Dialogs +{ + /// <summary> + /// Interaction logic for BugReportView.xaml + /// </summary> + public partial class BugReportView : UserControl + { + public BugReportView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportViewVM.cs new file mode 100644 index 000000000..397510ef2 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportViewVM.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.DI; +using Tango.FSE.Common; +using Tango.FSE.Common.BugReporting; +using Tango.FSE.Common.Notifications; + +namespace Tango.FSE.UI.Dialogs +{ + public class BugReportViewVM : FSEDialogViewVM + { + [TangoInject] + private INotificationProvider NotificationProvider { get; set; } + + public Bug Bug { get; set; } + public bool IsEditable { get; set; } + + public BugReportViewVM() + { + TangoIOC.Default.Inject(this); + IsEditable = true; + Bug = new Bug(); + CanClose = true; + OKText = "SUBMIT"; + HasDefault = true; + } + + public BugReportViewVM(Bug bug) : this() + { + if (bug != null) + { + Bug = bug; + IsEditable = false; + } + } + + protected override void Accept() + { + if (Bug.Title.IsNotNullOrEmpty()) + { + base.Accept(); + } + else + { + NotificationProvider.ShowError("Report title cannot remain empty."); + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs index 8381133bf..3ab27fe1e 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Tango.Core; +using Tango.Core.DI; using Tango.Core.ExtensionMethods; using Tango.Core.IO; using Tango.Core.Threading; @@ -15,6 +16,7 @@ using Tango.FileSystem; using Tango.FileSystem.Network; using Tango.FSE.Common.Connection; using Tango.FSE.Common.FileSystem; +using Tango.FSE.Common.Notifications; using Tango.Transport; using Tango.Transport.Transporters; using Tango.WebRTC; @@ -38,6 +40,9 @@ namespace Tango.FSE.UI.FileSystem private const int WEB_RTC_MAX_RETRIES = 8; //Maximum number of retries per chunk for the WebRTC channel until falling back to standard channel. private List<FileSystemHandler> _activeHandlers; + [TangoInject] + private INotificationProvider NotificationProvider { get; set; } + #region Properties private bool _enableWebRTC; @@ -170,6 +175,7 @@ namespace Tango.FSE.UI.FileSystem { IsWebRtcAvailable = false; LogManager.Log(ex, "Error initializing FileSystem via WebRTC."); + NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Could not initialize the remote file system fast channel."); } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs index 5d38d1ac9..fb797cae6 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs @@ -20,6 +20,7 @@ using System.ComponentModel; using System.Windows.Data; using MaterialDesignThemes.Wpf; using Tango.FSE.Common.Core; +using Tango.FSE.Common.BugReporting; namespace Tango.FSE.UI.Notifications { @@ -34,6 +35,9 @@ namespace Tango.FSE.UI.Notifications private ConcurrentQueue<PendingNotification<DialogAndView, DialogViewVM>> _pendingDialogs; private List<AppButton> _appButtons; + [TangoInject(TangoInjectMode.WhenAvailable)] + public IBugReporter BugReporter { get; set; } + private bool _notificationsVisible; /// <summary> /// Gets or sets a value indicating whether to allow notifications visibility. @@ -203,6 +207,7 @@ namespace Tango.FSE.UI.Notifications Type = MessageType.Error, }); } + /// <summary> /// Shows an information message box. /// </summary> @@ -334,12 +339,12 @@ namespace Tango.FSE.UI.Notifications vm.CancelText = cancelText; } - vm.Accepted += () => + vm.Accepted += () => { CurrentInputBox = null; source.SetResult(new InputBoxResult() { Confirmed = true, Input = vm.Input }); }; - vm.Canceled += () => + vm.Canceled += () => { CurrentInputBox = null; source.SetResult(new InputBoxResult() { Confirmed = false, Input = vm.Input }); @@ -443,13 +448,13 @@ namespace Tango.FSE.UI.Notifications TaskCompletionSource<DialogViewVM> source = new TaskCompletionSource<DialogViewVM>(); - datacontext.Accepted += () => + datacontext.Accepted += () => { LogManager.Log($"Dialog '{view.GetType().Name}' accepted."); OnDialogClosed(); source.SetResult(datacontext); }; - datacontext.Canceled += () => + datacontext.Canceled += () => { LogManager.Log($"Dialog '{view.GetType().Name}' canceled."); OnDialogClosed(); @@ -713,6 +718,42 @@ namespace Tango.FSE.UI.Notifications } /// <summary> + /// Display a new error SnackBar. Pressing the snack bar will display the issue reporting dialog. + /// The snack bar timeout is 10 seconds. + /// </summary> + /// <param name="exception">The exception.</param> + /// <param name="title">The title.</param> + /// <param name="message">The message.</param> + /// <returns></returns> + public SnackbarItem PushErrorReportingSnackbar(Exception exception, String title, String message) + { + return PushSnackbarItem(MessageType.Error, title, true, $"{message}\nTap to report this issue.", TimeSpan.FromSeconds(20), null, () => + { + BugReporter.ShowBugReportDialog(new Bug() + { + Type = BugType.FSE, + Description = message, + Exception = exception, + Title = title + " - " + message, + }); + }); + } + + /// <summary> + /// Displays a indeterminate progress Snackbar. Should use <see cref="M:Tango.FSE.Common.Notifications.SnackbarItem.ProgressCompleted(System.String,System.Nullable{System.TimeSpan})" /> and <see cref="M:Tango.FSE.Common.Notifications.SnackbarItem.ProgressFailed(System.String,System.Nullable{System.TimeSpan})" />. + /// </summary> + /// <param name="title">The title.</param> + /// <param name="message">The message.</param> + /// <returns></returns> + public SnackbarItem PushProgressSnackbar(String title, String message) + { + SnackbarItem item = new SnackbarItem(MessageType.Busy, title, false, message, null, () => { }, () => { }); + item.IsProgress = true; + PushSnackbarItem(item); + return item; + } + + /// <summary> /// Pops the snack bar item. /// </summary> /// <param name="snackbarItem">The snack bar item.</param> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Performance/DefaultPerformanceProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Performance/DefaultPerformanceProvider.cs index c82e4fcc5..e0ca2265c 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Performance/DefaultPerformanceProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Performance/DefaultPerformanceProvider.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Tango.Core; using Tango.Core.DI; using Tango.FSE.Common.Connection; +using Tango.FSE.Common.Notifications; using Tango.FSE.Common.Performance; using Tango.PPC.Shared.Performance; @@ -24,6 +25,9 @@ namespace Tango.FSE.UI.Performance /// </summary> private IMachineProvider MachineProvider { get; set; } + [TangoInject] + private INotificationProvider NotificationProvider { get; set; } + /// <summary> /// Occurs when a new performance monitoring frame is available. /// </summary> @@ -55,6 +59,7 @@ namespace Tango.FSE.UI.Performance if (!(ex is Transport.TransporterDisconnectedException)) { LogManager.Log(ex, "Error starting remote PPC performance updates."); + NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Error starting remote PPC performance updates."); } }, () => { @@ -64,6 +69,7 @@ namespace Tango.FSE.UI.Performance catch (Exception ex) { LogManager.Log(ex, "Error starting remote PPC performance updates."); + NotificationProvider.PushErrorReportingSnackbar(ex, "PPC Module Error", "Error starting remote PPC performance updates."); } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index 4fe0c09aa..24fbc3ae9 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -81,6 +81,7 @@ <Reference Include="System.Drawing" /> <Reference Include="System.IO.Compression" /> <Reference Include="System.IO.Compression.FileSystem" /> + <Reference Include="System.Management" /> <Reference Include="System.Reactive.Core, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> <HintPath>..\..\packages\System.Reactive.Core.3.1.1\lib\net46\System.Reactive.Core.dll</HintPath> </Reference> @@ -121,11 +122,17 @@ <SubType>Designer</SubType> </ApplicationDefinition> <Compile Include="Authentication\DefaultAuthenticationProvider.cs" /> + <Compile Include="BugReporting\DefaultBugReporter.cs" /> + <Compile Include="BugReporting\SystemInformationModel.cs" /> <Compile Include="Connection\DefaultMachineProvider.cs" /> <Compile Include="Connectivity\DefaultConnectivityProvider.cs" /> <Compile Include="Console\DefaultConsoleProvider.cs" /> <Compile Include="Contracts\ILayoutView.cs" /> <Compile Include="Diagnostics\DefaultDiagnosticsProvider.cs" /> + <Compile Include="Dialogs\BugReportView.xaml.cs"> + <DependentUpon>BugReportView.xaml</DependentUpon> + </Compile> + <Compile Include="Dialogs\BugReportViewVM.cs" /> <Compile Include="Dialogs\MachineConnectionBaseViewVM.cs" /> <Compile Include="Dialogs\MachineConnectionEmulatorView.xaml.cs"> <DependentUpon>MachineConnectionEmulatorView.xaml</DependentUpon> @@ -219,6 +226,10 @@ <Compile Include="Views\MainView.xaml.cs"> <DependentUpon>MainView.xaml</DependentUpon> </Compile> + <Page Include="Dialogs\BugReportView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Dialogs\MachineConnectionEmulatorView.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> @@ -321,6 +332,7 @@ <EmbeddedResource Include="Storage\ExplorerControlForms.resx"> <DependentUpon>ExplorerControlForms.cs</DependentUpon> </EmbeddedResource> + <EmbeddedResource Include="BugReporting\SystemInformationTemplate.cshtml" /> <None Include="packages.config" /> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> @@ -349,6 +361,10 @@ <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project> <Name>Tango.BL</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.CodeGeneration\Tango.CodeGeneration.csproj"> + <Project>{caedae94-11ed-473c-888a-268a6d38cd20}</Project> + <Name>Tango.CodeGeneration</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Console\Tango.Console.csproj"> <Project>{199E8359-CAD3-433D-9EED-2027652B24A4}</Project> <Name>Tango.Console</Name> @@ -389,6 +405,10 @@ <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project> <Name>Tango.SharedUI</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.TFS\Tango.TFS.csproj"> + <Project>{998f8471-dc1b-41b6-9d96-354e1b4e7a32}</Project> + <Name>Tango.TFS</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Transport\Tango.Transport.csproj"> <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> <Name>Tango.Transport</Name> @@ -492,4 +512,62 @@ </PropertyGroup> <Error Condition="!Exists('..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets'))" /> </Target> + <PropertyGroup> + <PostBuildEvent>RD /S /Q "$(TargetDir)cs\" +RD /S /Q "$(TargetDir)da\" +RD /S /Q "$(TargetDir)de\" +RD /S /Q "$(TargetDir)es\" +RD /S /Q "$(TargetDir)fa\" +RD /S /Q "$(TargetDir)fi\" +RD /S /Q "$(TargetDir)fr\" +RD /S /Q "$(TargetDir)it\" +RD /S /Q "$(TargetDir)ko\" +RD /S /Q "$(TargetDir)mk\" +RD /S /Q "$(TargetDir)nl\" +RD /S /Q "$(TargetDir)pl\" +RD /S /Q "$(TargetDir)pt\" +RD /S /Q "$(TargetDir)ru\" +RD /S /Q "$(TargetDir)sv\" +RD /S /Q "$(TargetDir)tr\" +RD /S /Q "$(TargetDir)zh-CN\" +RD /S /Q "$(TargetDir)af\" +RD /S /Q "$(TargetDir)ar\" +RD /S /Q "$(TargetDir)dn-BD\" +RD /S /Q "$(TargetDir)el\" +RD /S /Q "$(TargetDir)fi-FI\" +RD /S /Q "$(TargetDir)fr-BE\" +RD /S /Q "$(TargetDir)he\" +RD /S /Q "$(TargetDir)hr\" +RD /S /Q "$(TargetDir)hu\" +RD /S /Q "$(TargetDir)id\" +RD /S /Q "$(TargetDir)ja\" +RD /S /Q "$(TargetDir)lv\" +RD /S /Q "$(TargetDir)nb\" +RD /S /Q "$(TargetDir)ro\" +RD /S /Q "$(TargetDir)sk\" +RD /S /Q "$(TargetDir)sl\" +RD /S /Q "$(TargetDir)sr\" +RD /S /Q "$(TargetDir)sr-Latn\" +RD /S /Q "$(TargetDir)uk\" +RD /S /Q "$(TargetDir)uz-Cyrl-UZ\" +RD /S /Q "$(TargetDir)uz-Latn-UZ\" +RD /S /Q "$(TargetDir)vi\" +RD /S /Q "$(TargetDir)zh-Hans\" +RD /S /Q "$(TargetDir)zh-Hant\" +RD /S /Q "$(TargetDir)bg\" +RD /S /Q "$(TargetDir)bn-BD\" +RD /S /Q "$(TargetDir)nb-NO\" +RD /S /Q "$(TargetDir)pt-BR\" + +copy /Y "$(SolutionDir)Referenced Assemblies\mscoree.dll" "$(TargetDir)" +copy /Y "$(SolutionDir)Referenced Assemblies\msvcp140d.dll" "$(TargetDir)" +copy /Y "$(SolutionDir)Referenced Assemblies\ucrtbased.dll" "$(TargetDir)" +copy /Y "$(SolutionDir)Referenced Assemblies\vcruntime140.dll" "$(TargetDir)" +copy /Y "$(SolutionDir)Referenced Assemblies\vcruntime140d.dll" "$(TargetDir)" +copy /Y "$(SolutionDir)Referenced Assemblies\Microsoft.WITDataStore32.dll" "$(TargetDir)" + +if $(ConfigurationName) == Release del *.xml +if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" +if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)Roslyn\"</PostBuildEvent> + </PropertyGroup> </Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs index f89c2010f..4d9c49a74 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs @@ -44,6 +44,8 @@ using Tango.FSE.UI.Storage; using Tango.FSE.UI.SystemInfo; using Tango.FSE.UI.Threading; using Tango.FSE.UI.ViewModels; +using Tango.FSE.Common.BugReporting; +using Tango.FSE.UI.BugReporting; namespace Tango.FSE.UI { @@ -52,6 +54,7 @@ namespace Tango.FSE.UI static ViewModelLocator() { TangoIOC.Default.Unregister<IConnectivityProvider>(); + TangoIOC.Default.Unregister<FSEWebClient>(); TangoIOC.Default.Unregister<IDispatcherProvider>(); TangoIOC.Default.Unregister<INotificationProvider>(); TangoIOC.Default.Unregister<IAuthenticationProvider>(); @@ -70,6 +73,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Unregister<IStorageProvider>(); TangoIOC.Default.Unregister<FSEServicesContainer>(); TangoIOC.Default.Unregister<IMachineUpdatesProvider>(); + TangoIOC.Default.Unregister<IBugReporter>(); //TangoIOC.Default.Unregister<ExternalBridgeScanner>(); //TangoIOC.Default.Unregister<IDiagnosticsFrameProvider>(); //TangoIOC.Default.Unregister<IEventLogger>(); @@ -88,6 +92,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Register<IFSEModuleLoader, DefaultFSEModuleLoader>(); TangoIOC.Default.Register<INavigationManager, DefaultNavigationManager>(); TangoIOC.Default.Register<IFSEApplicationManager, DefaultFSEApplicationManager>(); + TangoIOC.Default.Register<IBugReporter, DefaultBugReporter>(); TangoIOC.Default.Register<IRemoteDesktopProvider, DefaultRemoteDesktopProvider>(); TangoIOC.Default.Register<IResolutionService, DefaultResolutionService>(); TangoIOC.Default.Register<IConsolProvider, DefaultConsoleProvider>(); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs index c7de0d308..3564f9b7b 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs @@ -121,6 +121,11 @@ namespace Tango.FSE.UI.ViewModels /// </summary> public RelayCommand LogoutCommand { get; set; } + /// <summary> + /// Opens the bug report dialog. + /// </summary> + public RelayCommand ReportIssueCommand { get; set; } + #endregion #region Constructors @@ -143,6 +148,8 @@ namespace Tango.FSE.UI.ViewModels _transportOutActionTimer = new ActionTimer(TimeSpan.FromMilliseconds(50)); _transportInActionTimer = new ActionTimer(TimeSpan.FromMilliseconds(50)); + + ReportIssueCommand = new RelayCommand(OpenBugReportDialog); } #endregion @@ -280,6 +287,11 @@ namespace Tango.FSE.UI.ViewModels AuthenticationProvider.LogOut(); } + private void OpenBugReportDialog() + { + BugReporter.ShowBugReportDialog(); + } + #endregion //Not used diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs index 441b2f10b..13950af0e 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs @@ -33,7 +33,7 @@ namespace Tango.FSE.UI.ViewModels catch (Exception ex) { LogManager.Log(ex, "Error retrieving environments from gateway."); - await NotificationProvider.ShowError("Error retrieving environments from gateway."); + await NotificationProvider.ShowError("Error retrieving environments from gateway service."); ApplicationManager.ShutDown(); } finally diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml index 42e2c7af8..c75579215 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml @@ -112,8 +112,9 @@ </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 0 5 0"> - <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}" VerticalAlignment="Center"></TextBlock> - <commonControls:ToggleIconButton FontSize="{StaticResource FSE_SmallerFontSize}" Margin="5 0 0 0" UncheckedText="Open Log Viewer" CheckedText="Close Log Viewer" TextAlignment="Left" Height="24" Width="Auto" Checked="OnLogsChecked" Unchecked="OnLogsUnChecked" VerticalAlignment="Center" IsChecked="{Binding IsLogsOpened}" CheckedIcon="ChevronDoubleDown" UncheckedIcon="ChevronDoubleUp" /> + <commonControls:IconButton Command="{Binding ReportIssueCommand}" ToolTip="Report Issue" ToolTipService.Placement="Top" Icon="Bug" Foreground="{StaticResource FSE_ErrorBrush}" Height="26" Cursor="Hand" Margin="0 -2 0 0" VerticalAlignment="Center"></commonControls:IconButton> + <Rectangle Width="1" HorizontalAlignment="Center" Stroke="{StaticResource FSE_BorderBrush}" Margin="10 4"></Rectangle> + <commonControls:ToggleIconButton Cursor="Hand" FontSize="{StaticResource FSE_SmallerFontSize}" Margin="5 0 0 0" UncheckedText="Open Log Viewer" CheckedText="Close Log Viewer" TextAlignment="Left" Height="24" Width="Auto" Checked="OnLogsChecked" Unchecked="OnLogsUnChecked" VerticalAlignment="Center" IsChecked="{Binding IsLogsOpened}" CheckedIcon="ChevronDoubleDown" UncheckedIcon="ChevronDoubleUp" /> </StackPanel> </Grid> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml index e3f12232e..6982ee92a 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml @@ -48,7 +48,7 @@ <ItemsControl FocusVisualStyle="{x:Null}" ItemsSource="{Binding NotificationProvider.SnackbarItems}"> <ItemsControl.ItemTemplate> <DataTemplate> - <Border Margin="0 5" Height="60"> + <Border Margin="0 5" Height="65"> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseDown"> <i:InvokeCommandAction Command="{Binding PressCommand}" /> @@ -77,6 +77,7 @@ </Style.Triggers> </Style> </Border.Style> + <Grid> <DockPanel> <Rectangle DockPanel.Dock="Top" Height="2" Fill="{Binding ElementName=msgIcon,Path=Foreground}"></Rectangle> <DockPanel> @@ -98,17 +99,25 @@ <Setter Property="Foreground" Value="{StaticResource FSE_SuccessBrush}"></Setter> <Setter Property="Kind" Value="Check"></Setter> </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="Busy"> + <Setter Property="Foreground" Value="{StaticResource FSE_InfoBrush}"></Setter> + <Setter Property="Kind" Value="Clock"></Setter> + </DataTrigger> </Style.Triggers> </Style> </material:PackIcon.Style> </material:PackIcon> <commonControls:IconButton Visibility="{Binding CanClose,Converter={StaticResource BooleanToVisibilityConverter}}" Margin="0 -5 -3 0" Icon="Close" DockPanel.Dock="Right" Padding="8" Command="{Binding CloseCommand}" HorizontalAlignment="Right" VerticalAlignment="Top" Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"/> - <StackPanel Margin="10 8 0 0"> - <TextBlock TextWrapping="Wrap" Text="{Binding Title}" FontSize="{StaticResource FSE_SmallFontSize}"></TextBlock> - <TextBlock TextWrapping="Wrap" Margin="0 2 0 0" Text="{Binding Message}" FontSize="{StaticResource FSE_SmallerFontSize}" Foreground="{StaticResource FSE_GrayBrush}"></TextBlock> + + <StackPanel Margin="10 8 0 0" Width="250"> + <TextBlock TextWrapping="Wrap" Text="{Binding Title}" FontSize="{StaticResource FSE_SmallFontSize}"></TextBlock> + <TextBlock TextWrapping="Wrap" Margin="0 2 0 0" TextTrimming="CharacterEllipsis" Text="{Binding Message}" FontSize="{StaticResource FSE_SmallerFontSize}" Foreground="{StaticResource FSE_GrayBrush}"></TextBlock> </StackPanel> </DockPanel> </DockPanel> + + <ProgressBar Height="Auto" Opacity="0.2" Width="Auto" IsIndeterminate="True" Visibility="{Binding IsProgress,Converter={StaticResource BooleanToVisibilityConverter}}" /> + </Grid> </Border> </DataTemplate> </ItemsControl.ItemTemplate> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/BugReportingInfoRequest.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/BugReportingInfoRequest.cs new file mode 100644 index 000000000..ee52e3368 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/BugReportingInfoRequest.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.FSE.Web.Messages +{ + public class BugReportingInfoRequest : WebRequestMessage + { + + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/BugReportingInfoResponse.cs b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/BugReportingInfoResponse.cs new file mode 100644 index 000000000..f5f326bb8 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/BugReportingInfoResponse.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Transport.Web; + +namespace Tango.FSE.Web.Messages +{ + public class BugReportingInfoResponse : WebResponseMessage + { + public String CollectionUrl { get; set; } + public String PersonalToken { get; set; } + public String UserEmail { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj index 166162caf..299240d60 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj @@ -41,6 +41,8 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> + <Compile Include="Messages\BugReportingInfoRequest.cs" /> + <Compile Include="Messages\BugReportingInfoResponse.cs" /> <Compile Include="Messages\LoginRequest.cs" /> <Compile Include="Messages\LoginResponse.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> diff --git a/Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs b/Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs index fde08b968..14b9a7562 100644 --- a/Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs +++ b/Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs @@ -103,36 +103,43 @@ namespace Tango.Transport.Web } catch (HttpRequestException ex) { - String message = JObject.Parse(data).GetValue("Message").ToString(); - Exception exception = null; - try { - String exceptionMessage = JObject.Parse(data).GetValue("ExceptionMessage").ToString(); - String exceptionType = JObject.Parse(data).GetValue("ExceptionType").ToString(); - String stackTrace = JObject.Parse(data).GetValue("StackTrace").ToString(); - Type type = GetType(exceptionType); - if (type != null) + String message = JObject.Parse(data).GetValue("Message").ToString(); + Exception exception = null; + + try { - exception = Activator.CreateInstance(type, new object[] { exceptionMessage + "\n" + stackTrace }) as Exception; - + String exceptionMessage = JObject.Parse(data).GetValue("ExceptionMessage").ToString(); + String exceptionType = JObject.Parse(data).GetValue("ExceptionType").ToString(); + String stackTrace = JObject.Parse(data).GetValue("StackTrace").ToString(); + Type type = GetType(exceptionType); + if (type != null) + { + exception = Activator.CreateInstance(type, new object[] { exceptionMessage + "\n" + stackTrace }) as Exception; + + } + else + { + exception = new HttpException(exceptionMessage + "\n" + stackTrace); + } } - else + catch { - exception = new HttpException(exceptionMessage + "\n" + stackTrace); + if (message == null) + { + Logging.LogManager.Default.Log($"Error parsing response message!\n{data}"); + } + + throw new HttpRequestException(ex.Message + " " + message); } + + throw exception; } catch { - if (message == null) - { - Logging.LogManager.Default.Log($"Error parsing response message!\n{data}"); - } - - throw new HttpRequestException(ex.Message + " " + message); + throw ex; } - - throw exception; } return JsonConvert.DeserializeObject<Response>(data); diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs index 95a26d78e..dccf2d24c 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs @@ -10,6 +10,7 @@ using Tango.BL.Entities; using Tango.Core; using Tango.Core.Cryptography; using Tango.FSE.Web.Messages; +using Tango.MachineService.Filters; using Tango.Web.Controllers; using Tango.Web.Helpers; using Tango.Web.Security; @@ -104,5 +105,17 @@ namespace Tango.MachineService.Controllers PasswordChangeRequired = user.PasswordChangeRequired }; } + + [HttpPost] + [JwtTokenFilter] + public BugReportingInfoResponse GetBugReportInfo(BugReportingInfoRequest request) + { + return new BugReportingInfoResponse() + { + CollectionUrl = MachineServiceConfig.FSE_TFS_COLLECTION_URL, + PersonalToken = MachineServiceConfig.FSE_TFS_PERSONAL_TOKEN, + UserEmail = MachineServiceConfig.FSE_TFS_USER_EMAIL + }; + } } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs b/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs index 014ef68ba..f781dbb89 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs @@ -17,5 +17,9 @@ namespace Tango.MachineService public static String REFRESH_TOKENS_TABLE_PARTITION => ConfigurationManager.AppSettings[nameof(REFRESH_TOKENS_TABLE_PARTITION)].ToString(); public static bool USE_DB_ACCESS_TOKENS => bool.Parse(ConfigurationManager.AppSettings[nameof(USE_DB_ACCESS_TOKENS)].ToString()); public static String CDN_ENDPOINT => ConfigurationManager.AppSettings[nameof(CDN_ENDPOINT)].ToString(); + + public static String FSE_TFS_COLLECTION_URL => ConfigurationManager.AppSettings[nameof(FSE_TFS_COLLECTION_URL)].ToString(); + public static String FSE_TFS_PERSONAL_TOKEN => ConfigurationManager.AppSettings[nameof(FSE_TFS_PERSONAL_TOKEN)].ToString(); + public static String FSE_TFS_USER_EMAIL => ConfigurationManager.AppSettings[nameof(FSE_TFS_USER_EMAIL)].ToString(); } }
\ No newline at end of file diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Web.config b/Software/Visual_Studio/Web/Tango.MachineService/Web.config index 1da22f45b..2c6408e50 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Web.config +++ b/Software/Visual_Studio/Web/Tango.MachineService/Web.config @@ -31,6 +31,10 @@ <add key="REFRESH_TOKENS_TABLE_PARTITION" value="REFRESH_TOKENS_PART" /> <add key="USE_DB_ACCESS_TOKENS" value="false" /> <add key="CDN_ENDPOINT" value="https://tango.azureedge.net" /> + + <add key="FSE_TFS_COLLECTION_URL" value="https://twinetfs.visualstudio.com" /> + <add key="FSE_TFS_PERSONAL_TOKEN" value="szzfokrceo4rhd4eqi5qpmxn3pa5iwl3q7tlqd36l2m7smz2ynoa" /> + <add key="FSE_TFS_USER_EMAIL" value="fse@twine-s.com" /> </appSettings> <!-- For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367. |
