diff options
| author | Shlomo Hecht <shlomo@twine-s.com> | 2018-05-02 17:36:54 +0300 |
|---|---|---|
| committer | Shlomo Hecht <shlomo@twine-s.com> | 2018-05-02 17:36:54 +0300 |
| commit | ee697f7a3350d0a97bddee4de3a2ae4f9d285052 (patch) | |
| tree | 2dc2e3bb811b0d89a3c4c51801c1572966fcee7c /Software/Visual_Studio/MachineStudio | |
| parent | 73c4b814f1f28170ae72723568189096413c3564 (diff) | |
| download | Tango-ee697f7a3350d0a97bddee4de3a2ae4f9d285052.tar.gz Tango-ee697f7a3350d0a97bddee4de3a2ae4f9d285052.zip | |
merge
Diffstat (limited to 'Software/Visual_Studio/MachineStudio')
31 files changed, 1394 insertions, 65 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Views/MachineTechView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Views/MachineTechView.xaml index 3d4ecdac1..53fcafb8f 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Views/MachineTechView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Views/MachineTechView.xaml @@ -220,9 +220,9 @@ <Border HorizontalAlignment="Right" Width="220" Margin="10 0 5 8" BorderBrush="Gainsboro" BorderThickness="1 0 1 1" Padding="5"> <Grid> <StackPanel TextElement.FontSize="10" VerticalAlignment="Center" TextElement.Foreground="Gray"> - <TextBlock HorizontalAlignment="Center"><Run FontWeight="SemiBold" FontStyle="Italic">Version Name:</Run> <Run Text="{Binding CurrentDiagnosticsResponse.VersionName,FallbackValue='N/A'}"></Run></TextBlock> - <TextBlock HorizontalAlignment="Center" Margin="0 2 0 0"><Run FontWeight="SemiBold" FontStyle="Italic">Version Number:</Run> <Run Text="{Binding CurrentDiagnosticsResponse.Version,FallbackValue='N/A'}"></Run></TextBlock> - <TextBlock HorizontalAlignment="Center" Margin="0 2 0 0"><Run FontWeight="SemiBold" FontStyle="Italic">Build Date:</Run> <Run Text="{Binding CurrentDiagnosticsResponse.VersionBuildDate,FallbackValue='N/A'}"></Run></TextBlock> + <TextBlock HorizontalAlignment="Center"><Run FontWeight="SemiBold" FontStyle="Italic">Version Name:</Run> <Run Text="{Binding MachineOperator.DeviceInformation.Name,FallbackValue='N/A'}"></Run></TextBlock> + <TextBlock HorizontalAlignment="Center" Margin="0 2 0 0"><Run FontWeight="SemiBold" FontStyle="Italic">Version Number:</Run> <Run Text="{Binding MachineOperator.DeviceInformation.Version,FallbackValue='N/A'}"></Run></TextBlock> + <TextBlock HorizontalAlignment="Center" Margin="0 2 0 0"><Run FontWeight="SemiBold" FontStyle="Italic">Build Date:</Run> <Run Text="{Binding MachineOperator.DeviceInformation.BuildDate,FallbackValue='N/A'}"></Run></TextBlock> <TextBlock HorizontalAlignment="Center" Margin="0 2 0 0"><Run FontWeight="SemiBold" FontStyle="Italic">Diagnostics Frame Size:</Run> <Run Text="{Binding CurrentDiagnosticsResponseSize,Converter={StaticResource NumberToFileSizeConverter},FallbackValue='N/A'}"></Run></TextBlock> </StackPanel> </Grid> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/PermissionToVisibilityConverter.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/PermissionToVisibilityConverter.cs new file mode 100644 index 000000000..08e7d1c12 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/PermissionToVisibilityConverter.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; +using Tango.BL.Entities; +using Tango.BL.Enumerations; +using Tango.Core.DI; +using Tango.MachineStudio.Common.Authentication; + +namespace Tango.MachineStudio.Common.Converters +{ + public class PermissionToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + User user = value as User; + + if (user != null) + { + if (user.HasPermission((Permissions)parameter)) + { + return Visibility.Visible; + } + } + + return Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/IStudioViewModel.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/IStudioViewModel.cs index 35ed50cd9..4203a1e8b 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/IStudioViewModel.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/IStudioViewModel.cs @@ -38,5 +38,10 @@ namespace Tango.MachineStudio.Common /// </summary> /// <param name="args">The arguments.</param> void OnModuleRequest(params object[] args); + + /// <summary> + /// Called when the application has been started + /// </summary> + void OnApplicationStarted(); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IStudioApplicationManager.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IStudioApplicationManager.cs index be793ac81..1de18ac94 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IStudioApplicationManager.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IStudioApplicationManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; using Tango.Integration.Services; namespace Tango.MachineStudio.Common.StudioApplication @@ -53,5 +54,12 @@ namespace Tango.MachineStudio.Common.StudioApplication /// Gets the machine studio application version. /// </summary> String Version { get; } + + /// <summary> + /// Notify the application manager about an external opened window. + /// When application exists. All registered windows will be closed. + /// </summary> + /// <param name="window">The window.</param> + void RegisterOpenedWindow(Window window); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioViewModel.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioViewModel.cs index 9c7e52d23..77fad1fc6 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioViewModel.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioViewModel.cs @@ -13,6 +13,79 @@ namespace Tango.MachineStudio.Common /// <typeparam name="Module">The type of the module.</typeparam> /// <seealso cref="Tango.SharedUI.ViewModel" /> /// <seealso cref="Tango.MachineStudio.Common.IStudioViewModel" /> + public abstract class StudioViewModelInternal : ViewModel, IStudioViewModel + { + /// <summary> + /// Gets or sets a value indicating whether this view model studio module is currently loaded. + /// </summary> + public bool IsModuleLoaded { get; private set; } + + /// <summary> + /// Initializes a new instance of the <see cref="StudioViewModel{Module}"/> class. + /// </summary> + public StudioViewModelInternal() : base() + { + + } + + /// <summary> + /// Called when another module has wants to navigate to this module with some arguments. + /// </summary> + /// <param name="args">The arguments.</param> + public virtual void OnModuleRequest(params object[] args) + { + + } + + /// <summary> + /// Called when the user has navigated out of the module. + /// </summary> + public virtual void OnNavigatedFrom() + { + IsModuleLoaded = false; + } + + /// <summary> + /// Called when the user has navigated in to the module. + /// </summary> + public virtual void OnNavigatedTo() + { + IsModuleLoaded = true; + } + + /// <summary> + /// Called before the application is shutting down. + /// Return false to cancel the shutdown in case an important process is in progress. + /// </summary> + /// <returns></returns> + public virtual Task<bool> OnShutdownRequest() + { + return Task.FromResult(true); + } + + /// <summary> + /// Called when application is shutting down. + /// </summary> + public virtual void OnShuttingDown() + { + + } + + /// <summary> + /// Called when the application has been started + /// </summary> + public virtual void OnApplicationStarted() + { + + } + } + + /// <summary> + /// Represents a Machine Studio view model + /// </summary> + /// <typeparam name="Module">The type of the module.</typeparam> + /// <seealso cref="Tango.SharedUI.ViewModel" /> + /// <seealso cref="Tango.MachineStudio.Common.IStudioViewModel" /> public abstract class StudioViewModel<Module> : ViewModel, IStudioViewModel where Module : IStudioModule { /// <summary> @@ -70,6 +143,14 @@ namespace Tango.MachineStudio.Common { } + + /// <summary> + /// Called when the application has been started + /// </summary> + public virtual void OnApplicationStarted() + { + + } } /// <summary> @@ -91,6 +172,14 @@ namespace Tango.MachineStudio.Common } /// <summary> + /// Called when the application has been started + /// </summary> + public virtual void OnApplicationStarted() + { + + } + + /// <summary> /// Called when another module has wants to navigate to this module with some arguments. /// </summary> /// <param name="args">The arguments.</param> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index e4a2720b9..ac6f84618 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -89,6 +89,7 @@ <DependentUpon>RealTimeGraphControl.xaml</DependentUpon> </Compile> <Compile Include="Controls\TableGrid.cs" /> + <Compile Include="Converters\PermissionToVisibilityConverter.cs" /> <Compile Include="Converters\SecondsToGraphPointsConverter.cs" /> <Compile Include="Diagnostics\DefaultDiagnosticsFrameProvider.cs" /> <Compile Include="Diagnostics\IDiagnosticsFrameProvider.cs" /> @@ -287,5 +288,8 @@ <EmbedInteropTypes>True</EmbedInteropTypes> </COMReference> </ItemGroup> + <ItemGroup> + <Folder Include="MarkupExtensions\" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs index d9c64b9e3..f124ebb54 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs @@ -15,6 +15,11 @@ using Tango.Settings; using Tango.MachineStudio.Common.EventLogging; using Tango.BL.Enumerations; using Tango.Core.DI; +using Tango.MachineStudio.UI.TFS; +using Tango.TFS; +using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.UI.ViewModels; +using Tango.MachineStudio.UI.Views; namespace Tango.MachineStudio.UI { @@ -82,7 +87,26 @@ namespace Tango.MachineStudio.UI Application.Current.Dispatcher.Invoke(() => { - ExceptionWindow exWin = new ExceptionWindow(e.Exception); + WorkItem bug = null; + TeamFoundationServiceExtendedClient tfsClient = null; + INotificationProvider notification = null; + + try + { + tfsClient = TangoIOC.Default.GetInstance<TeamFoundationServiceExtendedClient>(); + notification = TangoIOC.Default.GetInstance<INotificationProvider>(); + + if (tfsClient != null && tfsClient.IsInitialized) + { + bug = tfsClient.CreateBug(); + } + } + catch (Exception ex) + { + Debug.WriteLine(ex.ToString()); + } + + ExceptionWindow exWin = new ExceptionWindow(e.Exception, bug != null); exWin.ShowDialog(); switch (exWin.Resolution) @@ -101,6 +125,31 @@ namespace Tango.MachineStudio.UI LogManager.Log("User selection was to shutdown the application. Restarting..."); Environment.Exit(0); break; + case ExceptionResolutions.Report: + e.TryRecover = true; + LogManager.Log("User selection was to report the issue."); + + if (bug != null) + { + notification.ShowModalDialog<ReportIssueViewVM, ReportIssueView>(new ReportIssueViewVM(tfsClient.Project, bug), async (vm) => + { + using (notification.PushTaskItem("Uploading bug report...")) + { + try + { + tfsClient.FinalizeBug(vm.WorkItem); + await tfsClient.UploadWorkItem(vm.WorkItem); + } + catch (Exception ex) + { + notification.ShowError("An error occurred while trying to create the issue." + Environment.NewLine + ex.Message); + } + } + + }, null); + } + + break; } }); } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/CodeTemplate.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/CodeTemplate.cs new file mode 100644 index 000000000..4b307051f --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/CodeTemplate.cs @@ -0,0 +1,23 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.UI.Console; + +public void OnExecute(ConsoleManager manager) +{ + manager.InvokeUI(() => + { + + var notification = manager.TangoIOC.GetInstance<INotificationProvider>(); + notification.ShowInfo("Hello world!"); + + }); +} + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleManager.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleManager.cs new file mode 100644 index 000000000..e2d525d95 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleManager.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.DI; +using Tango.MachineStudio.Common.Modules; + +namespace Tango.MachineStudio.UI.Console +{ + public class ConsoleManager + { + public TangoIOC TangoIOC { get; set; } + private Action<String> _writeLine; + + public ConsoleManager(Action<String> writeLine) + { + _writeLine = writeLine; + TangoIOC = TangoIOC.Default; + } + + public void WriteLine(String text) + { + _writeLine(text); + } + + public void InvokeUI(Action action) + { + Core.Helpers.ThreadsHelper.InvokeUI(action); + } + + public void StartModule(String name) + { + IStudioModuleLoader loader = TangoIOC.Default.GetInstance<IStudioModuleLoader>(); + var module = loader.AllModules.SingleOrDefault(x => x.Name == name); + TangoIOC.Default.GetInstance<ViewModels.MainViewVM>().StartModule(module); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleOnExecuteParameters.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleOnExecuteParameters.cs new file mode 100644 index 000000000..b06637ccd --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleOnExecuteParameters.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Scripting; + +namespace Tango.MachineStudio.UI.Console +{ + public class ConsoleOnExecuteParameters : OnExecuteParameters + { + /// <summary> + /// Provides access to the script stub manager. + /// </summary> + public ConsoleManager manager; + + /// <summary> + /// Initializes a new instance of the <see cref="StubOnExecuteParameters"/> class. + /// </summary> + /// <param name="manager">The manager.</param> + public ConsoleOnExecuteParameters(ConsoleManager manager) + { + this.manager = manager; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindow.xaml new file mode 100644 index 000000000..22338fea7 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindow.xaml @@ -0,0 +1,223 @@ +<mahapps:MetroWindow x:Class="Tango.MachineStudio.UI.Console.ConsoleWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" + xmlns:views="clr-namespace:Tango.MachineStudio.UI.Views" + xmlns:fa="http://schemas.fontawesome.io/icons/" + xmlns:sharedControls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" + xmlns:console="clr-namespace:Tango.MachineStudio.UI.Console" + xmlns:local="clr-namespace:Tango.MachineStudio.UI.Console" + mc:Ignorable="d" + Title="Developer Console" Height="800" Width="1280" BorderThickness="1" BorderBrush="#ADADAD" d:DataContext="{d:DesignInstance Type=console:ConsoleWindowVM, IsDesignTimeCreatable=False}" DataContext="{Binding ConsoleWindowVM, Source={StaticResource Locator}}" Foreground="Gainsboro"> + + <Window.Resources> + <ResourceDictionary> + <ResourceDictionary.MergedDictionaries> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" /> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/FlatButton.xaml" /> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/VS/Colors.xaml" /> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/VS/Styles.xaml" /> + <ResourceDictionary> + <converters:StringEllipsisConverter x:Key="StringEllipsisConverter" /> + </ResourceDictionary> + </ResourceDictionary.MergedDictionaries> + </ResourceDictionary> + </Window.Resources> + + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="742*"/> + </Grid.RowDefinitions> + + <Menu IsMainMenu="True" BorderThickness="0"> + <MenuItem Header="File"> + <MenuItem Header="New" Command="{Binding NewCommand}"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="FileOutline" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Open" MinWidth="150" Command="{Binding OpenCommand}"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="FolderOutline" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Save" Command="{Binding SaveCommand}"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Save" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Save as" Command="{Binding SaveAsCommand}"> + <MenuItem.Icon> + <Grid> + <fa:ImageAwesome Icon="Save" Width="10" Foreground="Gainsboro" Margin="2" /> + <fa:ImageAwesome Icon="Save" Width="10" Foreground="Gainsboro" Margin="2 -5 -5 2" /> + </Grid> + </MenuItem.Icon> + </MenuItem> + </MenuItem> + <MenuItem Header="Edit"> + <MenuItem Header="Cut" MinWidth="150" Command="Cut"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Cut" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Copy" Command="Copy"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Copy" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Paste" Command="Paste"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Paste" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Undo" Command="Undo"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Undo" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Redo" Command="Redo"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Repeat" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + </MenuItem> + <MenuItem Header="Debug"> + <MenuItem Header="Run (F5)" MinWidth="150" Command="{Binding RunCommand}" > + <MenuItem.Icon> + <fa:ImageAwesome Icon="Play" Width="12" Margin="2"> + <fa:ImageAwesome.Style> + <Style TargetType="fa:ImageAwesome"> + <Setter Property="Foreground" Value="#8DD28A"></Setter> + <Style.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Foreground" Value="Gray"></Setter> + </Trigger> + </Style.Triggers> + </Style> + </fa:ImageAwesome.Style> + </fa:ImageAwesome> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Stop" Command="{Binding StopCommand}" IsEnabled="False"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Stop" Width="12" Margin="2"> + <fa:ImageAwesome.Style> + <Style TargetType="fa:ImageAwesome"> + <Setter Property="Foreground" Value="#F38B76"></Setter> + <Style.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Foreground" Value="Gray"></Setter> + </Trigger> + </Style.Triggers> + </Style> + </fa:ImageAwesome.Style> + </fa:ImageAwesome> + </MenuItem.Icon> + </MenuItem> + </MenuItem> + </Menu> + + <DockPanel Grid.Row="1"> + <materialDesign:ColorZone Background="#2E2E2E" Padding="16" materialDesign:ShadowAssist.ShadowDepth="Depth2" + Mode="PrimaryMid" DockPanel.Dock="Top"> + <DockPanel> + <Grid> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Height="60" HorizontalAlignment="Center"> + <Image Source="/Images/machine-trans.png" RenderOptions.BitmapScalingMode="Fant"></Image> + <TextBlock Text="Machine Studio" VerticalAlignment="Center" Margin="20 0 0 0" FontSize="36"/> + </StackPanel> + </Grid> + </DockPanel> + </materialDesign:ColorZone> + + <Grid> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + + <Grid Grid.Row="1" x:Name="grid"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="467*"/> + <RowDefinition Height="5"/> + <RowDefinition Height="200*"/> + </Grid.RowDefinitions> + + <controls:ScriptEditorControl BorderThickness="0 1 0 0" BorderBrush="#616161" Text="{Binding Code,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" RunCommand="{Binding RunCommand}" StopCommand="{Binding StopCommand}" HighlightTypes="{Binding HighlightTypes}" IntellisenseTypes="{Binding IntellisenseTypes}"></controls:ScriptEditorControl> + + <GridSplitter Grid.Row="1" Background="#101010" Foreground="#202020" BorderBrush="#202020" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> + + + <Grid Grid.Row="2" Background="#1B1B1B"> + <Grid.RowDefinitions> + <RowDefinition Height="20"/> + <RowDefinition Height="57*"/> + </Grid.RowDefinitions> + + <Border BorderThickness="0 0 0 1" BorderBrush="#595959"> + <TextBlock Margin="2" HorizontalAlignment="Center">LOG</TextBlock> + </Border> + + <TextBox x:Name="txtLog" TextChanged="TextBox_TextChanged" FontFamily="Lucida Console" Background="#202020" BorderThickness="0" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" Padding="5" IsReadOnly="True" TextWrapping="Wrap" FontSize="11" Foreground="Gainsboro" Grid.Row="2"></TextBox> + </Grid> + </Grid> + </Grid> + </Grid> + + <Border HorizontalAlignment="Right" Margin="0 -1 10 0" VerticalAlignment="Top" Width="300" Height="40" Padding="5" CornerRadius="0 0 30 30" BorderThickness="1 0 1 1" BorderBrush="DimGray"> + <Border.Style> + <Style TargetType="Border"> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="1" ScaleY="0"></ScaleTransform> + </Setter.Value> + </Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding NotificationProvider.HasTaskItems}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard HandoffBehavior="Compose"> + <Storyboard> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" FillBehavior="HoldEnd" To="1" Duration="00:00:0.2"></DoubleAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + <DataTrigger.ExitActions> + <BeginStoryboard HandoffBehavior="Compose"> + <Storyboard> + <DoubleAnimation BeginTime="00:00:02" FillBehavior="HoldEnd" Storyboard.TargetProperty="RenderTransform.ScaleY" To="0" From="1" Duration="00:00:0.5"></DoubleAnimation> + </Storyboard> + </BeginStoryboard> + </DataTrigger.ExitActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Border.Style> + <Border.Background> + <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> + <GradientStop Color="#03A9F4"/> + <GradientStop Color="#0081BB" Offset="1"/> + </LinearGradientBrush> + </Border.Background> + + <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="20 0 0 0"> + <mahapps:ProgressRing Width="24" Height="24" Foreground="White"></mahapps:ProgressRing> + <TextBlock Text="{Binding NotificationProvider.CurrentTaskItem.Message,Converter={StaticResource StringEllipsisConverter},ConverterParameter=35}" Foreground="White" VerticalAlignment="Center" Margin="10 0 0 0" TextWrapping="Wrap"></TextBlock> + </StackPanel> + </Border> + </Grid> + </DockPanel> + </Grid> +</mahapps:MetroWindow> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindow.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindow.xaml.cs new file mode 100644 index 000000000..de2c728b0 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindow.xaml.cs @@ -0,0 +1,43 @@ +using MahApps.Metro.Controls; +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.Shapes; + +namespace Tango.MachineStudio.UI.Console +{ + /// <summary> + /// Interaction logic for ConsoleWindow.xaml + /// </summary> + public partial class ConsoleWindow : MetroWindow + { + private ConsoleWindowVM _vm; + + public ConsoleWindow() + { + InitializeComponent(); + + this.Loaded += (_, __) => + { + _vm = this.DataContext as ConsoleWindowVM; + _vm.SetLogTextBox(txtLog); + }; + } + + //Auto scroll to bottom of response log each time it is changed. + private void TextBox_TextChanged(object sender, TextChangedEventArgs e) + { + txtLog.SelectionStart = txtLog.Text.Length; + txtLog.ScrollToEnd(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindowVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindowVM.cs new file mode 100644 index 000000000..a3a0a734e --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Console/ConsoleWindowVM.cs @@ -0,0 +1,257 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Threading; +using Tango.Core.Commands; +using Tango.Core.Helpers; +using Tango.MachineStudio.Common.Modules; +using Tango.MachineStudio.Common.Notifications; +using Tango.Scripting; +using Tango.SharedUI; + +namespace Tango.MachineStudio.UI.Console +{ + public class ConsoleWindowVM : ViewModel + { + private IStudioModuleLoader _moduleLoader; + private INotificationProvider _notificatrion; + private TextBox _txtLog; + private String _currentFile; + + + /// <summary> + /// Gets or sets the additional highlight C# types. + /// </summary> + public ObservableCollection<KeyValuePair<String, Type>> HighlightTypes { get; set; } + + internal void SetLogTextBox(TextBox txtLog) + { + _txtLog = txtLog; + } + + /// <summary> + /// Gets or sets the intellisense types. + /// </summary> + public ObservableCollection<KeyValuePair<String, Type>> IntellisenseTypes { get; set; } + + private String _code; + /// <summary> + /// Gets or sets the code. + /// </summary> + public String Code + { + get { return _code; } + set { _code = value; RaisePropertyChangedAuto(); } + } + + private bool _isRunning; + /// <summary> + /// Gets or sets a value indicating whether a stub is currently running. + /// </summary> + public bool IsRunning + { + get { return _isRunning; } + set { _isRunning = value; RaisePropertyChanged(nameof(IsRunning)); InvalidateRelayCommands(); } + } + + /// <summary> + /// Gets or sets the run command. + /// </summary> + public RelayCommand RunCommand { get; set; } + + /// <summary> + /// Gets or sets the stop command. + /// </summary> + public RelayCommand StopCommand { get; set; } + + /// <summary> + /// Gets or sets the clear command. + /// </summary> + public RelayCommand ClearCommand { get; set; } + + /// <summary> + /// Gets or sets the new command. + /// </summary> + public RelayCommand NewCommand { get; set; } + + /// <summary> + /// Gets or sets the open command. + /// </summary> + public RelayCommand OpenCommand { get; set; } + + /// <summary> + /// Gets or sets the save command. + /// </summary> + public RelayCommand SaveCommand { get; set; } + + /// <summary> + /// Gets or sets the save as command. + /// </summary> + public RelayCommand SaveAsCommand { get; set; } + + public ConsoleWindowVM(IStudioModuleLoader moduleLoader, INotificationProvider notification) + { + _moduleLoader = moduleLoader; + _notificatrion = notification; + + RunCommand = new RelayCommand(Run); + StopCommand = new RelayCommand(Stop); + + HighlightTypes = new ObservableCollection<KeyValuePair<string, Type>>(); + IntellisenseTypes = new ObservableCollection<KeyValuePair<string, Type>>(); + + IntellisenseTypes.Add(new KeyValuePair<string, Type>("manager", typeof(ConsoleManager))); + + foreach (var moduleType in moduleLoader.UserModules.SelectMany(x => x.MainViewType.Assembly.GetTypes())) + { + if (!moduleType.FullName.Contains("<") && !moduleType.FullName.Contains(">")) + { + HighlightTypes.Add(new KeyValuePair<string, Type>(moduleType.FullName, moduleType)); + } + } + + foreach (var type in this.GetType().Assembly.GetTypes()) + { + if (!type.FullName.Contains("<") && !type.FullName.Contains(">")) + { + HighlightTypes.Add(new KeyValuePair<string, Type>(type.Name, type)); + } + } + + foreach (var type in typeof(INotificationProvider).Assembly.GetTypes()) + { + if (!type.FullName.Contains("<") && !type.FullName.Contains(">")) + { + HighlightTypes.Add(new KeyValuePair<string, Type>(type.Name, type)); + } + } + + HighlightTypes.Add(new KeyValuePair<string, Type>("Thread", typeof(Thread))); + HighlightTypes.Add(new KeyValuePair<string, Type>("DateTime", typeof(DateTime))); + HighlightTypes.Add(new KeyValuePair<string, Type>("TimeSpan", typeof(TimeSpan))); + HighlightTypes.Add(new KeyValuePair<string, Type>("Dispatcher", typeof(Dispatcher))); + HighlightTypes.Add(new KeyValuePair<string, Type>("Task", typeof(Task))); + HighlightTypes.Add(new KeyValuePair<string, Type>("List", typeof(IList<Object>))); + HighlightTypes.Add(new KeyValuePair<string, Type>("int", typeof(Int32))); + HighlightTypes.Add(new KeyValuePair<string, Type>("double", typeof(Double))); + HighlightTypes.Add(new KeyValuePair<string, Type>("String", typeof(String))); + HighlightTypes.Add(new KeyValuePair<string, Type>("string", typeof(String))); + + foreach (var item in HighlightTypes) + { + IntellisenseTypes.Add(item); + } + + Code = EmbeddedResourceHelper.GetEmbeddedResourceText("Tango.MachineStudio.UI.Console.CodeTemplate.cs"); + + NewCommand = new RelayCommand(CreateNew); + OpenCommand = new RelayCommand(OpenFile); + SaveCommand = new RelayCommand(SaveFile); + SaveAsCommand = new RelayCommand(SaveAsFile); + ClearCommand = new RelayCommand(ClearLog); + } + + private void Stop() + { + + } + + private async void Run() + { + ScriptEngine engine = new ScriptEngine(new ConsoleOnExecuteParameters(new ConsoleManager(WriteLine))); + engine.Stop(); + engine.ReferencedAssemblies.Add(this.GetType()); + engine.ReferencedAssemblies.Add(typeof(INotificationProvider)); + + foreach (var module in _moduleLoader.AllModules) + { + engine.ReferencedAssemblies.Add(module.GetType()); + } + + await engine.Run(Code); + } + + private void WriteLine(String text) + { + InvokeUI(() => + { + _txtLog.AppendText(text); + }); + } + + /// <summary> + /// Clears the log. + /// </summary> + private void ClearLog() + { + _txtLog.Clear(); + } + + /// <summary> + /// Saves the selected script file. + /// </summary> + private void SaveFile() + { + if (_currentFile == null) + { + SaveAsFile(); + } + else + { + File.WriteAllText(_currentFile, Code); + } + } + + /// <summary> + /// Saves the selected script file. + /// </summary> + private void SaveAsFile() + { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Filter = "C# Script Files|*.cs"; + dlg.DefaultExt = ".cs"; + if (dlg.ShowDialog().Value) + { + File.WriteAllText(dlg.FileName, Code); + _currentFile = dlg.FileName; + } + } + + /// <summary> + /// Opens a script from HD. + /// </summary> + private void OpenFile() + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Filter = "C# Script Files|*.cs"; + if (dlg.ShowDialog().Value) + { + OpenFile(dlg.FileName); + } + } + + /// <summary> + /// Opens the file. + /// </summary> + /// <param name="file">The file.</param> + private void OpenFile(String file) + { + Code = File.ReadAllText(file); + _currentFile = file; + } + + private void CreateNew() + { + _txtLog.Clear(); + _currentFile = null; + Code = String.Empty; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/bug-resolved.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/bug-resolved.png Binary files differnew file mode 100644 index 000000000..e49f62923 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/bug-resolved.png diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/StudioApplication/DefaultStudioApplicationManager.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/StudioApplication/DefaultStudioApplicationManager.cs index 0bbcfd313..4c02be2b2 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/StudioApplication/DefaultStudioApplicationManager.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/StudioApplication/DefaultStudioApplicationManager.cs @@ -42,6 +42,22 @@ namespace Tango.MachineStudio.UI.StudioApplication _moduleLoader = moduleLoader; _navigationManager = navigationManager; _openedWindows = new List<Window>(); + + Task.Factory.StartNew(() => + { + while (MainWindow.Instance == null) + { + Thread.Sleep(100); + } + + InvokeUI(() => + { + MainWindow.Instance.ContentRendered += (_, __) => + { + TangoIOC.Default.GetAllInstancesByBase<IStudioViewModel>().ToList().ForEach(x => x.OnApplicationStarted()); + }; + }); + }); } /// <summary> @@ -229,6 +245,11 @@ namespace Tango.MachineStudio.UI.StudioApplication } } + /// <summary> + /// Notify the application manager about an external opened window. + /// When application exists. All registered windows will be closed. + /// </summary> + /// <param name="window">The window.</param> public void RegisterOpenedWindow(Window window) { _openedWindows.Add(window); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/SystemInformationModel.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/SystemInformationModel.cs index eb9ef8012..5dde73744 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/SystemInformationModel.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/SystemInformationModel.cs @@ -15,5 +15,7 @@ namespace Tango.MachineStudio.UI.TFS public String HostName { get; set; } public Machine Machine { get; set; } public String ConfigurationString { get; set; } + public String LoadedHardwareConfigurationString { get; set; } + public String LoadedProcessParametersString { get; set; } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/SystemInformationTemplate.cshtml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/SystemInformationTemplate.cshtml index 7b0c4a896..54db28e32 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/SystemInformationTemplate.cshtml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/SystemInformationTemplate.cshtml @@ -60,11 +60,32 @@ </tbody> </table> - <div style="font-size:20pt;text-decoration:underline;margin-top:10px">Configuration</div> + <div style="font-size:20pt;text-decoration:underline;margin-top:10px">Machine Configuration</div> <div style="white-space:pre;margin-top:10px;font-size:8pt">@vm.ConfigurationString</div> + + <div style="font-size:20pt;text-decoration:underline;margin-top:10px">Hardware Configuration</div> + if (vm.LoadedHardwareConfigurationString != null) + { + <div style="white-space:pre;margin-top:10px;font-size:8pt">@vm.LoadedHardwareConfigurationString</div> + } + else + { + <div style="color:Red;margin-top:10px">NOT SET</div> + } + + <div style="font-size:20pt;text-decoration:underline;margin-top:10px">Process Parameters</div> + + if (vm.LoadedProcessParametersString != null) + { + <div style="white-space:pre;margin-top:10px;font-size:8pt">@vm.LoadedProcessParametersString</div> + } + else + { + <div style="color:Red;margin-top:10px">NOT SET</div> + } } else { - <div style="color:Red;margin-top:10px">Not Connected</div> + <div style="color:Red;margin-top:10px">NOT CONNECTED</div> } </div>
\ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/TeamFoundationServiceExtendedClient.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/TeamFoundationServiceExtendedClient.cs index 27b257e61..79572eb71 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/TeamFoundationServiceExtendedClient.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/TeamFoundationServiceExtendedClient.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using System.Windows; using Tango.BL.Entities; @@ -21,6 +23,13 @@ namespace Tango.MachineStudio.UI.TFS { public Project Project { get; private set; } + private ObservableCollection<WorkItem> _resolvedWorkItems; + public ObservableCollection<WorkItem> ResolvedWorkItems + { + get { return _resolvedWorkItems; } + set { _resolvedWorkItems = value; RaisePropertyChangedAuto(); } + } + private bool _isInitialized; public bool IsInitialized { @@ -30,7 +39,20 @@ namespace Tango.MachineStudio.UI.TFS public TeamFoundationServiceExtendedClient(string collectionURL, string userName, string personalToken) : base(collectionURL, userName, personalToken) { + ResolvedWorkItems = new ObservableCollection<WorkItem>(); + TangoIOC.Default.GetInstance<IAuthenticationProvider>().CurrentUserChanged += TeamFoundationServiceExtendedClient_CurrentUserChanged; + } + private void TeamFoundationServiceExtendedClient_CurrentUserChanged(object sender, User user) + { + if (user != null) + { + Task.Factory.StartNew(async () => + { + Thread.Sleep(5000); + await UpdateCurrentUserResolvedWorkItems(); + }); + } } public Task<WorkItem> UploadWorkItem(WorkItem workItem) @@ -38,14 +60,53 @@ namespace Tango.MachineStudio.UI.TFS return UploadWorkItem(Project, workItem); } + public async Task UpdateCurrentUserResolvedWorkItems() + { + try + { + IStudioApplicationManager app = TangoIOC.Default.GetInstance<IStudioApplicationManager>(); + var items = await GetWorkItemsCreatedBy(Project, GetUserTeamMember()); + items.Where(x => x.StepsToReproduce != null).ToList().ForEach(x => x.StepsToReproduce = x.StepsToReproduce.Replace("<div style=\"white-space:pre;\">", "").Replace("</div>", "")); + ResolvedWorkItems = items.Where(x => x.State == State.Resolved && x.ResolvedReason == ResolvedReason.Fixed && x.IsBuildVersionValid && x.FoundInBuildVersion < Version.Parse(app.Version)).ToObservableCollection(); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error getting the current user resolved work items."); + } + } + + public async Task<WorkItem> CloseWorkItem(WorkItem workItem) + { + await SetWorkItemState(Project, workItem, State.Closed); + var updated = await AddWorkItemComment(Project, workItem, GetUserTeamMember(), "Bug has been verified and closed by " + GetUserTeamMember().DisplayName + " (via Tango Software)."); + ResolvedWorkItems.Remove(workItem); + return updated; + } + + public async Task<WorkItem> ReactivateWorkItem(WorkItem workItem) + { + await SetWorkItemState(Project, workItem, State.New); + var updated = await AddWorkItemComment(Project, workItem, GetUserTeamMember(), "Bug has been reactivated by " + GetUserTeamMember().DisplayName + " (via Tango Software)."); + updated = await SetWorkItemAssignment(Project, updated, workItem.ResolvedBy); + ResolvedWorkItems.Remove(workItem); + return updated; + } + public void Initialize() { Task.Factory.StartNew(() => { if (!IsInitialized) { - Project = GetProject("Tango").Result; - IsInitialized = true; + try + { + Project = GetProject("Tango").Result; + IsInitialized = true; + } + catch (Exception ex) + { + LogManager.Log(ex, "Error initializing the Team Foundation Service client."); + } } }); } @@ -60,7 +121,7 @@ namespace Tango.MachineStudio.UI.TFS item.Area = Project.Areas.FirstOrDefault(); item.Iteration = Project.Iterations.FirstOrDefault(); - TeamMember currentUser = Project.Members.SingleOrDefault(x => x.UniqueName.ToLower().Contains(auth.CurrentUser.Email.ToLower())); + TeamMember currentUser = GetUserTeamMember(); item.CreatedBy = currentUser; item.ChangedBy = currentUser; item.AuthorizedAs = currentUser; @@ -82,6 +143,14 @@ namespace Tango.MachineStudio.UI.TFS Name = "Screen Capture.jpg", }); + return item; + } + + public void FinalizeBug(WorkItem item) + { + IAuthenticationProvider auth = TangoIOC.Default.GetInstance<IAuthenticationProvider>(); + IStudioApplicationManager app = TangoIOC.Default.GetInstance<IStudioApplicationManager>(); + FileLogger appFileLogger = LogManager.Default.RegisteredLoggers.FirstOrDefault(x => x.GetType() == typeof(FileLogger)) as FileLogger; FileLogger embeddedFileLogger = MachineOperator.EmbeddedLogManager.RegisteredLoggers.FirstOrDefault(x => x.GetType() == typeof(FileLogger)) as FileLogger; @@ -113,7 +182,7 @@ namespace Tango.MachineStudio.UI.TFS SystemInformationModel sysModel = new SystemInformationModel(); sysModel.ApplicationVersion = app.Version; - sysModel.EmbeddedVersion = "Fake Version"; + sysModel.EmbeddedVersion = "N/A"; sysModel.HostName = Environment.MachineName; sysModel.UserName = auth.CurrentUser.Contact.FullName; @@ -122,17 +191,18 @@ namespace Tango.MachineStudio.UI.TFS Machine machine = app.ConnectedMachine.Machine; sysModel.Machine = machine; + sysModel.EmbeddedVersion = app.ConnectedMachine.DeviceInformation.Version; MachineDesigner.Views.MainView machineView = new MachineDesigner.Views.MainView(); machineView.Width = 1280; machineView.Height = 1100; - machineView.PanelColumnDefinition.Width = new System.Windows.GridLength(0); + machineView.PanelColumnDefinition.Width = new GridLength(0); machineView.stackHeader.Visibility = Visibility.Collapsed; machineView.Background = System.Windows.Media.Brushes.White; machineView.DataContext = new MachineDesigner.ViewModels.MainViewVM() { SelectedMachine = machine, Configuration = machine.Configuration }; String configImageFile = PathHelper.GetTempFilePath(); - machineView.RenderToFile(configImageFile, System.Drawing.Imaging.ImageFormat.Jpeg, new System.Windows.Size(machineView.Width, machineView.Height), 100); + machineView.RenderToFile(configImageFile, System.Drawing.Imaging.ImageFormat.Jpeg, new Size(machineView.Width, machineView.Height), 100); item.Attachments.Add(new Attachment() { @@ -141,7 +211,17 @@ namespace Tango.MachineStudio.UI.TFS Name = "Machine Configuration.jpg" }); - sysModel.ConfigurationString = machine.Configuration.CloneConfiguration().ToJsonString(); + sysModel.ConfigurationString = machine.Configuration.CloneConfiguration().ToJsonString(nameof(Configuration.MachinesConfigurations), nameof(Configuration.MachineVersions)); + + if (app.ConnectedMachine.CurrentProcessParameters != null) + { + sysModel.LoadedProcessParametersString = app.ConnectedMachine.CurrentProcessParameters.ToJsonString(nameof(ProcessParametersTable.ProcessParametersTablesGroup)); + } + + if (app.ConnectedMachine.CurrentHardwareConfiguration != null) + { + sysModel.LoadedHardwareConfigurationString = app.ConnectedMachine.CurrentHardwareConfiguration.ToJsonString(); + } } String html = String.Empty; @@ -154,7 +234,14 @@ namespace Tango.MachineStudio.UI.TFS item.SystemInformation = CodeGeneration.Helper.Parse(html, sysModel); - return item; + item.StepsToReproduce = String.Format("<div style=\"white-space:pre\">{0}</div>", item.StepsToReproduce); + } + + private TeamMember GetUserTeamMember() + { + IAuthenticationProvider auth = TangoIOC.Default.GetInstance<IAuthenticationProvider>(); + TeamMember currentUser = Project.Members.SingleOrDefault(x => x.UniqueName.ToLower().Contains(auth.CurrentUser.Email.ToLower())); + return currentUser; } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/WorkItemValidationAttribute.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/WorkItemValidationAttribute.cs index 1418d0576..3e85f91b4 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/WorkItemValidationAttribute.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/TFS/WorkItemValidationAttribute.cs @@ -16,13 +16,19 @@ namespace Tango.MachineStudio.UI.TFS if (String.IsNullOrWhiteSpace(item.Title)) { - ErrorMessage = "Title is empty"; + ErrorMessage = "Title is required."; return false; } if (item.AssignedTo == null) { - ErrorMessage = "Assigned To is empty"; + ErrorMessage = "Assigned To field is required."; + return false; + } + + if (String.IsNullOrWhiteSpace(item.StepsToReproduce)) + { + ErrorMessage = "Please enter steps to reproduce."; return false; } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index 8ab6bb188..5d685c112 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -131,6 +131,13 @@ <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </ApplicationDefinition> + <EmbeddedResource Include="Console\CodeTemplate.cs" /> + <Compile Include="Console\ConsoleManager.cs" /> + <Compile Include="Console\ConsoleOnExecuteParameters.cs" /> + <Compile Include="Console\ConsoleWindow.xaml.cs"> + <DependentUpon>ConsoleWindow.xaml</DependentUpon> + </Compile> + <Compile Include="Console\ConsoleWindowVM.cs" /> <Compile Include="Html\DefaultHtmlPresenter.cs" /> <Compile Include="Html\HtmlWindow.xaml.cs"> <DependentUpon>HtmlWindow.xaml</DependentUpon> @@ -161,6 +168,7 @@ <Compile Include="ViewModelLocator.cs" /> <Compile Include="ViewModels\ModuleWindowVM.cs" /> <Compile Include="ViewModels\ReportIssueViewVM.cs" /> + <Compile Include="ViewModels\ResolvedIssuesViewVM.cs" /> <Compile Include="ViewModels\ShutdownViewVM.cs" /> <Compile Include="ViewModels\UpdateViewVM.cs" /> <Compile Include="Views\ConnectedMachineView.xaml.cs"> @@ -190,6 +198,9 @@ <Compile Include="Views\ReportIssueView.xaml.cs"> <DependentUpon>ReportIssueView.xaml</DependentUpon> </Compile> + <Compile Include="Views\ResolvedIssuesView.xaml.cs"> + <DependentUpon>ResolvedIssuesView.xaml</DependentUpon> + </Compile> <Compile Include="Views\ShutdownView.xaml.cs"> <DependentUpon>ShutdownView.xaml</DependentUpon> </Compile> @@ -203,6 +214,10 @@ <Compile Include="Windows\ModuleWindow.xaml.cs"> <DependentUpon>ModuleWindow.xaml</DependentUpon> </Compile> + <Page Include="Console\ConsoleWindow.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Html\HtmlWindow.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> @@ -270,6 +285,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\ResolvedIssuesView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\ShutdownView.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -355,6 +374,10 @@ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project> <Name>Tango.PMR</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.Scripting\Tango.Scripting.csproj"> + <Project>{401989E7-AE1E-4002-B0EE-9A9F63740B97}</Project> + <Name>Tango.Scripting</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Settings\Tango.Settings.csproj"> <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project> <Name>Tango.Settings</Name> @@ -460,6 +483,7 @@ </ItemGroup> <ItemGroup> <Content Include="Html\HTML Templates\Thread Break.html" /> + <Resource Include="Images\bug-resolved.png" /> <EmbeddedResource Include="TFS\SystemInformationTemplate.cshtml" /> <Resource Include="Images\bug.png" /> </ItemGroup> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs index 8e6f11452..931130a05 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs @@ -13,6 +13,7 @@ using Tango.MachineStudio.Common.Speech; using Tango.MachineStudio.Common.StudioApplication; using Tango.MachineStudio.Common.Video; using Tango.MachineStudio.UI.Authentication; +using Tango.MachineStudio.UI.Console; using Tango.MachineStudio.UI.Html; using Tango.MachineStudio.UI.Modules; using Tango.MachineStudio.UI.Navigation; @@ -64,7 +65,6 @@ namespace Tango.MachineStudio.UI TangoIOC.Default.Unregister<IHtmlPresenter>(); TangoIOC.Default.Unregister<ITeamFoundationServiceClient>(); - TangoIOC.Default.Register<TeamFoundationServiceExtendedClient>(new TeamFoundationServiceExtendedClient("https://twinetfs.visualstudio.com/DefaultCollection", "Roy", "szzfokrceo4rhd4eqi5qpmxn3pa5iwl3q7tlqd36l2m7smz2ynoa")); TangoIOC.Default.Register<INotificationProvider, DefaultNotificationProvider>(); TangoIOC.Default.Register<IAuthenticationProvider, DefaultAuthenticationProvider>(); TangoIOC.Default.Register<INavigationManager, DefaultNavigationManager>(); @@ -76,6 +76,7 @@ namespace Tango.MachineStudio.UI TangoIOC.Default.Register<IEventLogger, DefaultEventLogger>(); TangoIOC.Default.Register<ISpeechProvider, DefaultSpeechProvider>(); TangoIOC.Default.Register<IHtmlPresenter, DefaultHtmlPresenter>(); + TangoIOC.Default.Register<TeamFoundationServiceExtendedClient>(new TeamFoundationServiceExtendedClient("https://twinetfs.visualstudio.com", String.Empty, "szzfokrceo4rhd4eqi5qpmxn3pa5iwl3q7tlqd36l2m7smz2ynoa")); TangoIOC.Default.Register<MainViewVM>(); TangoIOC.Default.Register<LoadingViewVM>(); @@ -85,6 +86,7 @@ namespace Tango.MachineStudio.UI TangoIOC.Default.Register<ConnectedMachineViewVM>(); TangoIOC.Default.Register<MachineLoginViewVM>(); TangoIOC.Default.Register<UpdateViewVM>(); + TangoIOC.Default.Register<ConsoleWindowVM>(); //Register View (Supervising Controller Pattern). //if (!ViewModelBase.IsInDesignModeStatic) @@ -157,5 +159,13 @@ namespace Tango.MachineStudio.UI return TangoIOC.Default.GetInstance<UpdateViewVM>(); } } + + public ConsoleWindowVM ConsoleWindowVM + { + get + { + return TangoIOC.Default.GetInstance<ConsoleWindowVM>(); + } + } } }
\ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs index 2b2b442f7..29f9102ac 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs @@ -16,6 +16,7 @@ using Tango.BL; using Tango.MachineStudio.Common.EventLogging; using Tango.BL.Enumerations; using Tango.MachineStudio.UI.TFS; +using Tango.MachineStudio.Common; namespace Tango.MachineStudio.UI.ViewModels { @@ -23,7 +24,7 @@ namespace Tango.MachineStudio.UI.ViewModels /// Represents the Machine Studio loading view, view model. /// </summary> /// <seealso cref="Tango.SharedUI.ViewModel" /> - public class LoadingViewVM : ViewModel + public class LoadingViewVM : StudioViewModelInternal { private INotificationProvider _notificationProvider; private TeamFoundationServiceExtendedClient _tfs; @@ -55,6 +56,11 @@ namespace Tango.MachineStudio.UI.ViewModels _navigationManager = navigationManager; _studioModuleLoader = studioModuleLoader; _notificationProvider = notificationProvider; + } + + public override void OnApplicationStarted() + { + base.OnApplicationStarted(); Load(); } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs index 0882267e8..04b973f23 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs @@ -148,6 +148,16 @@ namespace Tango.MachineStudio.UI.ViewModels /// </summary> public RelayCommand ReportIssueCommand { get; set; } + /// <summary> + /// Gets or sets the open resolved bugs. + /// </summary> + public RelayCommand OpenResolvedBugsCommand { get; set; } + + /// <summary> + /// Gets or sets the open developer console command. + /// </summary> + public RelayCommand OpenDeveloperConsoleCommand { get; set; } + private IAuthenticationProvider _authenticationProvider; /// <summary> /// Gets or sets the authentication provider. @@ -302,6 +312,8 @@ namespace Tango.MachineStudio.UI.ViewModels ResolveMachineEventCommand = new RelayCommand<MachinesEvent>(ResolveMachineEvent); ReportIssueCommand = new RelayCommand(ReportIssue); + OpenResolvedBugsCommand = new RelayCommand(OpenResolvedBugs); + OpenDeveloperConsoleCommand = new RelayCommand(OpenDeveloperConsole); } private void MachineEventsStateProvider_EventsResolved(object sender, IEnumerable<MachinesEvent> e) @@ -321,7 +333,7 @@ namespace Tango.MachineStudio.UI.ViewModels { while (!DisableCheckForUpdates) { - Thread.Sleep(TimeSpan.FromMinutes(1)); + Thread.Sleep(TimeSpan.FromMinutes(0.2)); try { @@ -649,10 +661,78 @@ namespace Tango.MachineStudio.UI.ViewModels { using (_notificationProvider.PushTaskItem("Uploading bug report...")) { - await TFSClient.UploadWorkItem(vm.WorkItem); + try + { + TFSClient.FinalizeBug(vm.WorkItem); + await TFSClient.UploadWorkItem(vm.WorkItem); + } + catch (Exception ex) + { + _notificationProvider.ShowError("An error occurred while trying to create the issue." + Environment.NewLine + ex.Message); + } } }, null); } + + private void OpenResolvedBugs() + { + ResolvedIssuesViewVM vm = null; + + vm = new ResolvedIssuesViewVM(TFSClient, async (item) => + { + //Approve + using (_notificationProvider.PushTaskItem("Approving issue...")) + { + vm.IsAvailable = false; + try + { + await TFSClient.CloseWorkItem(item); + } + catch (Exception ex) + { + _notificationProvider.ShowError("An error occurred while trying to update the issue." + Environment.NewLine + ex.Message); + } + vm.IsAvailable = true; + + if (TFSClient.ResolvedWorkItems.Count == 0) + { + vm.Close(); + } + } + }, async (item) => + { + //Decline + using (_notificationProvider.PushTaskItem("Reactivating issue...")) + { + vm.IsAvailable = false; + try + { + await TFSClient.ReactivateWorkItem(item); + } + catch (Exception ex) + { + _notificationProvider.ShowError("An error occurred while trying to update the issue." + Environment.NewLine + ex.Message); + } + + vm.IsAvailable = true; + + if (TFSClient.ResolvedWorkItems.Count == 0) + { + vm.Close(); + } + } + }); + + _notificationProvider.ShowModalDialog<ResolvedIssuesViewVM, ResolvedIssuesView>(vm, (_) => { }, null); + } + + private void OpenDeveloperConsole() + { + Console.ConsoleWindow console = new Console.ConsoleWindow(); + ApplicationManager.RegisterOpenedWindow(console); + console.Owner = MainWindow.Instance; + console.Show(); + } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ResolvedIssuesViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ResolvedIssuesViewVM.cs new file mode 100644 index 000000000..552880792 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ResolvedIssuesViewVM.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.Commands; +using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.UI.TFS; +using Tango.TFS; + +namespace Tango.MachineStudio.UI.ViewModels +{ + public class ResolvedIssuesViewVM : DialogViewVM + { + private Action<WorkItem> _onApprove; + private Action<WorkItem> _onDecline; + + public TeamFoundationServiceExtendedClient TFSClient { get; set; } + + public RelayCommand<WorkItem> ApproveCommand { get; set; } + + public RelayCommand<WorkItem> DeclineCommand { get; set; } + + private bool _isAvailable; + + public bool IsAvailable + { + get { return _isAvailable; } + set { _isAvailable = value; RaisePropertyChangedAuto(); } + } + + public ResolvedIssuesViewVM() : base() + { + IsAvailable = true; + ApproveCommand = new RelayCommand<WorkItem>(ApproveIssue); + DeclineCommand = new RelayCommand<WorkItem>(DeclineIssue); + } + + public ResolvedIssuesViewVM(TeamFoundationServiceExtendedClient tfsClient, Action<WorkItem> onApprove, Action<WorkItem> onDecline) : this() + { + TFSClient = tfsClient; + _onApprove = onApprove; + _onDecline = onDecline; + } + + private void DeclineIssue(WorkItem workItem) + { + _onDecline(workItem); + } + + private void ApproveIssue(WorkItem workItem) + { + _onApprove(workItem); + } + + public void Close() + { + Accept(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 86723479b..8417c70c8 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -10,9 +10,11 @@ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:entities="clr-namespace:Tango.BL.Entities;assembly=Tango.BL" + xmlns:enumerations="clr-namespace:Tango.BL.Enumerations;assembly=Tango.BL" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:db="clr-namespace:Tango.MachineStudio.DB.Views;assembly=Tango.MachineStudio.DB" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" + xmlns:commonConverters="clr-namespace:Tango.MachineStudio.Common.Converters;assembly=Tango.MachineStudio.Common" mc:Ignorable="d" d:DesignHeight="720" d:DesignWidth="1270" Background="Transparent" DataContext="{Binding MainViewVM, Source={StaticResource Locator}}"> @@ -22,6 +24,7 @@ <converters:NullObjectToBooleanConverter x:Key="NullObjectToBooleanConverter" /> <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> <converters:StringToWordsConverter x:Key="StringToWordsConverter" /> + <commonConverters:PermissionToVisibilityConverter x:Key="PermissionToVisibilityConverter" /> </UserControl.Resources> <Grid> @@ -189,7 +192,16 @@ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center">Speech</TextBlock> </StackPanel> </Button> - <Separator/> + <StackPanel Visibility="{Binding AuthenticationProvider.CurrentUser,Converter={StaticResource PermissionToVisibilityConverter},ConverterParameter={x:Static enumerations:Permissions.RunDeveloperConsole}}"> + <Separator/> + <Button Command="{Binding OpenDeveloperConsoleCommand}"> + <StackPanel Orientation="Horizontal"> + <materialDesign:PackIcon Kind="Console" Width="24" Height="24" /> + <TextBlock Margin="5 0 0 0" VerticalAlignment="Center">Developer Console</TextBlock> + </StackPanel> + </Button> + <Separator/> + </StackPanel> <Button Command="{Binding ExitCommand}"> <StackPanel Orientation="Horizontal"> <materialDesign:PackIcon Kind="CloseCircleOutline" Width="24" Height="24" /> @@ -320,7 +332,7 @@ <Button Cursor="Hand" Command="{Binding ReportIssueCommand}" IsEnabled="{Binding TFSClient.IsInitialized}"> <Button.Style> <Style TargetType="Button" BasedOn="{StaticResource emptyButton}"> - <Setter Property="ToolTip" Value="Report and issue"></Setter> + <Setter Property="ToolTip" Value="Report issue"></Setter> <Setter Property="Opacity" Value="1"></Setter> <Style.Triggers> <Trigger Property="IsEnabled" Value="False"> @@ -332,6 +344,38 @@ </Button.Style> <Image Margin="10 0 0 0" Source="/Images/bug.png" Width="24" RenderOptions.BitmapScalingMode="Fant" /> </Button> + <Button Cursor="Hand" Command="{Binding OpenResolvedBugsCommand}"> + <Button.Style> + <Style TargetType="Button" BasedOn="{StaticResource emptyButton}"> + <Setter Property="Visibility" Value="Visible"></Setter> + <Style.Triggers> + <EventTrigger RoutedEvent="Loaded"> + <EventTrigger.Actions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="00:00:01" RepeatBehavior="Forever"> + <DiscreteDoubleKeyFrame KeyTime="00:00:00" Value="1" /> + <DiscreteDoubleKeyFrame KeyTime="00:00:0.5" Value="0" /> + </DoubleAnimationUsingKeyFrames> + </Storyboard> + </BeginStoryboard> + </EventTrigger.Actions> + </EventTrigger> + <DataTrigger Binding="{Binding TFSClient.ResolvedWorkItems.Count}" Value="0"> + <Setter Property="Visibility" Value="Collapsed"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + <Button.ToolTip> + <TextBlock> + <Run>There are</Run> + <Run Text="{Binding TFSClient.ResolvedWorkItems.Count,Mode=OneWay}"></Run> + <Run>issues waiting for your approval</Run> + </TextBlock> + </Button.ToolTip> + <Image Margin="10 0 0 0" Source="/Images/bug-resolved.png" Width="24" RenderOptions.BitmapScalingMode="Fant" /> + </Button> </StackPanel> </Grid> </Grid> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ReportIssueView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ReportIssueView.xaml index f2e3038b9..37cd0b793 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ReportIssueView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ReportIssueView.xaml @@ -12,7 +12,7 @@ xmlns:tfs="clr-namespace:Tango.TFS;assembly=Tango.TFS" xmlns:tfss="clr-namespace:Tango.MachineStudio.UI.TFS" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" - mc:Ignorable="d" Width="530" Height="650" Background="White" d:DataContext="{d:DesignInstance Type=vm:ReportIssueViewVM, IsDesignTimeCreatable=False}"> + mc:Ignorable="d" Width="530" Height="680" Background="White" d:DataContext="{d:DesignInstance Type=vm:ReportIssueViewVM, IsDesignTimeCreatable=False}"> <UserControl.Resources> <converters:EnumToItemsSourceConverter x:Key="EnumToItemsSourceConverter" /> @@ -36,53 +36,85 @@ </Grid> <Grid Grid.Row="1"> - <StackPanel> - <TextBox materialDesign:HintAssist.Hint="Title" materialDesign:HintAssist.IsFloating="True" FontSize="16" Text="{Binding WorkItem.Title}"></TextBox> + <DockPanel> + <StackPanel DockPanel.Dock="Top"> + <DockPanel> + <materialDesign:PackIcon Kind="Pencil" Width="24" Height="24" VerticalAlignment="Center" Margin="0 0 10 0" /> + <TextBox materialDesign:HintAssist.Hint="Title" materialDesign:HintAssist.IsFloating="True" FontSize="16" Text="{Binding WorkItem.Title}"></TextBox> + </DockPanel> - <autoComplete:AutoCompleteTextBox Provider="{StaticResource TeamMembersProvider}" SelectedItem="{Binding WorkItem.AssignedTo,Mode=TwoWay}" DisplayMember="DisplayName" Margin="0 10 0 0" materialDesign:HintAssist.Hint="Assigned To" materialDesign:HintAssist.IsFloating="True"></autoComplete:AutoCompleteTextBox> - <ComboBox Margin="0 10 0 0" materialDesign:HintAssist.Hint="Area" materialDesign:HintAssist.IsFloating="True" ItemsSource="{Binding Project.Areas}" SelectedItem="{Binding WorkItem.Area}" DisplayMemberPath="Name"></ComboBox> - <ComboBox Margin="0 10 0 0" materialDesign:HintAssist.Hint="Severity" materialDesign:HintAssist.IsFloating="True" ItemsSource="{Binding Source={x:Type tfs:Severity},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValue="{Binding WorkItem.Severity}" SelectedValuePath="Value" DisplayMemberPath="DisplayName"></ComboBox> + <DockPanel Margin="0 10 0 0"> + <materialDesign:PackIcon Kind="Account" Width="24" Height="24" VerticalAlignment="Center" Margin="0 0 10 0" /> + <autoComplete:AutoCompleteTextBox Provider="{StaticResource TeamMembersProvider}" SelectedItem="{Binding WorkItem.AssignedTo,Mode=TwoWay}" DisplayMember="DisplayName" materialDesign:HintAssist.Hint="Assigned To" materialDesign:HintAssist.IsFloating="True"></autoComplete:AutoCompleteTextBox> + </DockPanel> - <TextBlock Margin="0 10 0 0">Tags</TextBlock> - <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Height="120"> - <ItemsControl ItemsSource="{Binding SelectedTags}"> - <ItemsControl.ItemsPanel> - <ItemsPanelTemplate> - <WrapPanel IsItemsHost="True" Orientation="Horizontal" /> - </ItemsPanelTemplate> - </ItemsControl.ItemsPanel> - <ItemsControl.ItemTemplate> - <DataTemplate> - <ToggleButton Style="{StaticResource emptyToggleButton}" IsChecked="{Binding IsSelected}" Cursor="Hand"> - <Border CornerRadius="5" Margin="0 5 5 5" Padding="5" BorderThickness="1" BorderBrush="DimGray"> - <Border.Style> - <Style TargetType="Border"> - <Setter Property="Background" Value="Silver"></Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding IsSelected}" Value="True"> - <Setter Property="Background" Value="{StaticResource AccentColorBrush}"></Setter> - <Setter Property="TextElement.Foreground" Value="White"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </Border.Style> - <TextBlock Text="{Binding Data.Name}" FontSize="11"></TextBlock> - </Border> - </ToggleButton> - </DataTemplate> - </ItemsControl.ItemTemplate> - </ItemsControl> - </ScrollViewer> - </StackPanel> + <DockPanel Margin="0 10 0 0"> + <materialDesign:PackIcon Kind="Star" Width="24" Height="24" VerticalAlignment="Center" Margin="0 0 10 0" /> + <ComboBox materialDesign:HintAssist.Hint="Area" materialDesign:HintAssist.IsFloating="True" ItemsSource="{Binding Project.Areas}" SelectedItem="{Binding WorkItem.Area}" DisplayMemberPath="Name"></ComboBox> + </DockPanel> + + <DockPanel Margin="0 10 0 0"> + <materialDesign:PackIcon Kind="CommentAlertOutline" Width="24" Height="24" VerticalAlignment="Center" Margin="0 0 10 0" /> + <ComboBox materialDesign:HintAssist.Hint="Severity" materialDesign:HintAssist.IsFloating="True" ItemsSource="{Binding Source={x:Type tfs:Severity},Converter={StaticResource EnumToItemsSourceConverter}}" SelectedValue="{Binding WorkItem.Severity}" SelectedValuePath="Value" DisplayMemberPath="DisplayName"></ComboBox> + </DockPanel> + + <DockPanel Margin="0 20 0 0"> + <materialDesign:PackIcon Kind="Tag" Width="24" Height="24" VerticalAlignment="Center" Margin="0 0 10 0" /> + <TextBlock VerticalAlignment="Center"><Run>Tags</Run> <Run FontSize="10" Foreground="Gray">(highlight selected tags)</Run></TextBlock> + </DockPanel> + <ScrollViewer Margin="30 0 0 0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Height="120"> + <ItemsControl ItemsSource="{Binding SelectedTags}"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel IsItemsHost="True" Orientation="Horizontal" /> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate> + <ToggleButton Style="{StaticResource emptyToggleButton}" IsChecked="{Binding IsSelected}" Cursor="Hand"> + <Border CornerRadius="5" Margin="0 5 5 5" Padding="5" BorderThickness="1" BorderBrush="DimGray"> + <Border.Style> + <Style TargetType="Border"> + <Setter Property="Background" Value="Silver"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding IsSelected}" Value="True"> + <Setter Property="Background" Value="{StaticResource AccentColorBrush}"></Setter> + <Setter Property="TextElement.Foreground" Value="White"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Border.Style> + <TextBlock Text="{Binding Data.Name}" FontSize="11"></TextBlock> + </Border> + </ToggleButton> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </ScrollViewer> + </StackPanel> + + <Grid> + <DockPanel> + <DockPanel Margin="0 10 0 0" DockPanel.Dock="Top"> + <materialDesign:PackIcon Kind="ChartTimeline" Width="24" Height="24" VerticalAlignment="Center" Margin="0 0 10 0" /> + <TextBlock VerticalAlignment="Center">Steps To Reproduce</TextBlock> + </DockPanel> + + <Grid Margin="30 0 0 0"> + <TextBox Margin="0 5 0 0" Style="{x:Null}" BorderBrush="Silver" AcceptsReturn="True" TextWrapping="Wrap" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Text="{Binding WorkItem.StepsToReproduce}"></TextBox> + </Grid> + </DockPanel> + </Grid> + </DockPanel> </Grid> <Grid Grid.Row="2"> - <Button HorizontalAlignment="Right" Width="140" Command="{Binding OKCommand}">SUBMIT</Button> + <Button HorizontalAlignment="Right" Height="40" Width="140" Command="{Binding OKCommand}" Background="#FF6262" BorderBrush="#FF6262" IsDefault="True">SUBMIT</Button> <ItemsControl ItemsSource="{Binding ValidationErrors}" HorizontalAlignment="Left" Margin="5" VerticalAlignment="Center" Visibility="Visible"> <ItemsControl.ItemTemplate> <DataTemplate> - <TextBlock Foreground="#FF4C4C" Margin="0 2 0 0"><Run>*</Run> <Run Text="{Binding}"></Run></TextBlock> + <TextBlock Foreground="#FF4C4C" Margin="0 2 0 0"><Run>*</Run> <Run Text="{Binding Path=*,Mode=OneWay}"></Run></TextBlock> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ResolvedIssuesView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ResolvedIssuesView.xaml new file mode 100644 index 000000000..4fb457f87 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ResolvedIssuesView.xaml @@ -0,0 +1,89 @@ +<UserControl x:Class="Tango.MachineStudio.UI.Views.ResolvedIssuesView" + 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:mahapps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:autoComplete="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete" + xmlns:integration="clr-namespace:Tango.Integration.Services;assembly=Tango.Integration" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:vm="clr-namespace:Tango.MachineStudio.UI.ViewModels" + xmlns:tfs="clr-namespace:Tango.TFS;assembly=Tango.TFS" + xmlns:tfss="clr-namespace:Tango.MachineStudio.UI.TFS" + xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" + mc:Ignorable="d" Width="530" Height="580" Background="White" d:DataContext="{d:DesignInstance Type=vm:ResolvedIssuesViewVM, IsDesignTimeCreatable=False}"> + <Grid> + <Grid IsEnabled="{Binding IsAvailable}"> + <Grid.RowDefinitions> + <RowDefinition Height="130"/> + <RowDefinition Height="1*"/> + <RowDefinition Height="200"/> + </Grid.RowDefinitions> + + <Grid> + <StackPanel Margin="10"> + <StackPanel Orientation="Horizontal"> + <Image Source="/Images/bug-resolved.png" Width="48" RenderOptions.BitmapScalingMode="Fant"></Image> + <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" FontSize="20">Resolved Issues</TextBlock> + </StackPanel> + + <TextBlock HorizontalAlignment="Left" Margin="10" TextWrapping="Wrap"> + Below you can find issues reported by you that have been flagged as resolved by the development team. + Please verify each one and report back by pressing 'FIXED' or 'NOT FIXED'. + </TextBlock> + </StackPanel> + </Grid> + + <Grid Grid.Row="1"> + <ListBox x:Name="list" ItemsSource="{Binding TFSClient.ResolvedWorkItems}" HorizontalContentAlignment="Stretch"> + <ListBox.ItemTemplate> + <DataTemplate> + <Border BorderBrush="#E6E6E6" BorderThickness="0 0 0 1" Padding="5"> + <DockPanel> + <StackPanel Orientation="Horizontal"> + <Image Source="/Images/bug.png" Width="24" RenderOptions.BitmapScalingMode="Fant"></Image> + <StackPanel Margin="5 0 0 0"> + <TextBlock Text="{Binding Title}" FontWeight="SemiBold" TextTrimming="CharacterEllipsis"></TextBlock> + <TextBlock Text="{Binding Comment,TargetNullValue='Comment',FallbackValue='Comment'}" Foreground="Gray" FontSize="10"></TextBlock> + </StackPanel> + </StackPanel> + + <StackPanel HorizontalAlignment="Right" Orientation="Horizontal"> + <Button Background="#FF8282" BorderBrush="#FF8282" Padding="0" Width="90" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.DeclineCommand}" CommandParameter="{Binding}"> + <StackPanel Orientation="Horizontal"> + <materialDesign:PackIcon VerticalAlignment="Center" Kind="Close" /> + <TextBlock Margin="10 0 0 0" FontSize="11" VerticalAlignment="Center">NOT FIXED</TextBlock> + </StackPanel> + </Button> + <Button Background="#91D66D" BorderBrush="#91D66D" Padding="0" Width="90" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.ApproveCommand}" CommandParameter="{Binding}"> + <StackPanel Orientation="Horizontal"> + <materialDesign:PackIcon VerticalAlignment="Center" Kind="Check" /> + <TextBlock Margin="10 0 0 0" FontSize="11" VerticalAlignment="Center">FIXED</TextBlock> + </StackPanel> + </Button> + </StackPanel> + </DockPanel> + </Border> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + </Grid> + + <Grid Grid.Row="2"> + <Border BorderBrush="#FFA5A5" BorderThickness="0 1 0 0" Margin="5"> + <DockPanel> + <DockPanel Margin="0 10 0 0" DockPanel.Dock="Top"> + <materialDesign:PackIcon Kind="ChartTimeline" Width="24" Height="24" VerticalAlignment="Center" Margin="0 0 10 0" /> + <TextBlock VerticalAlignment="Center" FontSize="16">Steps To Reproduce</TextBlock> + </DockPanel> + + <Grid> + <TextBox Margin="5 10 10 10" Style="{x:Null}" BorderThickness="0" AcceptsReturn="True" TextWrapping="Wrap" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Text="{Binding ElementName=list,Path=SelectedItem.StepsToReproduce}" IsReadOnly="True"></TextBox> + </Grid> + </DockPanel> + </Border> + </Grid> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ResolvedIssuesView.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ResolvedIssuesView.xaml.cs new file mode 100644 index 000000000..7825bf587 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ResolvedIssuesView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.UI.Views +{ + /// <summary> + /// Interaction logic for ResolvedBugsView.xaml + /// </summary> + public partial class ResolvedIssuesView : UserControl + { + public ResolvedIssuesView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionResolutions.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionResolutions.cs index 2e7327559..e27a84c3b 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionResolutions.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionResolutions.cs @@ -10,6 +10,7 @@ namespace Tango.MachineStudio.UI.Windows { Shutdown, Restart, - Ignore + Ignore, + Report } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml index 892e4944f..147b40892 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Windows" mc:Ignorable="d" - WindowStyle="None" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStartupLocation="CenterScreen" d:DesignHeight="300" d:DesignWidth="300" Width="610" Height="410" Background="Transparent" d:DataContext="{d:DesignInstance Type=local:ExceptionWindow, IsDesignTimeCreatable=False}"> + WindowStyle="None" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Width="800" Height="600" Background="Transparent" d:DataContext="{d:DesignInstance Type=local:ExceptionWindow, IsDesignTimeCreatable=False}"> <Grid> <Border BorderThickness="1" BorderBrush="DodgerBlue" Background="White" Margin="10" CornerRadius="10"> <Border.Effect> @@ -48,8 +48,16 @@ </Grid> <Grid Grid.Row="1"> - <Button HorizontalAlignment="Left" Width="140" Command="{Binding ResolveCommand}" CommandParameter="{x:Static local:ExceptionResolutions.Ignore}">Ignore</Button> + <StackPanel HorizontalAlignment="Left" Orientation="Horizontal"> + <Button Width="140" Command="{Binding ResolveCommand}" CommandParameter="{x:Static local:ExceptionResolutions.Ignore}">Ignore</Button> + </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> + <Button x:Name="btnReport" Style="{StaticResource MaterialDesignFlatButton}" Width="150" Command="{Binding ResolveCommand}" CommandParameter="{x:Static local:ExceptionResolutions.Report}"> + <StackPanel Orientation="Horizontal"> + <Image Source="/Images/bug.png" RenderOptions.BitmapScalingMode="Fant"></Image> + <TextBlock Foreground="#FF5C5C" Margin="10 0 0 0" VerticalAlignment="Center">Report Issue</TextBlock> + </StackPanel> + </Button> <Button Margin="5 0 0 0" Width="140" Command="{Binding ResolveCommand}" CommandParameter="{x:Static local:ExceptionResolutions.Shutdown}">Shutdown</Button> <Button Margin="5 0 0 0" Width="140" Command="{Binding ResolveCommand}" CommandParameter="{x:Static local:ExceptionResolutions.Restart}">Restart</Button> </StackPanel> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml.cs index 0f74fee17..0a6f2de39 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml.cs @@ -33,10 +33,15 @@ namespace Tango.MachineStudio.UI.Windows DataContext = this; } - public ExceptionWindow(Exception ex) : this() + public ExceptionWindow(Exception ex, bool canReport) : this() { Exception = ex.FlattenException(); ResolveCommand = new RelayCommand<ExceptionResolutions>(Resolve); + + if (!canReport) + { + btnReport.Visibility = Visibility.Collapsed; + } } private void Resolve(ExceptionResolutions resolution) |
