aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-11 00:54:54 +0300
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-11 00:54:54 +0300
commitcb1b51c238c64f570d73b7dca6a2eee205b2da01 (patch)
treedae3c0d5da9d003cb6860431d763eaad0dd5caf7
parentb4682a3abfe299c19b24752b2fb1ce2477611ec3 (diff)
downloadTango-cb1b51c238c64f570d73b7dca6a2eee205b2da01.tar.gz
Tango-cb1b51c238c64f570d73b7dca6a2eee205b2da01.zip
Implemented FSE bug reporting !!!
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs20
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/LogsViewVM.cs1
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MonitoringViewVM.cs2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/UpdatesViewVM.cs5
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/LogsView.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml4
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/UpdatesView.xaml210
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/CacheEntities/CachedBugInfoResponse.cs17
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServiceBase.cs6
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/FSEServicesContainer.cs6
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/IAuthenticationService.cs6
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Services/BugReportingService.cs66
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Tango.FSE.BL.csproj2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.BL/Web/FSEWebClientBase.cs9
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/Bug.cs44
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/BugType.cs14
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/IBugReporter.cs34
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs7
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/INotificationProvider.cs17
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/MessageType.cs3
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Notifications/SnackbarItem.cs75
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml37
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj3
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs17
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs7
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs318
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/SystemInformationModel.cs23
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/SystemInformationTemplate.cshtml82
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Console/DefaultConsoleProvider.cs5
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportView.xaml48
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/BugReportViewVM.cs52
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs6
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Notifications/DefaultNotificationProvider.cs49
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Performance/DefaultPerformanceProvider.cs6
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj78
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs5
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs12
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml5
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml17
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/BugReportingInfoRequest.cs14
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Web/Messages/BugReportingInfoResponse.cs16
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Web/Tango.FSE.Web.csproj2
-rw-r--r--Software/Visual_Studio/Tango.Transport/Web/WebTransportClient.cs47
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs13
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs4
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Web.config4
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.