aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/FSE/Modules
diff options
context:
space:
mode:
authorAvi Levkovich <avi@twine-s.com>2020-05-13 13:27:01 +0300
committerAvi Levkovich <avi@twine-s.com>2020-05-13 13:27:01 +0300
commit15dfc2cdcbc2e518c09c1ee75f32ff149d4a337d (patch)
tree4c0b49773706b85282e6f6b1ec3d2e949d3ca22e /Software/Visual_Studio/FSE/Modules
parent6a49e917c587dcbbfe8175b8dde73840b7d105fc (diff)
parentcd750d626d3780990797faf09446033bbaa4311c (diff)
downloadTango-15dfc2cdcbc2e518c09c1ee75f32ff149d4a337d.tar.gz
Tango-15dfc2cdcbc2e518c09c1ee75f32ff149d4a337d.zip
commit merge
Diffstat (limited to 'Software/Visual_Studio/FSE/Modules')
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/App.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DecimalPlacesToStringFormatConverter.cs (renamed from Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Converters/DoubleToChartValuesConverter.cs)11
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DiagnosticsWidgetToSettingsViewConverter.cs36
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/PercentageToWidthConverter.cs40
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsConfigurableWidget.cs49
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs11
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidgetSettings.cs15
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/Images/tft_screen.pngbin0 -> 43439 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidget.cs68
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettings.cs38
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettingsView.xaml28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettingsView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetView.xaml32
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidget.cs22
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetBase.cs (renamed from Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidget.cs)53
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettings.cs71
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettingsView.xaml66
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettingsView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetView.xaml (renamed from Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml)6
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetView.xaml.cs (renamed from Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml.cs)2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidget.cs (renamed from Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidget.cs)5
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettings.cs20
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettingsView.xaml100
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettingsView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetView.xaml13
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetView.xaml.cs (renamed from Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidgetView.xaml.cs)2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidgetView.xaml53
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj63
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Themes/Generic.xaml60
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs30
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs78
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml90
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml52
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.json22
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/FileSystemViewVM.cs3
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj1
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml3
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml4
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs3
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectView.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectViewVM.cs26
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridView.xaml31
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridView.xaml.cs130
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridViewVM.cs31
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Result.cs2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Tango.FSE.Stubs.csproj8
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/MainViewVM.cs24
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs24
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestRunnerViewVM.cs26
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml20
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs15
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerCatalogView.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerExecutionView.xaml18
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Images/machine-update_gray.pngbin0 -> 113791 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj3
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs10
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/MainViewVM.cs1
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml8
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeView.xaml6
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml6
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml6
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/MainView.xaml4
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/WelcomeView.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/App.xaml16
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Images/users_and_roles.pngbin0 -> 1777 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Images/users_roles_back.pngbin0 -> 147207 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Models/RoleModel.cs49
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Models/RolesCollection.cs60
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Navigation/UsersAndRolesNavigationManager.cs19
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Navigation/UsersAndRolesView.cs15
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/AssemblyInfo.cs55
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Resources.Designer.cs71
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Resources.resx117
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Settings.Designer.cs30
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Settings.settings7
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Tango.FSE.UsersAndRoles.csproj212
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/UsersAndRolesModule.cs26
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/UsersAndRolesViewModel.cs15
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModelLocator.cs56
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/MainViewVM.cs64
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationSelectionViewVM.cs92
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationUsersViewVM.cs230
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/UserDetailsViewVM.cs387
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/MainView.xaml21
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/MainView.xaml.cs31
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationSelectionView.xaml57
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationSelectionView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationUsersView.xaml140
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationUsersView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml166
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/app.config85
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/packages.config10
95 files changed, 3615 insertions, 171 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/App.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/App.xaml
index 9efba692b..da0a65fc1 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/App.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/App.xaml
@@ -10,6 +10,8 @@
<ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Images.xaml" />
<ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Styles.xaml" />
<ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Controls.xaml" />
+
+ <ResourceDictionary Source="Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Converters/DoubleToChartValuesConverter.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DecimalPlacesToStringFormatConverter.cs
index 1ac86b849..032d0bb1e 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Converters/DoubleToChartValuesConverter.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DecimalPlacesToStringFormatConverter.cs
@@ -6,13 +6,18 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
-namespace Tango.FSE.PPCConsole.Converters
+namespace Tango.FSE.Diagnostics.Converters
{
- public class DoubleToChartValuesConverter : IValueConverter
+ public class DecimalPlacesToStringFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- return new LiveCharts.ChartValues<double>() { (double)value };
+ if (value != null)
+ {
+ return $"F{int.Parse(value.ToString())}";
+ }
+
+ return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DiagnosticsWidgetToSettingsViewConverter.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DiagnosticsWidgetToSettingsViewConverter.cs
new file mode 100644
index 000000000..3ba8f2e4b
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/DiagnosticsWidgetToSettingsViewConverter.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using Tango.FSE.Diagnostics.Project;
+
+namespace Tango.FSE.Diagnostics.Converters
+{
+ public class DiagnosticsWidgetToSettingsViewConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ DiagnosticsConfigurableWidget widget = value as DiagnosticsConfigurableWidget;
+
+ if (widget != null)
+ {
+ if (widget.Settings != null)
+ {
+ var view = widget.Settings.GetView();
+ view.DataContext = widget;
+ return view;
+ }
+ }
+
+ return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/PercentageToWidthConverter.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/PercentageToWidthConverter.cs
new file mode 100644
index 000000000..2ea6710c7
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Converters/PercentageToWidthConverter.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.FSE.Diagnostics.Converters
+{
+ public class PercentageToWidthConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ try
+ {
+ double parentWidth = (double)values[0];
+ double percentage = (double)values[1];
+
+ return percentage / 100d * parentWidth;
+ }
+ catch
+ {
+ if (values.Length > 0)
+ {
+ return values[0];
+ }
+ else
+ {
+ return 0d;
+ }
+ }
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsConfigurableWidget.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsConfigurableWidget.cs
new file mode 100644
index 000000000..ac1d29847
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsConfigurableWidget.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Diagnostics.Project
+{
+ public abstract class DiagnosticsConfigurableWidget : DiagnosticsWidget
+ {
+ public DiagnosticsWidgetSettings Settings { get; set; }
+ }
+
+ public abstract class DiagnosticsConfigurableWidget<T> : DiagnosticsConfigurableWidget where T : DiagnosticsWidgetSettings, new()
+ {
+ private T _settings;
+ public new T Settings
+ {
+ get { return _settings; }
+ set
+ {
+ _settings = value;
+ RaisePropertyChangedAuto();
+
+ if (_settings != null)
+ {
+ base.Settings = value;
+ OnSettingsChanged();
+ _settings.PropertyChanged += _settings_PropertyChanged;
+ }
+ }
+ }
+
+ public DiagnosticsConfigurableWidget() : base()
+ {
+ Settings = new T();
+ }
+
+ private void _settings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ OnSettingsChanged();
+ }
+
+ protected virtual void OnSettingsChanged()
+ {
+
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs
index b91da83c2..c7880909b 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidget.cs
@@ -42,8 +42,11 @@ namespace Tango.FSE.Diagnostics.Project
public int Row { get; set; }
public int ColumnSpan { get; set; }
public int RowSpan { get; set; }
+ public double Width { get; set; }
+ public double Height { get; set; }
private bool _isVisible;
+ [JsonIgnore]
public bool IsVisible
{
get { return _isVisible; }
@@ -58,8 +61,16 @@ namespace Tango.FSE.Diagnostics.Project
}
}
+ [JsonIgnore]
+ public abstract String DisplayName
+ {
+ get;
+ }
+
public DiagnosticsWidget()
{
+ Width = 100;
+ Height = 100;
TangoIOC.Default.Inject(this);
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidgetSettings.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidgetSettings.cs
new file mode 100644
index 000000000..2fb38ad93
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/DiagnosticsWidgetSettings.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.Core;
+
+namespace Tango.FSE.Diagnostics.Project
+{
+ public abstract class DiagnosticsWidgetSettings : ExtendedObject
+ {
+ public abstract FrameworkElement GetView();
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/Images/tft_screen.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/Images/tft_screen.png
new file mode 100644
index 000000000..268453279
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/Images/tft_screen.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidget.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidget.cs
new file mode 100644
index 000000000..3a2590ca2
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidget.cs
@@ -0,0 +1,68 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+
+namespace Tango.FSE.Diagnostics.Project.Widgets.Monitor
+{
+ public class MonitorWidget : DiagnosticsConfigurableWidget<MonitorWidgetSettings>
+ {
+ public TechMonitors Monitor { get; set; }
+
+ [JsonIgnore]
+ public TechMonitor TechMonitor { get; private set; }
+
+ [JsonIgnore]
+ public override string DisplayName
+ {
+ get
+ {
+ return this.TechMonitor != null ? this.TechMonitor.Description : String.Empty;
+ }
+ }
+
+ private String _value;
+ [JsonIgnore]
+ public String Value
+ {
+ get { return _value; }
+ set { _value = value; RaisePropertyChangedAuto(); }
+ }
+
+ public override async Task Init()
+ {
+ int monitor = (int)Monitor;
+ TechMonitor = await Services.TechComponentsService.Monitors.FindOne(x => x.Code == monitor);
+ }
+
+ public override void OnDiagnosticsData(DiagnosticsPackage package)
+ {
+ if (IsVisible)
+ {
+ var value = package.GetMonitorLastValue(Monitor);
+ string format = "0";
+
+ if (Settings.DecimalPlaces > 0)
+ {
+ format = "0." + String.Join("", Enumerable.Range(0, Settings.DecimalPlaces).Select(x => "#"));
+ }
+ else
+ {
+ format = "0";
+ }
+
+ Value = value.ToString(format);
+ }
+ }
+
+ public override FrameworkElement GetView()
+ {
+ return new MonitorWidgetView() { DataContext = this };
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettings.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettings.cs
new file mode 100644
index 000000000..3949f1029
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettings.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+
+namespace Tango.FSE.Diagnostics.Project.Widgets.Monitor
+{
+ public class MonitorWidgetSettings : DiagnosticsWidgetSettings
+ {
+ private int _decimalPlaces;
+ public int DecimalPlaces
+ {
+ get { return _decimalPlaces; }
+ set { _decimalPlaces = value; RaisePropertyChangedAuto(); }
+ }
+
+ private Color _color;
+ public Color Color
+ {
+ get { return _color; }
+ set { _color = value; RaisePropertyChangedAuto(); }
+ }
+
+ public MonitorWidgetSettings()
+ {
+ DecimalPlaces = 0;
+ Color = Colors.Gainsboro;
+ }
+
+ public override FrameworkElement GetView()
+ {
+ return new MonitorWidgetSettingsView() { DataContext = this };
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettingsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettingsView.xaml
new file mode 100644
index 000000000..9ddaea737
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettingsView.xaml
@@ -0,0 +1,28 @@
+<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.Monitor.MonitorWidgetSettingsView"
+ 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:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
+ xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets.Monitor"
+ xmlns:colorPicker="clr-namespace:Tango;assembly=Tango.ColorPicker"
+ mc:Ignorable="d"
+ d:DesignHeight="700" d:DesignWidth="300">
+ <Grid>
+ <StackPanel>
+ <controls:FSEGroupBox Header="FORMAT" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <StackPanel>
+ <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}" >Decimal Places</TextBlock>
+ <mahapps:NumericUpDown Background="Transparent" BorderThickness="0 0 0 1" HorizontalContentAlignment="Left" Minimum="0" Maximum="3" Focusable="False" Value="{Binding Settings.DecimalPlaces,UpdateSourceTrigger=PropertyChanged}" />
+ </StackPanel>
+ </controls:FSEGroupBox>
+
+ <controls:FSEGroupBox Header="COLOR" Margin="0 10 0 0" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <Viewbox>
+ <colorPicker:ColorCanvas Background="Transparent" BorderThickness="0" FontSize="{StaticResource FSE_SmallerFontSize}" SelectedColor="{Binding Settings.Color,Mode=TwoWay}" />
+ </Viewbox>
+ </controls:FSEGroupBox>
+ </StackPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettingsView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettingsView.xaml.cs
new file mode 100644
index 000000000..b39d0e146
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetSettingsView.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.Diagnostics.Project.Widgets.Monitor
+{
+ /// <summary>
+ /// Interaction logic for MonitorWidgetSettingsView.xaml
+ /// </summary>
+ public partial class MonitorWidgetSettingsView : UserControl
+ {
+ public MonitorWidgetSettingsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetView.xaml
new file mode 100644
index 000000000..1d8ba96a6
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetView.xaml
@@ -0,0 +1,32 @@
+<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.Monitor.MonitorWidgetView"
+ 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:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets.Monitor"
+ mc:Ignorable="d"
+ d:DesignHeight="250" d:DesignWidth="400" d:DataContext="{d:DesignInstance Type=local:MonitorWidget,IsDesignTimeCreatable=False}">
+ <Grid>
+ <Viewbox Stretch="Fill">
+ <StackPanel>
+ <Grid Grid.Column="1" Grid.Row="1" Width="200" Height="120">
+ <Border BorderThickness="0" BorderBrush="{StaticResource AccentColorBrush}">
+ <Border.Background>
+ <ImageBrush ImageSource="../Monitor/Images/tft_screen.png" Opacity="1" />
+ </Border.Background>
+
+ <Grid>
+ <Viewbox Stretch="Uniform" Width="150" VerticalAlignment="Center" Margin="25 10 10 10" HorizontalAlignment="Left">
+ <TextBlock FontFamily="{StaticResource digital-7}" TextAlignment="Left" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="90" Text="{Binding Value,FallbackValue='0000'}">
+ <TextBlock.Foreground>
+ <SolidColorBrush Color="{Binding Settings.Color}"></SolidColorBrush>
+ </TextBlock.Foreground>
+ </TextBlock>
+ </Viewbox>
+ </Grid>
+ </Border>
+ </Grid>
+ </StackPanel>
+ </Viewbox>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetView.xaml.cs
new file mode 100644
index 000000000..b97823e13
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/Monitor/MonitorWidgetView.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.Diagnostics.Project.Widgets.Monitor
+{
+ /// <summary>
+ /// Interaction logic for MonitorWidgetView.xaml
+ /// </summary>
+ public partial class MonitorWidgetView : UserControl
+ {
+ public MonitorWidgetView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidget.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidget.cs
new file mode 100644
index 000000000..50693746e
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidget.cs
@@ -0,0 +1,22 @@
+using Newtonsoft.Json;
+using RealTimeGraphX.DataPoints;
+using RealTimeGraphX.WPF;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.Core.Commands;
+
+namespace Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph
+{
+ public class RealTimeGraphWidget : RealTimeGraphWidgetBase<RealTimeGraphWidgetSettings>
+ {
+
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidget.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetBase.cs
index 3f8a12182..8e79e53e3 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidget.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetBase.cs
@@ -11,10 +11,11 @@ using System.Windows;
using System.Windows.Media;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
+using Tango.Core.Commands;
-namespace Tango.FSE.Diagnostics.Project.Widgets
+namespace Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph
{
- public class RealTimeGraphWidget : DiagnosticsWidget
+ public abstract class RealTimeGraphWidgetBase<T> : DiagnosticsConfigurableWidget<T> where T : RealTimeGraphWidgetSettings, new()
{
public TechMonitors Monitor { get; set; }
@@ -22,20 +23,41 @@ namespace Tango.FSE.Diagnostics.Project.Widgets
public TechMonitor TechMonitor { get; private set; }
[JsonIgnore]
+ public override string DisplayName
+ {
+ get
+ {
+ return this.TechMonitor != null ? this.TechMonitor.Description : String.Empty;
+ }
+ }
+
+ [JsonIgnore]
public WpfGraphController<TimeSpanDataPoint, DoubleDataPoint> Controller { get; set; }
- public RealTimeGraphWidget()
+ [JsonIgnore]
+ public RelayCommand ClearCommand { get; set; }
+
+ public RealTimeGraphWidgetBase()
{
Controller = new WpfGraphController<TimeSpanDataPoint, DoubleDataPoint>();
- Controller.Range.AutoY = true;
- Controller.Range.MaximumX = TimeSpan.FromSeconds(60);
+ Controller.Range.MinimumY = Settings.Min;
+ Controller.Range.MaximumY = Settings.Max;
+ Controller.Range.AutoY = Settings.AutoRange;
+ Controller.Range.MaximumX = Settings.Duration;
Controller.RefreshRate = TimeSpan.FromMilliseconds(100);
Controller.DisableRendering = true;
Controller.DataSeriesCollection.Add(new WpfGraphDataSeries()
{
- Stroke = Colors.DodgerBlue
+ Stroke = Settings.Color
});
+
+ ClearCommand = new RelayCommand(Clear);
+ }
+
+ public void Clear()
+ {
+ Controller?.Clear();
}
public override async Task Init()
@@ -52,10 +74,27 @@ namespace Tango.FSE.Diagnostics.Project.Widgets
protected override void OnVisibleChanged(bool isVisible)
{
base.OnVisibleChanged(isVisible);
-
Controller.DisableRendering = !isVisible;
}
+ protected override void OnSettingsChanged()
+ {
+ base.OnSettingsChanged();
+
+ if (Controller != null)
+ {
+ Controller.Range.MinimumY = Settings.Min;
+ Controller.Range.MaximumY = Settings.Max;
+ Controller.Range.AutoY = Settings.AutoRange;
+ Controller.Range.MaximumX = Settings.Duration;
+
+ if (Controller.DataSeriesCollection.Count > 0)
+ {
+ Controller.DataSeriesCollection[0].Stroke = Settings.Color;
+ }
+ }
+ }
+
public override void OnDiagnosticsData(DiagnosticsPackage package)
{
var points = package.GetMonitorArray(Monitor);
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettings.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettings.cs
new file mode 100644
index 000000000..2ebb1f127
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettings.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+using Tango.Core;
+
+namespace Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph
+{
+ public class RealTimeGraphWidgetSettings : DiagnosticsWidgetSettings
+ {
+ private TimeSpan _duration;
+ public TimeSpan Duration
+ {
+ get { return _duration; }
+ set { _duration = value; RaisePropertyChangedAuto(); }
+ }
+
+ private int _decimalPlaces;
+ public int DecimalPlaces
+ {
+ get { return _decimalPlaces; }
+ set { _decimalPlaces = value; RaisePropertyChangedAuto(); }
+ }
+
+ private double _min;
+ public double Min
+ {
+ get { return _min; }
+ set { _min = value; RaisePropertyChangedAuto(); }
+ }
+
+ private double _max;
+ public double Max
+ {
+ get { return _max; }
+ set { _max = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _autoRange;
+ public bool AutoRange
+ {
+ get { return _autoRange; }
+ set { _autoRange = value; RaisePropertyChangedAuto(); }
+ }
+
+ private Color _color;
+ public Color Color
+ {
+ get { return _color; }
+ set { _color = value; RaisePropertyChangedAuto(); }
+ }
+
+ public RealTimeGraphWidgetSettings()
+ {
+ Duration = TimeSpan.FromMinutes(10);
+ DecimalPlaces = 0;
+ Min = 0;
+ Max = 1000;
+ AutoRange = true;
+ Color = Colors.DodgerBlue;
+ }
+
+ public override FrameworkElement GetView()
+ {
+ return new RealTimeGraphWidgetSettingsView() { DataContext = this };
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettingsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettingsView.xaml
new file mode 100644
index 000000000..333f21b76
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettingsView.xaml
@@ -0,0 +1,66 @@
+<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph.RealTimeGraphWidgetSettingsView"
+ 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:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
+ xmlns:colorPicker="clr-namespace:Tango;assembly=Tango.ColorPicker"
+ xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph"
+ mc:Ignorable="d"
+ d:DesignHeight="1200" d:DesignWidth="600" d:DataContext="{d:DesignInstance Type=local:RealTimeGraphWidget,IsDesignTimeCreatable=False}">
+ <Grid>
+ <StackPanel>
+
+ <controls:FSEGroupBox Header="DURATION" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <StackPanel>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Right" FontSize="{StaticResource FSE_SmallerFontSize}" Text="{Binding Settings.Duration,Mode=OneWay}" />
+ <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}">Maximum Visible Time</TextBlock>
+ </DockPanel>
+ <Slider Margin="0 5 0 0" Minimum="10" Maximum="3600" IsSnapToTickEnabled="True" Value="{Binding Settings.Duration,Converter={StaticResource TimeSpanToSecondsConverter},Mode=TwoWay}"></Slider>
+ </StackPanel>
+ </controls:FSEGroupBox>
+
+ <controls:FSEGroupBox Margin="0 10 0 0" Header="RANGE" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <StackPanel>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Right" FontSize="{StaticResource FSE_SmallerFontSize}" >
+ <Run Text="{Binding Settings.Min,Mode=OneWay}"></Run>
+ <Run>-</Run>
+ <Run Text="{Binding Settings.Max,Mode=OneWay}"></Run>
+ </TextBlock>
+ <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}" >Y Min/Max</TextBlock>
+ </DockPanel>
+ <mahapps:RangeSlider Margin="0 5 0 0"
+ Minimum="-100000"
+ Interval="1"
+ Maximum="100000"
+ SmallChange="1"
+ IsSnapToTickEnabled="True"
+ AutoToolTipPlacement="None"
+ LowerValue="{Binding Settings.Min,UpdateSourceTrigger=PropertyChanged}"
+ UpperValue="{Binding Settings.Max,UpdateSourceTrigger=PropertyChanged}"/>
+
+ <CheckBox Margin="0 10 0 0" IsChecked="{Binding Settings.AutoRange}">Auto Range</CheckBox>
+ </StackPanel>
+ </controls:FSEGroupBox>
+
+ <controls:FSEGroupBox Header="FORMAT" Margin="0 10 0 0" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <StackPanel>
+ <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}" >Decimal Places</TextBlock>
+ <mahapps:NumericUpDown Background="Transparent" BorderThickness="0 0 0 1" HorizontalContentAlignment="Left" Minimum="0" Maximum="3" Focusable="False" Value="{Binding Settings.DecimalPlaces,UpdateSourceTrigger=PropertyChanged}" />
+ </StackPanel>
+ </controls:FSEGroupBox>
+
+ <controls:FSEGroupBox Header="COLOR" Margin="0 10 0 0" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <Viewbox>
+ <colorPicker:ColorCanvas Background="Transparent" BorderThickness="0" FontSize="{StaticResource FSE_SmallerFontSize}" SelectedColor="{Binding Settings.Color,Mode=TwoWay}" />
+ </Viewbox>
+ </controls:FSEGroupBox>
+
+ <Button Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Margin="0 20 0 0" Height="50" material:ButtonAssist.CornerRadius="25" Command="{Binding ClearCommand}">CLEAR</Button>
+ </StackPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettingsView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettingsView.xaml.cs
new file mode 100644
index 000000000..2aefc0835
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetSettingsView.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.Diagnostics.Project.Widgets.RealTimeGraph
+{
+ /// <summary>
+ /// Interaction logic for RealTimeGraphWidgetSettingsView.xaml
+ /// </summary>
+ public partial class RealTimeGraphWidgetSettingsView : UserControl
+ {
+ public RealTimeGraphWidgetSettingsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetView.xaml
index cd2735e2a..f08274275 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetView.xaml
@@ -1,13 +1,13 @@
-<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphWidgetView"
+<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph.RealTimeGraphWidgetView"
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:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets"
+ xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph"
xmlns:graphs="clr-namespace:Tango.FSE.Common.Graphs;assembly=Tango.FSE.Common"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=local:RealTimeGraphWidget,IsDesignTimeCreatable=False}">
<Grid>
- <graphs:RealTimeGraph HorizontalTicks="7" VerticalTicks="5" Controller="{Binding Controller}" />
+ <graphs:RealTimeGraph Style="{StaticResource FSE_RealTimeGraph_Diagnostics}" StringFormat="{Binding Settings.DecimalPlaces,Converter={StaticResource DecimalPlacesToStringFormatConverter}}" Controller="{Binding Controller}" />
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetView.xaml.cs
index 546a55f74..043293c9b 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphWidgetView.xaml.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraph/RealTimeGraphWidgetView.xaml.cs
@@ -13,7 +13,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
-namespace Tango.FSE.Diagnostics.Project.Widgets
+namespace Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph
{
/// <summary>
/// Interaction logic for RealTimeGraphWidgetView.xaml
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidget.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidget.cs
index 25425a683..1ebaa199e 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidget.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidget.cs
@@ -8,10 +8,11 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
+using Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph;
-namespace Tango.FSE.Diagnostics.Project.Widgets
+namespace Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel
{
- public class RealTimeGraphMultiChannelWidget : RealTimeGraphWidget
+ public class RealTimeGraphMultiChannelWidget : RealTimeGraphWidgetBase<RealTimeGraphMultiChannelWidgetSettings>
{
public async override Task Init()
{
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettings.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettings.cs
new file mode 100644
index 000000000..9bc05c74f
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettings.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+using Tango.Core;
+using Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph;
+
+namespace Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel
+{
+ public class RealTimeGraphMultiChannelWidgetSettings : RealTimeGraphWidgetSettings
+ {
+ public override FrameworkElement GetView()
+ {
+ return new RealTimeGraphMultiChannelWidgetSettingsView() { DataContext = this };
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettingsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettingsView.xaml
new file mode 100644
index 000000000..0ac731be0
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettingsView.xaml
@@ -0,0 +1,100 @@
+<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel.RealTimeGraphMultiChannelWidgetSettingsView"
+ 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:material="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
+ xmlns:colorPicker="clr-namespace:Tango;assembly=Tango.ColorPicker"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="600" d:DataContext="{d:DesignInstance Type=local:RealTimeGraphMultiChannelWidget,IsDesignTimeCreatable=False}">
+ <Grid>
+ <StackPanel>
+
+ <controls:FSEGroupBox Header="DURATION" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <StackPanel>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Right" FontSize="{StaticResource FSE_SmallerFontSize}" Text="{Binding Settings.Duration,Mode=OneWay}" />
+ <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}">Maximum Visible Time</TextBlock>
+ </DockPanel>
+ <Slider Margin="0 5 0 0" Minimum="10" Maximum="3600" IsSnapToTickEnabled="True" Value="{Binding Settings.Duration,Converter={StaticResource TimeSpanToSecondsConverter},Mode=TwoWay}"></Slider>
+ </StackPanel>
+ </controls:FSEGroupBox>
+
+ <controls:FSEGroupBox Margin="0 10 0 0" Header="RANGE" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <StackPanel>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Right" FontSize="{StaticResource FSE_SmallerFontSize}" >
+ <Run Text="{Binding Settings.Min,Mode=OneWay}"></Run>
+ <Run>-</Run>
+ <Run Text="{Binding Settings.Max,Mode=OneWay}"></Run>
+ </TextBlock>
+ <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}" >Y Min/Max</TextBlock>
+ </DockPanel>
+ <mahapps:RangeSlider Margin="0 5 0 0"
+ Minimum="-100000"
+ Interval="1"
+ Maximum="100000"
+ SmallChange="1"
+ IsSnapToTickEnabled="True"
+ AutoToolTipPlacement="None"
+ LowerValue="{Binding Settings.Min,UpdateSourceTrigger=PropertyChanged}"
+ UpperValue="{Binding Settings.Max,UpdateSourceTrigger=PropertyChanged}"/>
+
+ <CheckBox Margin="0 10 0 0" IsChecked="{Binding Settings.AutoRange}">Auto Range</CheckBox>
+ </StackPanel>
+ </controls:FSEGroupBox>
+
+ <controls:FSEGroupBox Header="FORMAT" Margin="0 10 0 0" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <StackPanel>
+ <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}" >Decimal Places</TextBlock>
+ <mahapps:NumericUpDown Background="Transparent" BorderThickness="0 0 0 1" HorizontalContentAlignment="Left" Minimum="0" Maximum="3" Focusable="False" Value="{Binding Settings.DecimalPlaces,UpdateSourceTrigger=PropertyChanged}" />
+ </StackPanel>
+ </controls:FSEGroupBox>
+
+ <controls:FSEGroupBox Header="VISIBILITY" Margin="0 10 0 0" HeaderFontSize="{StaticResource FSE_SmallFontSize}">
+ <Border TextElement.FontSize="{StaticResource FSE_SmallFontSize}">
+ <ItemsControl ItemsSource="{Binding Controller.DataSeriesCollection}">
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <ToggleButton IsChecked="{Binding IsVisible}" Cursor="Hand">
+ <ToggleButton.Template>
+ <ControlTemplate>
+ <StackPanel Orientation="Horizontal" Margin="0 2" Background="Transparent">
+ <Ellipse Width="10" Height="10">
+ <Ellipse.Style>
+ <Style TargetType="Ellipse">
+ <Setter Property="Fill" Value="Black"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding IsVisible}" Value="True">
+ <Setter Property="Fill">
+ <Setter.Value>
+ <SolidColorBrush Color="{Binding Stroke}" />
+ </Setter.Value>
+ </Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Ellipse.Style>
+ </Ellipse>
+ <TextBlock Margin="5 0 0 0" Text="{Binding Name}">
+ <TextBlock.Foreground>
+ <SolidColorBrush Color="{Binding Stroke}" />
+ </TextBlock.Foreground>
+ </TextBlock>
+ </StackPanel>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </Border>
+ </controls:FSEGroupBox>
+
+ <Button Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Margin="0 20 0 0" Height="50" material:ButtonAssist.CornerRadius="25" Command="{Binding ClearCommand}">CLEAR</Button>
+ </StackPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettingsView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettingsView.xaml.cs
new file mode 100644
index 000000000..936efc60a
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetSettingsView.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.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel
+{
+ /// <summary>
+ /// Interaction logic for RealTimeGraphWidgetSettingsView.xaml
+ /// </summary>
+ public partial class RealTimeGraphMultiChannelWidgetSettingsView : UserControl
+ {
+ public RealTimeGraphMultiChannelWidgetSettingsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetView.xaml
new file mode 100644
index 000000000..6ff068180
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetView.xaml
@@ -0,0 +1,13 @@
+<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel.RealTimeGraphMultiChannelWidgetView"
+ 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:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel"
+ xmlns:graphs="clr-namespace:Tango.FSE.Common.Graphs;assembly=Tango.FSE.Common"
+ mc:Ignorable="d"
+ d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=local:RealTimeGraphMultiChannelWidget,IsDesignTimeCreatable=False}">
+ <Grid>
+ <graphs:RealTimeGraph Style="{StaticResource FSE_RealTimeGraph_Diagnostics}" Controller="{Binding Controller}" StringFormat="{Binding Settings.DecimalPlaces,Converter={StaticResource DecimalPlacesToStringFormatConverter}}" />
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidgetView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetView.xaml.cs
index 944f73dc3..3c7c061d2 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidgetView.xaml.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannel/RealTimeGraphMultiChannelWidgetView.xaml.cs
@@ -13,7 +13,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
-namespace Tango.FSE.Diagnostics.Project.Widgets
+namespace Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel
{
/// <summary>
/// Interaction logic for RealTimeGraphWidgetView.xaml
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidgetView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidgetView.xaml
deleted file mode 100644
index a248ac6e4..000000000
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Project/Widgets/RealTimeGraphMultiChannelWidgetView.xaml
+++ /dev/null
@@ -1,53 +0,0 @@
-<UserControl x:Class="Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannelWidgetView"
- 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:local="clr-namespace:Tango.FSE.Diagnostics.Project.Widgets"
- xmlns:graphs="clr-namespace:Tango.FSE.Common.Graphs;assembly=Tango.FSE.Common"
- mc:Ignorable="d"
- d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=local:RealTimeGraphMultiChannelWidget,IsDesignTimeCreatable=False}">
- <Grid>
- <DockPanel>
- <Border Margin="2 0 0 0" DockPanel.Dock="Right" HorizontalAlignment="Right" BorderThickness="1" BorderBrush="{StaticResource FSE_RealTimeGraph_OuterBorderBrush}" Background="{StaticResource FSE_RealTimeGraph_BackgroundBrush}" CornerRadius="5" TextElement.FontSize="{StaticResource FSE_SmallerFontSize}" Padding="5" MaxWidth="83">
- <ItemsControl ItemsSource="{Binding Controller.DataSeriesCollection}">
- <ItemsControl.ItemTemplate>
- <DataTemplate>
- <ToggleButton IsChecked="{Binding IsVisible}" Cursor="Hand">
- <ToggleButton.Template>
- <ControlTemplate>
- <StackPanel Orientation="Horizontal" Margin="0 2" Background="Transparent">
- <Ellipse Width="10" Height="10">
- <Ellipse.Style>
- <Style TargetType="Ellipse">
- <Setter Property="Fill" Value="Black"></Setter>
- <Style.Triggers>
- <DataTrigger Binding="{Binding IsVisible}" Value="True">
- <Setter Property="Fill">
- <Setter.Value>
- <SolidColorBrush Color="{Binding Stroke}" />
- </Setter.Value>
- </Setter>
- </DataTrigger>
- </Style.Triggers>
- </Style>
- </Ellipse.Style>
- </Ellipse>
- <TextBlock Margin="5 0 0 0" Text="{Binding Name}">
- <TextBlock.Foreground>
- <SolidColorBrush Color="{Binding Stroke}" />
- </TextBlock.Foreground>
- </TextBlock>
- </StackPanel>
- </ControlTemplate>
- </ToggleButton.Template>
- </ToggleButton>
- </DataTemplate>
- </ItemsControl.ItemTemplate>
- </ItemsControl>
- </Border>
-
- <graphs:RealTimeGraph Controller="{Binding Controller}" HorizontalTicks="7" VerticalTicks="5" />
- </DockPanel>
- </Grid>
-</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj
index b39213edf..2b3699858 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Tango.FSE.Diagnostics.csproj
@@ -62,6 +62,7 @@
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll</HintPath>
</Reference>
@@ -80,19 +81,41 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Controls\DiagnosticsGrid.cs" />
+ <Compile Include="Converters\DecimalPlacesToStringFormatConverter.cs" />
+ <Compile Include="Converters\DiagnosticsWidgetToSettingsViewConverter.cs" />
<Compile Include="Converters\DiagnosticsWidgetToViewConverter.cs" />
+ <Compile Include="Converters\PercentageToWidthConverter.cs" />
<Compile Include="DiagnosticsPackage.cs" />
+ <Compile Include="Project\DiagnosticsConfigurableWidget.cs" />
<Compile Include="Project\DiagnosticsProject.cs" />
<Compile Include="Project\DiagnosticsProjectTab.cs" />
<Compile Include="Project\DiagnosticsProjectTabColumnDefinition.cs" />
<Compile Include="Project\DiagnosticsProjectTabRowDefinition.cs" />
<Compile Include="Project\DiagnosticsWidget.cs" />
- <Compile Include="Project\Widgets\RealTimeGraphMultiChannelWidget.cs" />
- <Compile Include="Project\Widgets\RealTimeGraphWidget.cs" />
- <Compile Include="Project\Widgets\RealTimeGraphMultiChannelWidgetView.xaml.cs">
+ <Compile Include="Project\DiagnosticsWidgetSettings.cs" />
+ <Compile Include="Project\Widgets\Monitor\MonitorWidget.cs" />
+ <Compile Include="Project\Widgets\Monitor\MonitorWidgetSettings.cs" />
+ <Compile Include="Project\Widgets\Monitor\MonitorWidgetSettingsView.xaml.cs">
+ <DependentUpon>MonitorWidgetSettingsView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Project\Widgets\Monitor\MonitorWidgetView.xaml.cs">
+ <DependentUpon>MonitorWidgetView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Project\Widgets\RealTimeGraphMultiChannel\RealTimeGraphMultiChannelWidget.cs" />
+ <Compile Include="Project\Widgets\RealTimeGraphMultiChannel\RealTimeGraphMultiChannelWidgetSettingsView.xaml.cs">
+ <DependentUpon>RealTimeGraphMultiChannelWidgetSettingsView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Project\Widgets\RealTimeGraphMultiChannel\RealTimeGraphMultiChannelWidgetSettings.cs" />
+ <Compile Include="Project\Widgets\RealTimeGraph\RealTimeGraphWidgetBase.cs" />
+ <Compile Include="Project\Widgets\RealTimeGraph\RealTimeGraphWidgetSettings.cs" />
+ <Compile Include="Project\Widgets\RealTimeGraph\RealTimeGraphWidget.cs" />
+ <Compile Include="Project\Widgets\RealTimeGraphMultiChannel\RealTimeGraphMultiChannelWidgetView.xaml.cs">
<DependentUpon>RealTimeGraphMultiChannelWidgetView.xaml</DependentUpon>
</Compile>
- <Compile Include="Project\Widgets\RealTimeGraphWidgetView.xaml.cs">
+ <Compile Include="Project\Widgets\RealTimeGraph\RealTimeGraphWidgetSettingsView.xaml.cs">
+ <DependentUpon>RealTimeGraphWidgetSettingsView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Project\Widgets\RealTimeGraph\RealTimeGraphWidgetView.xaml.cs">
<DependentUpon>RealTimeGraphWidgetView.xaml</DependentUpon>
</Compile>
<Compile Include="ViewModelLocator.cs" />
@@ -157,6 +180,10 @@
<Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project>
<Name>Tango.BL</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.ColorPicker\Tango.ColorPicker.csproj">
+ <Project>{a2f5af44-29ff-45d6-9d25-ecda5cce88b5}</Project>
+ <Name>Tango.ColorPicker</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\..\Tango.Core\Tango.Core.csproj">
<Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
<Name>Tango.Core</Name>
@@ -199,11 +226,31 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
- <Page Include="Project\Widgets\RealTimeGraphMultiChannelWidgetView.xaml">
+ <Page Include="Project\Widgets\Monitor\MonitorWidgetSettingsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Project\Widgets\Monitor\MonitorWidgetView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Project\Widgets\RealTimeGraphMultiChannel\RealTimeGraphMultiChannelWidgetView.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Project\Widgets\RealTimeGraphMultiChannel\RealTimeGraphMultiChannelWidgetSettingsView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
- <Page Include="Project\Widgets\RealTimeGraphWidgetView.xaml">
+ <Page Include="Project\Widgets\RealTimeGraph\RealTimeGraphWidgetSettingsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Project\Widgets\RealTimeGraph\RealTimeGraphWidgetView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Themes\Generic.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
@@ -223,7 +270,9 @@
<ItemGroup>
<Resource Include="Images\diagnostics.png" />
</ItemGroup>
- <ItemGroup />
+ <ItemGroup>
+ <Resource Include="Project\Widgets\Monitor\Images\tft_screen.png" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets" Condition="Exists('..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Themes/Generic.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Themes/Generic.xaml
new file mode 100644
index 000000000..2428e9255
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Themes/Generic.xaml
@@ -0,0 +1,60 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:graphs="clr-namespace:Tango.FSE.Common.Graphs;assembly=Tango.FSE.Common"
+ xmlns:localConverters="clr-namespace:Tango.FSE.Diagnostics.Converters"
+ xmlns:realTimeGraphX="clr-namespace:RealTimeGraphX.WPF;assembly=RealTimeGraphX.WPF"
+ xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Themes">
+
+ <localConverters:DecimalPlacesToStringFormatConverter x:Key="DecimalPlacesToStringFormatConverter" />
+
+ <Style TargetType="{x:Type graphs:RealTimeGraph}" x:Key="FSE_RealTimeGraph_Diagnostics">
+ <Setter Property="BorderThickness" Value="1"></Setter>
+ <Setter Property="BorderBrush" Value="{StaticResource FSE_RealTimeGraph_OuterBorderBrush}"></Setter>
+ <Setter Property="Padding" Value="20 20 30 20"></Setter>
+ <Setter Property="FontSize" Value="11"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource FSE_RealTimeGraph_ForegroundBrush}"></Setter>
+ <Setter Property="Background" Value="{StaticResource FSE_RealTimeGraph_BackgroundBrush}"></Setter>
+ <Setter Property="GridLinesBrush" Value="{StaticResource FSE_RealTimeGraph_GridLinesBrush}"></Setter>
+ <Setter Property="HorizontalTicks" Value="7"></Setter>
+ <Setter Property="VerticalTicks" Value="5"></Setter>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type graphs:RealTimeGraph}">
+ <Grid>
+ <Border Background="{TemplateBinding Background}"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ CornerRadius="5"
+ Padding="{TemplateBinding Padding}">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="1*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="1*"/>
+ </Grid.ColumnDefinitions>
+
+ <Grid Grid.Column="1">
+ <realTimeGraphX:WpfGraphGridLines Columns="{TemplateBinding HorizontalTicks}" Rows="{TemplateBinding VerticalTicks}" Controller="{TemplateBinding Controller}" Foreground="{TemplateBinding GridLinesBrush}" />
+ <realTimeGraphX:WpfGraphSurface x:Name="surface" Controller="{TemplateBinding Controller}" BorderThickness="1 0 0 1" BorderBrush="{StaticResource FSE_RealTimeGraph_InnerBorderBrush}" />
+ </Grid>
+
+ <realTimeGraphX:WpfGraphAxisControl Width="70" Visibility="{TemplateBinding VerticalAxisVisibility}" Orientation="Vertical" Controller="{TemplateBinding Controller}" StringFormat="{TemplateBinding StringFormat}" Ticks="{TemplateBinding VerticalTicks}" />
+ <realTimeGraphX:WpfGraphAxisControl Height="35" Visibility="{TemplateBinding HorizontalAxisVisibility}" Orientation="Horizontal" Controller="{TemplateBinding Controller}" Grid.Column="1" Grid.Row="1" Ticks="{TemplateBinding HorizontalTicks}" StringFormat="hh\:mm\:ss"/>
+ </Grid>
+ </Border>
+ <Image HorizontalAlignment="Left" VerticalAlignment="Top" Margin="8" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="10" Height="10" />
+ <Image HorizontalAlignment="Right" VerticalAlignment="Top" Margin="8" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="10" Height="10" />
+
+ <Image HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="8" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="10" Height="10" />
+ <Image HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="8" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="10" Height="10" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+
+</ResourceDictionary> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs
index a439eeeee..acea47b10 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsTabViewVM.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.Core.Commands;
using Tango.FSE.Common;
using Tango.FSE.Diagnostics.Project;
using Tango.PMR.Diagnostics;
@@ -25,6 +26,35 @@ namespace Tango.FSE.Diagnostics.ViewModels
set { _isSelected = value; RaisePropertyChangedAuto(); OnIsSelectedChanged(); }
}
+ private DiagnosticsWidget _selectedWidget;
+ public DiagnosticsWidget SelectedWidget
+ {
+ get { return _selectedWidget; }
+ set { _selectedWidget = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isWidgetSettingsOpened;
+ public bool IsWidgetSettingsOpened
+ {
+ get { return _isWidgetSettingsOpened; }
+ set { _isWidgetSettingsOpened = value; RaisePropertyChangedAuto(); }
+ }
+
+ public RelayCommand<DiagnosticsWidget> OpenWidgetSettingsCommand { get; set; }
+
+ public RelayCommand CloseWidgetSettingsCommand { get; set; }
+
+ public DiagnosticsTabViewVM()
+ {
+ OpenWidgetSettingsCommand = new RelayCommand<DiagnosticsWidget>(OpenWidgetSettings);
+ CloseWidgetSettingsCommand = new RelayCommand(() => IsWidgetSettingsOpened = false);
+ }
+
+ private void OpenWidgetSettings(DiagnosticsWidget widget)
+ {
+ IsWidgetSettingsOpened = true;
+ }
+
private void OnIsSelectedChanged()
{
Tab.Widgets.ToList().ForEach(x => x.IsVisible = IsSelected);
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs
index 9c5ebaa66..75c623c62 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
+using Tango.Core.Commands;
using Tango.FSE.Common;
using Tango.FSE.Common.Diagnostics;
using Tango.FSE.Diagnostics.Project;
@@ -17,6 +18,15 @@ namespace Tango.FSE.Diagnostics.ViewModels
{
private Dictionary<String, PropertyInfo> _monitorsProperties;
private bool _isLoaded;
+ private string _diagnosticsProjectFile;
+ private FileSystemWatcher _diagnosticsProjectFileWatcher;
+
+ private bool _isLoadingProject;
+ public bool IsLoadingProject
+ {
+ get { return _isLoadingProject; }
+ set { _isLoadingProject = value; RaisePropertyChangedAuto(); }
+ }
private DiagnosticsProject _project;
public DiagnosticsProject Project
@@ -39,6 +49,8 @@ namespace Tango.FSE.Diagnostics.ViewModels
set { _selectedTab = value; RaisePropertyChangedAuto(); OnSelectedTabChanged(); }
}
+ public RelayCommand ExportProjectCommand { get; set; }
+
public DiagnosticsViewVM()
{
_monitorsProperties = new Dictionary<string, PropertyInfo>();
@@ -50,12 +62,39 @@ namespace Tango.FSE.Diagnostics.ViewModels
Tabs = new ObservableCollection<DiagnosticsTabViewVM>();
Project = new DiagnosticsProject();
+
+ ExportProjectCommand = new RelayCommand(ExportProject);
}
public override void OnApplicationStarted()
{
base.OnApplicationStarted();
DiagnosticsProvider.FrameReceived += DiagnosticsProvider_FrameReceived;
+
+ _diagnosticsProjectFileWatcher = new FileSystemWatcher(ApplicationManager.StartPath, "diagnostics.json");
+ _diagnosticsProjectFileWatcher.Changed += _diagnosticsProjectFileWatcher_Changed;
+ _diagnosticsProjectFileWatcher.EnableRaisingEvents = true;
+ }
+
+ private void _diagnosticsProjectFileWatcher_Changed(object sender, FileSystemEventArgs e)
+ {
+ InvokeUI(async () =>
+ {
+ int selectedIndex = 0;
+
+ if (SelectedTab != null)
+ {
+ selectedIndex = Tabs.IndexOf(SelectedTab);
+ }
+
+ await Task.Delay(200);
+ await LoadProject();
+
+ if (selectedIndex > 0 && Tabs.Count > selectedIndex)
+ {
+ SelectedTab = Tabs[selectedIndex];
+ }
+ });
}
private void DiagnosticsProvider_FrameReceived(object sender, DiagnosticsFrameReceivedEventArgs e)
@@ -63,22 +102,26 @@ namespace Tango.FSE.Diagnostics.ViewModels
PopulateDiagnosticsData(e.Frame);
}
- public override void OnApplicationReady()
+ public async override void OnApplicationReady()
{
base.OnApplicationReady();
if (!_isLoaded)
{
- LoadProject();
+ _diagnosticsProjectFile = Path.Combine(ApplicationManager.StartPath, "diagnostics.json");
+ await LoadProject();
}
}
- private async void LoadProject()
+ private async Task LoadProject()
{
- Project = DiagnosticsProject.FromFile(Path.Combine(ApplicationManager.StartPath, "diagnostics.json"));
+ Project = DiagnosticsProject.FromFile(_diagnosticsProjectFile);
try
{
+ IsLoadingProject = true;
+ _isLoaded = false;
+
await Services.TechComponentsService.Preload();
foreach (var widget in Project.Tabs.SelectMany(x => x.Widgets))
@@ -108,16 +151,15 @@ namespace Tango.FSE.Diagnostics.ViewModels
NotificationProvider.PushErrorReportingSnackbar(ex, "Diagnostics Module Error", "Error initializing diagnostics module.");
return;
}
+ finally
+ {
+ IsLoadingProject = false;
+ }
}
private void OnSelectedTabChanged()
{
- //if (SelectedTab != null)
- //{
- // Tabs.Where(x => x != SelectedTab).SelectMany(x => x.Tab.Widgets).ToList().ForEach(x => x.IsVisible = false);
- // SelectedTab.Tab.Widgets.ToList().ForEach(x => x.IsVisible = true);
- //}
}
private void PopulateDiagnosticsData(DiagnosticsFrame frame)
@@ -134,5 +176,23 @@ namespace Tango.FSE.Diagnostics.ViewModels
}
}
}
+
+ private async void ExportProject()
+ {
+ var result = await StorageProvider.SaveFile("Export diagnostics project", "Diagnostics Projects|*.json", "diagnostics.json", ".json");
+
+ if (result.Confirmed)
+ {
+ try
+ {
+ Project.ToFile(result.SelectedItem);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error exporting diagnostics project.");
+ await NotificationProvider.ShowError($"Error exporting diagnostics project\n{ex.FlattenMessage()}");
+ }
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml
index c53998f4d..7a8545f86 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsTabView.xaml
@@ -4,7 +4,10 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:global="clr-namespace:Tango.FSE.Diagnostics"
+ xmlns:commonControls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
xmlns:vm="clr-namespace:Tango.FSE.Diagnostics.ViewModels"
+ xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+ xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:controls="clr-namespace:Tango.FSE.Diagnostics.Controls"
xmlns:local="clr-namespace:Tango.FSE.Diagnostics.Views"
xmlns:converters="clr-namespace:Tango.FSE.Diagnostics.Converters"
@@ -13,29 +16,100 @@
<UserControl.Resources>
<converters:DiagnosticsWidgetToViewConverter x:Key="DiagnosticsWidgetToViewConverter" />
+ <converters:DiagnosticsWidgetToSettingsViewConverter x:Key="DiagnosticsWidgetToSettingsViewConverter" />
+ <converters:PercentageToWidthConverter x:Key="PercentageToWidthConverter" />
</UserControl.Resources>
<Grid>
- <ItemsControl ItemsSource="{Binding Tab.Widgets}">
- <ItemsControl.ItemsPanel>
+ <ListBox HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" ItemsSource="{Binding Tab.Widgets}" SelectedItem="{Binding SelectedWidget,Mode=TwoWay}" Style="{StaticResource FSE_BlankListBox}" ScrollViewer.VerticalScrollBarVisibility="Disabled">
+ <ListBox.ItemsPanel>
<ItemsPanelTemplate>
<controls:DiagnosticsGrid IsItemsHost="True" ShowGridLines="False" Columns="{Binding Tab.Columns}" Rows="{Binding Tab.Rows}"/>
</ItemsPanelTemplate>
- </ItemsControl.ItemsPanel>
- <ItemsControl.ItemContainerStyle>
- <Style TargetType="FrameworkElement">
+ </ListBox.ItemsPanel>
+ <ListBox.ItemContainerStyle>
+ <Style TargetType="ListBoxItem" BasedOn="{StaticResource FSE_BlankListBoxItem}">
<Setter Property="Grid.Column" Value="{Binding Column}"></Setter>
<Setter Property="Grid.Row" Value="{Binding Row}"></Setter>
<Setter Property="Grid.ColumnSpan" Value="{Binding ColumnSpan}"></Setter>
<Setter Property="Grid.RowSpan" Value="{Binding RowSpan}"></Setter>
<Setter Property="Margin" Value="5"></Setter>
</Style>
- </ItemsControl.ItemContainerStyle>
+ </ListBox.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
- <ContentPresenter Content="{Binding Converter={StaticResource DiagnosticsWidgetToViewConverter}}"/>
+ <Grid x:Name="parentGrid">
+ <Grid x:Name="widgetGrid" Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center">
+ <Grid.Width>
+ <MultiBinding Converter="{StaticResource PercentageToWidthConverter}">
+ <Binding ElementName="parentGrid" Path="ActualWidth" />
+ <Binding Path="Width" />
+ </MultiBinding>
+ </Grid.Width>
+ <Grid.Height>
+ <MultiBinding Converter="{StaticResource PercentageToWidthConverter}">
+ <Binding ElementName="parentGrid" Path="ActualHeight" />
+ <Binding Path="Height" />
+ </MultiBinding>
+ </Grid.Height>
+
+ <ContentPresenter Content="{Binding Converter={StaticResource DiagnosticsWidgetToViewConverter}}"/>
+
+ <Grid HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="32" Height="32" Margin="10" Visibility="{Binding Settings,Converter={StaticResource IsNullToVisibilityConverter},FallbackValue='Collapsed',TargetNullValue='Collapsed'}">
+ <i:Interaction.Triggers>
+ <i:EventTrigger EventName="PreviewMouseUp">
+ <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.OpenWidgetSettingsCommand}" CommandParameter="{Binding}" />
+ </i:EventTrigger>
+ </i:Interaction.Triggers>
+ <Grid Cursor="Hand" Visibility="{Binding ElementName=widgetGrid,Path=IsMouseOver,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <Grid.Style>
+ <Style TargetType="Grid">
+ <Setter Property="Opacity" Value="0.6"></Setter>
+ <Style.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Opacity" Value="1"></Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </Grid.Style>
+ <Ellipse Fill="#202020"/>
+ <material:PackIcon HorizontalAlignment="Center" VerticalAlignment="Center" Width="20" Height="20" Kind="SettingsOutline" />
+ </Grid>
+ </Grid>
+ </Grid>
+ </Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
- </ItemsControl>
+ </ListBox>
+
+ <Grid Margin="20" HorizontalAlignment="Right" Width="300">
+ <Grid.Style>
+ <Style TargetType="Grid">
+ <Setter Property="Visibility" Value="Collapsed"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding IsWidgetSettingsOpened}" Value="True">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Grid.Style>
+ <Border Background="#B1393939" CornerRadius="5">
+ <Border.Effect>
+ <DropShadowEffect ShadowDepth="0" />
+ </Border.Effect>
+
+ <DockPanel>
+ <Border DockPanel.Dock="Top" Background="{StaticResource FSE_PrimaryBackgroundBrush}" CornerRadius="5 5 0 0">
+ <DockPanel Margin="20 10 10 10">
+ <commonControls:IconButton Command="{Binding CloseWidgetSettingsCommand}" ToolTip="Close Settings" Icon="Close" DockPanel.Dock="Right" Padding="0" Width="24" Height="24"></commonControls:IconButton>
+ <TextBlock VerticalAlignment="Center" Text="{Binding SelectedWidget.DisplayName,Mode=OneWay}"></TextBlock>
+ </DockPanel>
+ </Border>
+ <ScrollViewer Padding="10" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
+ <ContentPresenter Content="{Binding SelectedWidget,Converter={StaticResource DiagnosticsWidgetToSettingsViewConverter}}" />
+ </ScrollViewer>
+ </DockPanel>
+ </Border>
+ </Grid>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml
index 5b01eaa1b..96f9e1bf0 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/Views/DiagnosticsView.xaml
@@ -10,7 +10,7 @@
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:DiagnosticsViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.DiagnosticsViewVM}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
<Grid Margin="20">
- <DockPanel>
+ <DockPanel x:Name="dock">
<Grid DockPanel.Dock="Top" Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
@@ -93,28 +93,34 @@
<Rectangle Grid.Column="2" VerticalAlignment="Bottom" StrokeThickness="2" Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" />
</Grid>
- <ItemsControl x:Name="tabControl" Margin="0 0 0 0" ItemsSource="{Binding Tabs}" BorderThickness="0" Background="Transparent">
- <ItemsControl.ItemsPanel>
- <ItemsPanelTemplate>
- <Grid/>
- </ItemsPanelTemplate>
- </ItemsControl.ItemsPanel>
- <ItemsControl.ItemContainerStyle>
- <Style TargetType="FrameworkElement">
- <Setter Property="Visibility" Value="Hidden"></Setter>
- <Style.Triggers>
- <DataTrigger Binding="{Binding IsSelected}" Value="True">
- <Setter Property="Visibility" Value="Visible"></Setter>
- </DataTrigger>
- </Style.Triggers>
- </Style>
- </ItemsControl.ItemContainerStyle>
- <ItemsControl.ItemTemplate>
- <DataTemplate>
- <local:DiagnosticsTabView />
- </DataTemplate>
- </ItemsControl.ItemTemplate>
- </ItemsControl>
+ <Grid x:Name="grid">
+ <Viewbox Stretch="Fill" Margin="0 0 0 0" VerticalAlignment="Top" Width="{Binding ElementName=grid,Path=ActualWidth}" Height="{Binding ElementName=grid,Path=ActualHeight}">
+ <ItemsControl x:Name="tabControl" Width="1810" Height="827" ItemsSource="{Binding Tabs}" BorderThickness="0" Background="Transparent">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <Grid/>
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemContainerStyle>
+ <Style TargetType="FrameworkElement">
+ <Setter Property="Visibility" Value="Hidden"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding IsSelected}" Value="True">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </ItemsControl.ItemContainerStyle>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <local:DiagnosticsTabView />
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </Viewbox>
+ </Grid>
</DockPanel>
+
+ <controls:IconButton HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 10 0 0" Cursor="Hand" ToolTip="Export diagnostics project" Icon="LightningBolt" Foreground="{StaticResource FSE_OrangeBrush}" Command="{Binding ExportProjectCommand}"></controls:IconButton>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.json b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.json
index 056761391..6baf6b4c2 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.json
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.json
@@ -81,7 +81,7 @@
],
"Widgets": [
{
- "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphWidget, Tango.FSE.Diagnostics",
+ "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph.RealTimeGraphWidget, Tango.FSE.Diagnostics",
"Monitor": "Dancer2Angle",
"Column": 0,
"Row": 0,
@@ -89,7 +89,7 @@
"RowSpan": 3
},
{
- "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphWidget, Tango.FSE.Diagnostics",
+ "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph.RealTimeGraphWidget, Tango.FSE.Diagnostics",
"Monitor": "Dancer2Angle",
"Column": 3,
"Row": 0,
@@ -97,7 +97,7 @@
"RowSpan": 3
},
{
- "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphWidget, Tango.FSE.Diagnostics",
+ "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph.RealTimeGraphWidget, Tango.FSE.Diagnostics",
"Monitor": "Dancer2Angle",
"Column": 6,
"Row": 0,
@@ -105,7 +105,7 @@
"RowSpan": 3
},
{
- "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphWidget, Tango.FSE.Diagnostics",
+ "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph.RealTimeGraphWidget, Tango.FSE.Diagnostics",
"Monitor": "Dancer2Angle",
"Column": 9,
"Row": 0,
@@ -113,13 +113,23 @@
"RowSpan": 3
},
{
- "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannelWidget, Tango.FSE.Diagnostics",
+ "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphMultiChannel.RealTimeGraphMultiChannelWidget, Tango.FSE.Diagnostics",
"Monitor": "DispensersMotorsFrequency",
"Column": 0,
"Row": 3,
"ColumnSpan": 3,
"RowSpan": 3
+ },
+ {
+ "$type": "Tango.FSE.Diagnostics.Project.Widgets.Monitor.MonitorWidget, Tango.FSE.Diagnostics",
+ "Monitor": "Dancer2Angle",
+ "Column": 0,
+ "Row": 6,
+ "ColumnSpan": 3,
+ "RowSpan": 2,
+ "Width": 50
}
+
]
},
{
@@ -202,7 +212,7 @@
],
"Widgets": [
{
- "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraphWidget, Tango.FSE.Diagnostics",
+ "$type": "Tango.FSE.Diagnostics.Project.Widgets.RealTimeGraph.RealTimeGraphWidget, Tango.FSE.Diagnostics",
"Monitor": "Dancer2Angle",
"Column": 2,
"Row": 2,
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/FileSystemViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/FileSystemViewVM.cs
index bb655d27b..6ad02cd49 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/FileSystemViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/FileSystemViewVM.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
+using Tango.BL.Enumerations;
using Tango.Core.Commands;
using Tango.FileSystem;
using Tango.FSE.Common;
@@ -160,7 +161,7 @@ namespace Tango.FSE.Firmware.ViewModels
private async void MachineProvider_MachineConnected(object sender, MachineConnectedEventArgs e)
{
- if (e.DifferentFromPrevious)
+ if (e.DifferentFromPrevious && e.MachineOperator.IsConnected && AuthenticationProvider.CurrentUser.HasPermission(Permissions.FSE_FirmwareFileSystemRead))
{
try
{
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml
index d3db0d70b..ff31c4d0e 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml
@@ -11,7 +11,7 @@
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:FileSystemViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.FileSystemViewVM}">
<Grid IsEnabled="{Binding IsFree}">
- <Grid IsEnabled="{Binding MachineProvider.IsPPCAvailable}">
+ <Grid IsEnabled="{Binding MachineProvider.IsConnected}">
<Grid Margin="0 20 0 0">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
index 3c740f103..af50e4e32 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj
@@ -105,7 +105,6 @@
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
- <Compile Include="Converters\DoubleToChartValuesConverter.cs" />
<Compile Include="Dialogs\MachineUpdateView.xaml.cs">
<DependentUpon>MachineUpdateView.xaml</DependentUpon>
</Compile>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml
index 7de5c805d..0af569096 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml
@@ -8,7 +8,6 @@
xmlns:global="clr-namespace:Tango.FSE.PPCConsole"
xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
xmlns:vm="clr-namespace:Tango.FSE.PPCConsole.ViewModels"
- xmlns:converters="clr-namespace:Tango.FSE.PPCConsole.Converters"
xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
xmlns:local="clr-namespace:Tango.FSE.PPCConsole.Views"
mc:Ignorable="d"
@@ -16,8 +15,6 @@
<UserControl.Resources>
- <converters:DoubleToChartValuesConverter x:Key="DoubleToChartValuesConverter" />
-
<Style x:Key="DynamicResolutionGraph" TargetType="graphs:RealTimeGraph" BasedOn="{StaticResource {x:Type graphs:RealTimeGraph}}">
<Setter Property="VerticalTicks" Value="11"></Setter>
<Style.Triggers>
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 247753801..b3a34c3b9 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
@@ -149,8 +149,8 @@
</Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Height="50">
- <controls:TextIconButton Icon="Stop" Padding="0 12" Width="200" Command="{Binding StopCommand}" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Grid.Column="1" Style="{StaticResource FSE_TextIconButton_Dark}">STOP</controls:TextIconButton>
- <controls:TextIconButton Icon="Play" Padding="0 12" Width="200" Command="{Binding StartCommand}" IsEnabled="{Binding RemoteDesktopProvider.CanStartSession}" Grid.Column="2" Margin="10 0 0 0" Height="Auto">START</controls:TextIconButton>
+ <controls:TextIconButton material:ButtonAssist.CornerRadius="25" Icon="Stop" Padding="0 12" Width="200" Command="{Binding StopCommand}" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Grid.Column="1" Style="{StaticResource FSE_TextIconButton_Dark}">STOP</controls:TextIconButton>
+ <controls:TextIconButton material:ButtonAssist.CornerRadius="25" Icon="Play" Padding="0 12" Width="200" Command="{Binding StartCommand}" IsEnabled="{Binding RemoteDesktopProvider.CanStartSession}" Grid.Column="2" Margin="10 0 0 0" Height="Auto">START</controls:TextIconButton>
</StackPanel>
</Grid>
<Grid>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs
index 97cf9a433..f6566765e 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs
@@ -10,7 +10,8 @@ namespace Tango.FSE.Stubs.Contracts
public interface ITestDesignerView : IFSEView
{
void FormatCode();
- void HighlightCode(int position, int length);
+ void HighlightCode(int position, int length, int line);
void InsertCode(String code);
+ void InvalidateHighlighting();
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectView.xaml
index 2289196e7..7bb2af7a7 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectView.xaml
@@ -57,5 +57,7 @@
</ListBox>
</Border>
</DockPanel>
+
+ <CheckBox IsChecked="{Binding ShowSuppressedProjects}" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="10 0 0 -55" Foreground="{StaticResource FSE_GrayBrush}" FontSize="{StaticResource FSE_SmallFontSize}">Show Suppressed Projects</CheckBox>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectViewVM.cs
index 5164e3262..c430c3f90 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/LoadPublishedProjectViewVM.cs
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Windows.Data;
using Tango.BL.Entities;
using Tango.FSE.Common;
@@ -10,6 +12,8 @@ namespace Tango.FSE.Stubs.Dialogs
{
public class LoadPublishedProjectViewVM : FSEDialogViewVM
{
+ private ICollectionView _projectsView;
+
public List<PublishedTestProject> PublishedTestProjects { get; set; }
private PublishedTestProject _selectedProject;
@@ -19,10 +23,32 @@ namespace Tango.FSE.Stubs.Dialogs
set { _selectedProject = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
}
+ private bool _showSuppressedProjects;
+ public bool ShowSuppressedProjects
+ {
+ get { return _showSuppressedProjects; }
+ set { _showSuppressedProjects = value; RaisePropertyChangedAuto(); _projectsView?.Refresh(); }
+ }
+
public LoadPublishedProjectViewVM(List<PublishedTestProject> projects)
{
OKText = "LOAD PROJECT";
PublishedTestProjects = projects;
+ _projectsView = CollectionViewSource.GetDefaultView(PublishedTestProjects);
+ _projectsView.Filter = (obj) =>
+ {
+ PublishedTestProject p = obj as PublishedTestProject;
+
+ if (p != null)
+ {
+ if (!ShowSuppressedProjects && !p.IsVisible)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ };
}
protected override bool CanOK()
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridView.xaml
new file mode 100644
index 000000000..0e7a1185b
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridView.xaml
@@ -0,0 +1,31 @@
+<UserControl x:Class="Tango.FSE.Stubs.Dialogs.ResultGridView"
+ 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.Stubs.Dialogs"
+ mc:Ignorable="d"
+ Width="1000" Height="600" d:DataContext="{d:DesignInstance Type=local:ResultGridViewVM, IsDesignTimeCreatable=False}" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
+ <Grid Margin="10">
+ <DockPanel>
+ <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
+ <material:PackIcon Kind="ViewGrid" Width="32" Height="32" />
+ <TextBlock Margin="10 0 0 0" FontSize="{StaticResource FSE_LargeFontSize}" VerticalAlignment="Center" Text="{Binding Result.Name}"></TextBlock>
+ </StackPanel>
+
+ <Border Margin="0 20 0 0" BorderThickness="1" BorderBrush="{StaticResource FSE_BorderBrush}" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" CornerRadius="5">
+ <DataGrid x:Name="grid"
+ CellStyle="{StaticResource FSE_DataGrid_Cell}"
+ Style="{StaticResource FSE_DataGrid}"
+ AutoGenerateColumns="False"
+ CanUserSortColumns="True"
+ CanUserReorderColumns="True"
+ CanUserResizeColumns="True"
+ CanUserResizeRows="True">
+
+ </DataGrid>
+ </Border>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridView.xaml.cs
new file mode 100644
index 000000000..ab908f94f
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridView.xaml.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+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.Stubs.Dialogs
+{
+ /// <summary>
+ /// Interaction logic for ResultGridView.xaml
+ /// </summary>
+ public partial class ResultGridView : UserControl
+ {
+ public class ResultObject
+ {
+ public Object V0 { get; set; }
+ public Object V1 { get; set; }
+ public Object V2 { get; set; }
+ public Object V3 { get; set; }
+ public Object V4 { get; set; }
+ public Object V5 { get; set; }
+ public Object V6 { get; set; }
+ public Object V7 { get; set; }
+ public Object V8 { get; set; }
+ public Object V9 { get; set; }
+ public Object V10 { get; set; }
+ public Object V11 { get; set; }
+ public Object V12 { get; set; }
+ public Object V13 { get; set; }
+ public Object V14 { get; set; }
+ }
+
+ public ResultGridView()
+ {
+ InitializeComponent();
+
+ Loaded += ResultGridView_Loaded;
+ }
+
+ private void ResultGridView_Loaded(object sender, RoutedEventArgs e)
+ {
+ var vm = DataContext as ResultGridViewVM;
+ var results = vm.Items;
+
+ List<ResultObject> objects = new List<ResultObject>();
+
+ if (results.Count > 0)
+ {
+ var model = results.First();
+
+ if (model.GetType().IsValueTypeOrString())
+ {
+ grid.Columns.Add(new DataGridTextColumn()
+ {
+ Header = "Values",
+ Binding = new Binding("V0"),
+ });
+
+ foreach (var item in results)
+ {
+ objects.Add(new ResultObject()
+ {
+ V0 = item,
+ });
+ }
+ }
+ else
+ {
+ int columnCount = 0;
+
+ //Generate columns
+ foreach (var prop in model.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
+ {
+ grid.Columns.Add(new DataGridTextColumn()
+ {
+ Header = prop.Name,
+ Binding = new Binding($"V{columnCount++}"),
+ });
+ }
+
+ foreach (var field in model.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
+ {
+ grid.Columns.Add(new DataGridTextColumn()
+ {
+ Header = field.Name,
+ Binding = new Binding($"V{columnCount++}"),
+ });
+ }
+
+ //Generate cells
+
+ foreach (var item in results)
+ {
+ ResultObject obj = new ResultObject();
+
+ var properties = model.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
+ var fields = model.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance).ToList();
+
+ int propCount = 0;
+
+ for (int i = 0; i < properties.Count; i++)
+ {
+ typeof(ResultObject).GetProperty($"V{i}").SetValue(obj, properties[i].GetValue(item));
+ propCount++;
+ }
+
+ for (int i = 0; i < fields.Count; i++)
+ {
+ typeof(ResultObject).GetProperty($"V{i + propCount}").SetValue(obj, fields[i].GetValue(item));
+ }
+
+ objects.Add(obj);
+ }
+ }
+ }
+
+ grid.ItemsSource = objects;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridViewVM.cs
new file mode 100644
index 000000000..b6e45c208
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ResultGridViewVM.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.FSE.Common;
+
+namespace Tango.FSE.Stubs.Dialogs
+{
+ public class ResultGridViewVM : FSEDialogViewVM
+ {
+ public Result Result { get; set; }
+
+ public List<Object> Items { get; set; }
+
+ public ResultGridViewVM(Result result) : base()
+ {
+ CanCancel = false;
+ OKText = "CLOSE";
+
+ Result = result;
+ Items = new List<object>();
+
+ foreach (var item in Result.Value as IEnumerable)
+ {
+ Items.Add(item);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Result.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Result.cs
index 813f31532..b75bf3c42 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Result.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Result.cs
@@ -14,7 +14,7 @@ namespace Tango.FSE.Stubs
public String Name { get; set; }
public Object Value { get; set; }
- internal bool IsValueArray
+ public bool IsValueArray
{
get { return Value != null && typeof(IEnumerable).IsAssignableFrom(Value.GetType()) && Value.GetType() != typeof(String); }
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Tango.FSE.Stubs.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Tango.FSE.Stubs.csproj
index 67bd5dfc8..61dedf949 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Tango.FSE.Stubs.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Tango.FSE.Stubs.csproj
@@ -110,6 +110,10 @@
<DependentUpon>LoadPublishedProjectView.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\LoadPublishedProjectViewVM.cs" />
+ <Compile Include="Dialogs\ResultGridView.xaml.cs">
+ <DependentUpon>ResultGridView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Dialogs\ResultGridViewVM.cs" />
<Compile Include="Dialogs\UserInputDialogView.xaml.cs">
<DependentUpon>UserInputDialogView.xaml</DependentUpon>
</Compile>
@@ -247,6 +251,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Dialogs\ResultGridView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Dialogs\UserInputDialogView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/MainViewVM.cs
index 02d2f8b53..49345e413 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/MainViewVM.cs
@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.BL.Enumerations;
using Tango.FSE.Common;
using Tango.FSE.Common.Navigation;
using Tango.FSE.Stubs.Views;
@@ -14,7 +15,7 @@ namespace Tango.FSE.Stubs.ViewModels
[NavigationContainer]
public class MainViewVM : FSEViewModel
{
- public override void OnApplicationStarted()
+ public override void OnApplicationReady()
{
InvokeUI(() =>
{
@@ -29,16 +30,19 @@ namespace Tango.FSE.Stubs.ViewModels
Image = ResourceHelper.GetImageFromResources("Images/test_runner.png"),
});
- NavigationManager.MenuItems.Add(new NavigationMenuItem(() =>
- {
- NavigationManager.NavigateTo<StubsModule>(nameof(TestDesignerView));
- })
+ if (AuthenticationProvider.CurrentUser.HasPermission(Permissions.FSE_RunTestDesigner))
{
- Name = "Test Designer",
- Index = 7,
- Description = "Create and test new test runner projects.",
- Image = ResourceHelper.GetImageFromResources("Images/test_designer.png"),
- });
+ NavigationManager.MenuItems.Add(new NavigationMenuItem(() =>
+ {
+ NavigationManager.NavigateTo<StubsModule>(nameof(TestDesignerView));
+ })
+ {
+ Name = "Test Designer",
+ Index = 7,
+ Description = "Create and test new test runner projects.",
+ Image = ResourceHelper.GetImageFromResources("Images/test_designer.png"),
+ });
+ }
});
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs
index cc5cdfdc7..8eb71490c 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs
@@ -13,6 +13,7 @@ using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using Tango.BL.Entities;
+using Tango.BL.Enumerations;
using Tango.Core;
using Tango.Core.Commands;
using Tango.Core.ExtensionMethods;
@@ -179,6 +180,7 @@ namespace Tango.FSE.Stubs.ViewModels
public RelayCommand TogglePublishPanelCommand { get; set; }
public RelayCommand<Script> RenameLibraryCommand { get; set; }
public RelayCommand<CreateItem> CreateItemCommand { get; set; }
+ public RelayCommand<Result> DisplayResultGridCommand { get; set; }
#endregion
@@ -217,12 +219,13 @@ namespace Tango.FSE.Stubs.ViewModels
AddLibraryCommand = new RelayCommand(AddNewLibrary);
ClearOutputCommand = new RelayCommand(Clear);
DeleteLibraryCommand = new RelayCommand<Script>(DeleteLibrary);
- PublishProjectCommand = new RelayCommand(PublishProject);
+ PublishProjectCommand = new RelayCommand(PublishProject,() => CurrentUser.HasPermission(Permissions.FSE_PublishTestProjects));
LoadPublishedProjectCommand = new RelayCommand(LoadPublishedProject);
UnPublishProjectCommand = new RelayCommand(UnPublishProject);
- TogglePublishPanelCommand = new RelayCommand(() => IsPublishPanelOpened = !IsPublishPanelOpened);
+ TogglePublishPanelCommand = new RelayCommand(() => IsPublishPanelOpened = !IsPublishPanelOpened, () => CurrentUser.HasPermission(Permissions.FSE_PublishTestProjects));
RenameLibraryCommand = new RelayCommand<Script>(RenameLibrary);
CreateItemCommand = new RelayCommand<CreateItem>(AutoCreateItem);
+ DisplayResultGridCommand = new RelayCommand<Result>(DisplayResultGrid);
}
#endregion
@@ -637,6 +640,8 @@ namespace Tango.FSE.Stubs.ViewModels
}
InvalidateRelayCommands();
+
+ View.InvalidateHighlighting();
}
private async void OpenProject()
@@ -932,7 +937,7 @@ namespace Tango.FSE.Stubs.ViewModels
if (errorScript != null)
{
OpenScript(errorScript);
- View.HighlightCode(error.Position, error.Length);
+ View.HighlightCode(error.Position, error.Length, error.Line);
}
}
@@ -943,6 +948,19 @@ namespace Tango.FSE.Stubs.ViewModels
#endregion
+ #region Results
+
+ private void DisplayResultGrid(Result result)
+ {
+ if (result != null)
+ {
+ ResultGridViewVM vm = new ResultGridViewVM(result);
+ NotificationProvider.ShowDialog(vm);
+ }
+ }
+
+ #endregion
+
#region INavigationObjectReceiver
public async void OnNavigatedToWithObject(NavigationObject obj)
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestRunnerViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestRunnerViewVM.cs
index 6e4ec2b74..54e3d0f6d 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestRunnerViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestRunnerViewVM.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Tango.BL.Entities;
using Tango.Core.Commands;
using Tango.FSE.Common;
+using Tango.FSE.Stubs.Dialogs;
using Tango.FSE.Stubs.Messages;
using Tango.FSE.Stubs.Views;
@@ -82,10 +83,18 @@ namespace Tango.FSE.Stubs.ViewModels
set { _failedError = value; RaisePropertyChangedAuto(); }
}
+ private bool _isRunning;
+ public bool IsRunning
+ {
+ get { return _isRunning; }
+ set { _isRunning = value; RaisePropertyChangedAuto(); }
+ }
+
public RelayCommand<PublishedTestProject> EditProjectCommand { get; set; }
public RelayCommand<PublishedTestProject> RunProjectCommand { get; set; }
public RelayCommand StartProjectCommand { get; set; }
public RelayCommand StopProjectCommand { get; set; }
+ public RelayCommand<Result> DisplayResultGridCommand { get; set; }
public TestRunnerViewVM()
{
@@ -93,6 +102,7 @@ namespace Tango.FSE.Stubs.ViewModels
RunProjectCommand = new RelayCommand<PublishedTestProject>(RunProject);
StartProjectCommand = new RelayCommand(StartProject, () => ProjectRunner != null && ProjectRunner.CanRun);
StopProjectCommand = new RelayCommand(StopProject, () => ProjectRunner != null && ProjectRunner.IsRunning);
+ DisplayResultGridCommand = new RelayCommand<Result>(DisplayResultGrid);
_requiresReloadingOfProjects = true;
RegisterForMessage<TestProjectPublishedOrSuppressed>((x) => _requiresReloadingOfProjects = true);
@@ -102,6 +112,7 @@ namespace Tango.FSE.Stubs.ViewModels
{
try
{
+ IsRunning = true;
FailedError = null;
Results = new List<Result>();
Status = "Running...";
@@ -119,6 +130,10 @@ namespace Tango.FSE.Stubs.ViewModels
Status = "Failed";
FailedError = ex.FlattenMessage();
}
+ finally
+ {
+ IsRunning = false;
+ }
}
private void StopProject()
@@ -187,7 +202,7 @@ namespace Tango.FSE.Stubs.ViewModels
public override Task<bool> OnNavigateBackRequest()
{
- if (SelectedView == RunnerView.TestRunnerExecutionView)
+ if (SelectedView == RunnerView.TestRunnerExecutionView && !IsRunning)
{
SelectedView = RunnerView.TestRunnerCatalogView;
return Task.FromResult(false);
@@ -210,5 +225,14 @@ namespace Tango.FSE.Stubs.ViewModels
{
//Do nothing
}
+
+ private void DisplayResultGrid(Result result)
+ {
+ if (result != null)
+ {
+ ResultGridViewVM vm = new ResultGridViewVM(result);
+ NotificationProvider.ShowDialog(vm);
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml
index 97f8cea6b..29251ca31 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml
@@ -219,7 +219,7 @@
<DockPanel>
<Grid DockPanel.Dock="Bottom">
<StackPanel VerticalAlignment="Top" Margin="10">
- <Button Margin="0 10 0 0" Height="50" Width="Auto" Foreground="{StaticResource FSE_GreenBrush}" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Command="{Binding PublishProjectCommand}">
+ <Button material:ButtonAssist.CornerRadius="25" Margin="0 10 0 0" Height="50" Width="Auto" Foreground="{StaticResource FSE_GreenBrush}" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Command="{Binding PublishProjectCommand}">
<DockPanel>
<material:PackIcon Kind="Publish" Height="20" Width="20" />
<TextBlock Margin="20 0 0 0" VerticalAlignment="Center" >PUBLISH</TextBlock>
@@ -585,7 +585,23 @@
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="NAME" Binding="{Binding Name}" />
- <DataGridTextColumn Header="VALUE" Binding="{Binding Value}" Width="1*" />
+ <DataGridTemplateColumn Header="VALUE" Width="1*">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <Grid>
+ <TextBlock Visibility="{Binding IsValueArray,Converter={StaticResource BooleanToVisibilityInverseConverter}}" Text="{Binding Value}"></TextBlock>
+ <StackPanel Orientation="Horizontal" Visibility="{Binding IsValueArray,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <TextBlock Foreground="{StaticResource FSE_GrayBrush}">
+ <Run>This test result contains</Run>
+ <Run Text="{Binding Value.Count,Mode=OneWay}"></Run>
+ <Run Text="Values."></Run>
+ </TextBlock>
+ <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.DisplayResultGridCommand}" CommandParameter="{Binding}" Height="22" Foreground="{StaticResource FSE_PrimaryAccentBrush}" Background="Transparent" BorderBrush="Transparent" Margin="0 -4 0 0">(Grid View)</Button>
+ </StackPanel>
+ </Grid>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs
index b91ede833..e310afc89 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs
@@ -49,14 +49,25 @@ namespace Tango.FSE.Stubs.Views
GetCurrentEditor()?.FormatCode();
}
- public void HighlightCode(int position, int length)
+ public void HighlightCode(int position, int length, int line)
{
- GetCurrentEditor()?.Highlight(position, length);
+ GetCurrentEditor()?.Highlight(position, length, line);
}
public void InsertCode(string code)
{
GetCurrentEditor()?.InsertCode(code);
}
+
+ public void InvalidateHighlighting()
+ {
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ foreach (var editor in tabControl.FindVisualChildren<ScriptEditor>())
+ {
+ editor.InvalidateHighlighting();
+ }
+ }));
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerCatalogView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerCatalogView.xaml
index 2af7253ae..f2671a169 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerCatalogView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerCatalogView.xaml
@@ -58,7 +58,7 @@
<Polygon Fill="{StaticResource FSE_PrimaryBackgroundLighterBrush}" Points="0,0 150,0 0,170"></Polygon>
<DockPanel>
<Border CornerRadius="0 0 5 5" Padding="8" BorderThickness="0 1 0 0" BorderBrush="{StaticResource FSE_BorderBrush}" DockPanel.Dock="Bottom" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" >
- <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RunProjectCommand}" CommandParameter="{Binding}" Height="30" Width="140" HorizontalContentAlignment="Stretch" HorizontalAlignment="Right" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="14" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RunProjectCommand}" CommandParameter="{Binding}" Height="30" Width="140" HorizontalContentAlignment="Stretch" HorizontalAlignment="Right" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
<DockPanel>
<material:PackIcon Kind="Play" Height="24" Width="24" Foreground="{StaticResource FSE_GreenBrush}" />
<TextBlock Margin="20 2 0 0" VerticalAlignment="Center">RUN</TextBlock>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerExecutionView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerExecutionView.xaml
index 53c0bff56..92f23e4b5 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerExecutionView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestRunnerExecutionView.xaml
@@ -6,6 +6,7 @@
xmlns:global="clr-namespace:Tango.FSE.Stubs"
xmlns:vm="clr-namespace:Tango.FSE.Stubs.ViewModels"
xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
xmlns:local="clr-namespace:Tango.FSE.Stubs.Views"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1280" d:DesignStyle="{StaticResource FSE_User_Control_Designer}" d:DataContext="{d:DesignInstance Type=vm:TestRunnerViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.TestRunnerViewVM}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
@@ -57,13 +58,13 @@
<StackPanel HorizontalAlignment="Left" Width="1050" Margin="0 20 0 0">
<DockPanel>
<Grid Margin="20 0 0 0" DockPanel.Dock="Right" >
- <Button Command="{Binding StartProjectCommand}" Visibility="{Binding ProjectRunner.IsRunning,Converter={StaticResource BooleanToVisibilityInverseConverter}}" IsEnabled="{Binding ProjectRunner.CanRun}" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Width="200" Height="50">
+ <Button material:ButtonAssist.CornerRadius="25" Command="{Binding StartProjectCommand}" Visibility="{Binding ProjectRunner.IsRunning,Converter={StaticResource BooleanToVisibilityInverseConverter}}" IsEnabled="{Binding ProjectRunner.CanRun}" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Width="200" Height="50">
<DockPanel>
<material:PackIcon Kind="Play" Foreground="{StaticResource FSE_GreenBrush}" Width="24" Height="24" />
<TextBlock Margin="10 0 0 0" VerticalAlignment="Center">START</TextBlock>
</DockPanel>
</Button>
- <Button Command="{Binding StopProjectCommand}" Visibility="{Binding ProjectRunner.IsRunning,Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Width="200" Height="50">
+ <Button material:ButtonAssist.CornerRadius="25" Command="{Binding StopProjectCommand}" Visibility="{Binding ProjectRunner.IsRunning,Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Width="200" Height="50">
<DockPanel>
<material:PackIcon Kind="Stop" Foreground="{StaticResource FSE_RedBrush}" Width="24" Height="24" />
<TextBlock Margin="10 0 0 0" VerticalAlignment="Center">STOP</TextBlock>
@@ -135,7 +136,18 @@
</material:PackIcon>
<StackPanel Margin="15 0 0 0" VerticalAlignment="Center">
<TextBlock Text="{Binding Name}" ></TextBlock>
- <TextBlock Margin="0 2 0 0" FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_GrayBrush}" Text="{Binding Value}"></TextBlock>
+ <Grid Margin="0 2 0 0">
+ <TextBlock Visibility="{Binding IsValueArray,Converter={StaticResource BooleanToVisibilityInverseConverter}}" FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_GrayBrush}" Text="{Binding Value}"></TextBlock>
+
+ <StackPanel Orientation="Horizontal" Visibility="{Binding IsValueArray,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <TextBlock FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_GrayBrush}">
+ <Run>This test result contains</Run>
+ <Run Text="{Binding Value.Count,Mode=OneWay}"></Run>
+ <Run Text="Values."></Run>
+ </TextBlock>
+ <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.DisplayResultGridCommand}" CommandParameter="{Binding}" Height="22" FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_PrimaryAccentBrush}" Background="Transparent" BorderBrush="Transparent" Margin="0 -4 0 0">(Grid View)</Button>
+ </StackPanel>
+ </Grid>
</StackPanel>
</DockPanel>
</DataTemplate>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Images/machine-update_gray.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Images/machine-update_gray.png
new file mode 100644
index 000000000..6e9bba9b3
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Images/machine-update_gray.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj
index afc7344f5..3c145d540 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Tango.FSE.Upgrade.csproj
@@ -238,6 +238,9 @@
<Resource Include="Images\flash_drive.png" />
<Resource Include="Images\upgrade_remotely.png" />
</ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\machine-update_gray.png" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets" Condition="Exists('..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs
index 7ea8d49d6..f1737463d 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs
@@ -95,6 +95,14 @@ namespace Tango.FSE.Upgrade.ViewModels
set { _isCompleted = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
}
+ private bool _suppressFirmwareUpgrade;
+ public bool SuppressFirmwareUpgrade
+ {
+ get { return _suppressFirmwareUpgrade; }
+ set { _suppressFirmwareUpgrade = value; RaisePropertyChangedAuto(); }
+ }
+
+
public RelayCommand StartUpgradeCommand { get; set; }
public RelayCommand SaveTupFileCommand { get; set; }
public RelayCommand SelectTupFileLocationCommand { get; set; }
@@ -170,7 +178,7 @@ namespace Tango.FSE.Upgrade.ViewModels
try
{
IsFree = false;
- Handler = await RemoteUpgradeManager.PerformRemoteApplicationUpgrade(TemporaryTupFile);
+ Handler = await RemoteUpgradeManager.PerformRemoteApplicationUpgrade(TemporaryTupFile, !SuppressFirmwareUpgrade);
await Handler.WaitForCompletion();
IsCompleted = true;
await MachineProvider.DisconnectAndWaitForReconnection(TimeSpan.FromSeconds(20), TimeSpan.FromMinutes(1));
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/MainViewVM.cs
index 2907d8d5c..b6986e660 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/MainViewVM.cs
@@ -12,6 +12,7 @@ using Tango.SharedUI.Helpers;
namespace Tango.FSE.Upgrade.ViewModels
{
+ [ModularNavigationContainer]
public class MainViewVM : RemoteUpgradeViewModel
{
public override void OnApplicationReady()
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml
index c65744fdc..3c775f3f3 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml
@@ -40,6 +40,8 @@
</DockPanel>
</RadioButton>
+ <CheckBox IsEnabled="{Binding ElementName=chkUpgradeNow,Path=IsChecked}" IsChecked="{Binding SuppressFirmwareUpgrade}" ToolTip="Performs an application upgrade while skipping the firmware upgrade" Background="{StaticResource FSE_WarningBrush}" Margin="105 -5 0 0" FontSize="{StaticResource FSE_SmallFontSize}">Suppress firmware upgrade</CheckBox>
+
<RadioButton x:Name="chkSaveToDisk" Margin="0 20 0 0" IsChecked="{Binding ElementName=chkUpgradeNow,Path=IsChecked,Converter={StaticResource BooleanInverseConverter},Mode=TwoWay}" VerticalContentAlignment="Center" Cursor="Hand" Padding="25 0 0 0">
<DockPanel>
<Image Source="../Images/flash_drive.png" Width="48" Height="48" />
@@ -61,13 +63,13 @@
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="1000">
<DockPanel>
<Grid DockPanel.Dock="Right" >
- <Button Visibility="{Binding ElementName=chkUpgradeNow,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding StartUpgradeCommand}" HorizontalAlignment="Right" Width="250" Height="50" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="25" Visibility="{Binding ElementName=chkUpgradeNow,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding StartUpgradeCommand}" HorizontalAlignment="Right" Width="250" Height="50">
<StackPanel Orientation="Horizontal">
<material:PackIcon Width="32" Height="28" Kind="ClockFast" />
<TextBlock Margin="10 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}">UPGRADE NOW</TextBlock>
</StackPanel>
</Button>
- <Button Command="{Binding SaveTupFileCommand}" Visibility="{Binding ElementName=chkSaveToDisk,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="250" Height="50" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="25" Command="{Binding SaveTupFileCommand}" Visibility="{Binding ElementName=chkSaveToDisk,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="250" Height="50">
<StackPanel Orientation="Horizontal">
<material:PackIcon Width="32" Height="28" Kind="ContentSaveEdit" />
<TextBlock Margin="10 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}">SAVE PACKAGE</TextBlock>
@@ -76,7 +78,7 @@
</Grid>
<StackPanel VerticalAlignment="Bottom" Margin="0 0 40 0">
- <TextBlock Text="{Binding Handler.Progress.Message}" Style="{StaticResource FSE_HandlerStatusTextBlock}"></TextBlock>
+ <TextBlock Text="{Binding Handler.Progress.Message}" ToolTip="{Binding Handler.Progress.Message}" TextTrimming="CharacterEllipsis" Style="{StaticResource FSE_HandlerStatusTextBlock}"></TextBlock>
<ProgressBar Margin="0 5 0 0" Minimum="0" Maximum="{Binding Handler.Progress.Maximum}" Value="{Binding Handler.Progress.Value}" IsIndeterminate="{Binding Handler.Progress.IsIndeterminate}"></ProgressBar>
</StackPanel>
</DockPanel>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeView.xaml
index 652bce48f..046259d75 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeView.xaml
@@ -76,15 +76,15 @@
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="1000">
<DockPanel>
- <Button Command="{Binding GeneratePackageCommand}" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="250" Height="50" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="25" Command="{Binding GeneratePackageCommand}" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="250" Height="50">
<StackPanel Orientation="Horizontal">
- <material:PackIcon Width="32" Height="28" Kind="ClockFast" />
+ <material:PackIcon Width="32" Height="28" Kind="PackageDown" />
<TextBlock Margin="10 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}">GENERATE PACKAGE</TextBlock>
</StackPanel>
</Button>
<StackPanel VerticalAlignment="Bottom" Margin="0 0 40 0">
- <TextBlock Text="{Binding Handler.Progress.Message}" Style="{StaticResource FSE_HandlerStatusTextBlock}"></TextBlock>
+ <TextBlock Text="{Binding Handler.Progress.Message}" ToolTip="{Binding Handler.Progress.Message}" TextTrimming="CharacterEllipsis" Style="{StaticResource FSE_HandlerStatusTextBlock}"></TextBlock>
<ProgressBar Margin="0 5 0 0" Minimum="0" Maximum="{Binding Handler.Progress.Maximum}" Value="{Binding Handler.Progress.Value}" IsIndeterminate="{Binding Handler.Progress.IsIndeterminate}"></ProgressBar>
</StackPanel>
</DockPanel>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml
index 6ee70f44c..a8739b347 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml
@@ -43,7 +43,7 @@
<DockPanel Margin="0 0 0 0">
<controls:IconButton ToolTip="Browse for .tfp file location" Margin="5 0 0 0" DockPanel.Dock="Right" Icon="FolderOpenOutline" Width="38" Height="38" Command="{Binding SelectTfpFileLocationCommand}" />
- <TextBox FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_PrimaryAccentBrush}" IsReadOnly="True" Text="{Binding TfpFileLocationToSave}" FlowDirection="RightToLeft" VerticalContentAlignment="Bottom"></TextBox>
+ <TextBox FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_PrimaryAccentBrush}" IsReadOnly="True" Text="{Binding TfpFileLocationToSave}" VerticalContentAlignment="Bottom"></TextBox>
</DockPanel>
</StackPanel>
</StackPanel>
@@ -52,13 +52,13 @@
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="1000">
<DockPanel>
<Grid DockPanel.Dock="Right" >
- <Button Visibility="{Binding ElementName=chkUpgradeNow,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding StartUpgradeCommand}" HorizontalAlignment="Right" Width="250" Height="50" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="25" Visibility="{Binding ElementName=chkUpgradeNow,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding StartUpgradeCommand}" HorizontalAlignment="Right" Width="250" Height="50">
<StackPanel Orientation="Horizontal">
<material:PackIcon Width="32" Height="28" Kind="ClockFast" />
<TextBlock Margin="10 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}">UPGRADE NOW</TextBlock>
</StackPanel>
</Button>
- <Button Command="{Binding SaveTfpFileCommand}" Visibility="{Binding ElementName=chkSaveToDisk,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="250" Height="50" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="25" Command="{Binding SaveTfpFileCommand}" Visibility="{Binding ElementName=chkSaveToDisk,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="250" Height="50">
<StackPanel Orientation="Horizontal">
<material:PackIcon Width="32" Height="28" Kind="ContentSaveEdit" />
<TextBlock Margin="10 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}">SAVE PACKAGE</TextBlock>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml
index 7da85e751..d105c5617 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml
@@ -81,14 +81,14 @@
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="1000">
<DockPanel>
<Grid DockPanel.Dock="Right" HorizontalAlignment="Right" >
- <Button Visibility="{Binding ElementName=chkDownload,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding GeneratePackageCommand}" Width="250" Height="50" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="25" Visibility="{Binding ElementName=chkDownload,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding GeneratePackageCommand}" Width="250" Height="50">
<StackPanel Orientation="Horizontal">
- <material:PackIcon Width="32" Height="28" Kind="ClockFast" />
+ <material:PackIcon Width="32" Height="28" Kind="PackageDown" />
<TextBlock Margin="10 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}" Text="GENERATE PACKAGE"/>
</StackPanel>
</Button>
- <Button Visibility="{Binding ElementName=chkExisting,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding ContinueCommand}" Width="250" Height="50" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="25" Visibility="{Binding ElementName=chkExisting,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding ContinueCommand}" Width="250" Height="50">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}">CONTINUE</TextBlock>
<material:PackIcon Margin="10 -5 0 0" Width="32" Height="28" Kind="ArrowRight" />
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/MainView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/MainView.xaml
index 57363eed8..26a3560c2 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/MainView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/MainView.xaml
@@ -22,7 +22,7 @@
</UserControl.Resources>
<Grid>
- <Image Source="../Images/machine-update2.png" HorizontalAlignment="Right" VerticalAlignment="Top" Stretch="Uniform" Width="800" Margin="80" Opacity="0.6" Visibility="{Binding ResolutionService.IsHighResolution,Converter={StaticResource BooleanToVisibilityConverter}}"></Image>
+ <Image Source="../Images/machine-update_gray.png" HorizontalAlignment="Right" VerticalAlignment="Top" Stretch="Uniform" Width="800" Margin="80" Opacity="0.1" Visibility="{Binding ResolutionService.IsHighResolution,Converter={StaticResource BooleanToVisibilityConverter}}"></Image>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
@@ -48,7 +48,7 @@
</Grid.Style>
<DockPanel>
<DockPanel DockPanel.Dock="Top">
- <Image Source="../Images/remote_upgrade_large.png" Stretch="Uniform" Width="90" RenderOptions.BitmapScalingMode="Fant" />
+ <Image Source="../Images/remote_upgrade_large.png" Stretch="Uniform" VerticalAlignment="Top" Width="60" RenderOptions.BitmapScalingMode="Fant" />
<StackPanel Margin="20 0 0 0">
<TextBlock FontSize="{StaticResource FSE_ModuleHeaderFontSize}" Foreground="{StaticResource FSE_PrimaryAccentBrush}">Remote Upgrade Wizard</TextBlock>
<TextBlock Margin="0 10 0 0" Foreground="{StaticResource FSE_GrayBrush}">
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/WelcomeView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/WelcomeView.xaml
index e82173419..83fa278ee 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/WelcomeView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/WelcomeView.xaml
@@ -44,7 +44,7 @@
</StackPanel>
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="1000">
- <Button Command="{Binding StartUpgradeCommand}" DockPanel.Dock="Right" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="200" Height="50" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">
+ <Button material:ButtonAssist.CornerRadius="25" Command="{Binding StartUpgradeCommand}" DockPanel.Dock="Right" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="250" Height="50">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" FontSize="{StaticResource FSE_LargeFontSize}">CONTINUE</TextBlock>
<material:PackIcon Margin="10 -5 0 0" Width="32" Height="28" Kind="ArrowRight" />
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/App.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/App.xaml
new file mode 100644
index 000000000..f85429b2a
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/App.xaml
@@ -0,0 +1,16 @@
+<Application x:Class="Tango.FSE.UsersAndRoles.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Application.Resources>
+ <ResourceDictionary>
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Converters.xaml" />
+ <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Colors.xaml" />
+ <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Fonts.xaml" />
+ <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Images.xaml" />
+ <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Styles.xaml" />
+ <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Controls.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+ </ResourceDictionary>
+ </Application.Resources>
+</Application> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Images/users_and_roles.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Images/users_and_roles.png
new file mode 100644
index 000000000..298dfbda2
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Images/users_and_roles.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Images/users_roles_back.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Images/users_roles_back.png
new file mode 100644
index 000000000..f008b6e08
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Images/users_roles_back.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Models/RoleModel.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Models/RoleModel.cs
new file mode 100644
index 000000000..266a5c090
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Models/RoleModel.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.Core;
+
+namespace Tango.FSE.UsersAndRoles.Models
+{
+ public class RoleModel : ExtendedObject
+ {
+ private Role _role;
+ public Role Role
+ {
+ get { return _role; }
+ set { _role = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isEnabled;
+ public bool IsEnabled
+ {
+ get { return _isEnabled; }
+ set { _isEnabled = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isSelected;
+ public bool IsSelected
+ {
+ get { return _isSelected; }
+ set { _isSelected = value; RaisePropertyChangedAuto(); }
+ }
+
+ public List<Roles> Dependencies { get; set; }
+
+ public RoleModel(Role role, params Roles[] dependencies)
+ {
+ Role = role;
+ IsEnabled = true;
+ Dependencies = new List<Roles>();
+
+ if (dependencies != null)
+ {
+ Dependencies.AddRange(dependencies);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Models/RolesCollection.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Models/RolesCollection.cs
new file mode 100644
index 000000000..b81a76d64
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Models/RolesCollection.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.UsersAndRoles.Models
+{
+ public class RolesCollection : Collection<RoleModel>
+ {
+ private bool _invalidating;
+
+ protected override void InsertItem(int index, RoleModel item)
+ {
+ base.InsertItem(index, item);
+ item.PropertyChanged += Item_PropertyChanged;
+ Invalidate();
+ }
+
+ private void Item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(RoleModel.IsSelected))
+ {
+ Invalidate();
+ }
+ }
+
+ private void Invalidate()
+ {
+ if (!_invalidating)
+ {
+ _invalidating = true;
+
+ foreach (var role in Items)
+ {
+ foreach (var dependencyRole in role.Dependencies)
+ {
+ var dependencyRoleModel = Items.SingleOrDefault(x => x.Role.Code == dependencyRole.ToInt32());
+
+ if (dependencyRoleModel != null)
+ {
+ if (role.IsSelected)
+ {
+ dependencyRoleModel.IsSelected = true;
+ dependencyRoleModel.IsEnabled = false;
+ }
+ else
+ {
+ dependencyRoleModel.IsEnabled = !Items.Any(x => x.IsSelected && x.Dependencies.Contains(dependencyRole));
+ }
+ }
+ }
+ }
+
+ _invalidating = false;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Navigation/UsersAndRolesNavigationManager.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Navigation/UsersAndRolesNavigationManager.cs
new file mode 100644
index 000000000..1a6fe03f4
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Navigation/UsersAndRolesNavigationManager.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.FSE.Common.Navigation;
+using Tango.FSE.UsersAndRoles.Navigation;
+using Tango.SharedUI.Controls;
+
+namespace Tango.FSE.UsersAndRoles.Navigation
+{
+ public class UsersAndRolesNavigationManager : ModularNavigationManager<UsersAndRolesView>
+ {
+ public UsersAndRolesNavigationManager(FrameworkElement navigationControlParent) : base(navigationControlParent)
+ {
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Navigation/UsersAndRolesView.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Navigation/UsersAndRolesView.cs
new file mode 100644
index 000000000..f015cbdb6
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Navigation/UsersAndRolesView.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.UsersAndRoles.Navigation
+{
+ public enum UsersAndRolesView
+ {
+ OrganizationSelectionView,
+ OrganizationUsersView,
+ UserDetailsView,
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/AssemblyInfo.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..5219b830b
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tango.FSE.UsersAndRoles")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Tango.FSE.UsersAndRoles")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>. For example, if you are using US english
+//in your source files, set the <UICulture> to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Resources.Designer.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..dde06bfd9
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Tango.FSE.UsersAndRoles.Properties
+{
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Tango.FSE.UsersAndRoles.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Resources.resx b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Resources.resx
new file mode 100644
index 000000000..af7dbebba
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Settings.Designer.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..f07016802
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Tango.FSE.UsersAndRoles.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Settings.settings b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Settings.settings
new file mode 100644
index 000000000..033d7a5e9
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Tango.FSE.UsersAndRoles.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Tango.FSE.UsersAndRoles.csproj
new file mode 100644
index 000000000..81a628011
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Tango.FSE.UsersAndRoles.csproj
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{D509DDAA-AA70-4B2A-8D6A-8C94F057A9C1}</ProjectGuid>
+ <OutputType>library</OutputType>
+ <RootNamespace>Tango.FSE.UsersAndRoles</RootNamespace>
+ <AssemblyName>Tango.FSE.UsersAndRoles</AssemblyName>
+ <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ <Deterministic>true</Deterministic>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\Build\FSE\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\Build\FSE\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="ControlzEx, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\ControlzEx.3.0.2.4\lib\net45\ControlzEx.dll</HintPath>
+ </Reference>
+ <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
+ </Reference>
+ <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
+ <Reference Include="MahApps.Metro, Version=1.6.5.1, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MahApps.Metro.1.6.5\lib\net46\MahApps.Metro.dll</HintPath>
+ </Reference>
+ <Reference Include="MaterialDesignColors, Version=1.2.2.920, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MaterialDesignColors.1.2.2\lib\net45\MaterialDesignColors.dll</HintPath>
+ </Reference>
+ <Reference Include="MaterialDesignThemes.Wpf, Version=3.0.1.920, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MaterialDesignThemes.3.0.1\lib\net45\MaterialDesignThemes.Wpf.dll</HintPath>
+ </Reference>
+ <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xaml">
+ <RequiredTargetFramework>4.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="WindowsBase" />
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Models\RoleModel.cs" />
+ <Compile Include="Models\RolesCollection.cs" />
+ <Compile Include="Navigation\UsersAndRolesNavigationManager.cs" />
+ <Compile Include="Navigation\UsersAndRolesView.cs" />
+ <Compile Include="UsersAndRolesViewModel.cs" />
+ <Compile Include="ViewModelLocator.cs" />
+ <Compile Include="UsersAndRolesModule.cs" />
+ <Compile Include="ViewModels\MainViewVM.cs" />
+ <Compile Include="ViewModels\OrganizationSelectionViewVM.cs" />
+ <Compile Include="ViewModels\OrganizationUsersViewVM.cs" />
+ <Compile Include="ViewModels\UserDetailsViewVM.cs" />
+ <Compile Include="Views\MainView.xaml.cs">
+ <DependentUpon>MainView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\OrganizationSelectionView.xaml.cs">
+ <DependentUpon>OrganizationSelectionView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\OrganizationUsersView.xaml.cs">
+ <DependentUpon>OrganizationUsersView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\UserDetailsView.xaml.cs">
+ <DependentUpon>UserDetailsView.xaml</DependentUpon>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <None Include="app.config" />
+ <None Include="packages.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj">
+ <Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project>
+ <Name>Tango.AutoComplete</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.BL\Tango.BL.csproj">
+ <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project>
+ <Name>Tango.BL</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Core\Tango.Core.csproj">
+ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
+ <Name>Tango.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Integration\Tango.Integration.csproj">
+ <Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project>
+ <Name>Tango.Integration</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Logging\Tango.Logging.csproj">
+ <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project>
+ <Name>Tango.Logging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.PMR\Tango.PMR.csproj">
+ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project>
+ <Name>Tango.PMR</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Settings\Tango.Settings.csproj">
+ <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project>
+ <Name>Tango.Settings</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.SharedUI\Tango.SharedUI.csproj">
+ <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project>
+ <Name>Tango.SharedUI</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Transport\Tango.Transport.csproj">
+ <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project>
+ <Name>Tango.Transport</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.FSE.BL\Tango.FSE.BL.csproj">
+ <Project>{834c81c3-09b5-45d7-be12-e7d1e6655a7c}</Project>
+ <Name>Tango.FSE.BL</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.FSE.Common\Tango.FSE.Common.csproj">
+ <Project>{bc37cccb-7392-4f78-8d1c-e9629e6e046e}</Project>
+ <Name>Tango.FSE.Common</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Views\MainView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\OrganizationSelectionView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\OrganizationUsersView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\UserDetailsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\users_and_roles.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\users_roles_back.png" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets" Condition="Exists('..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </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>
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/UsersAndRolesModule.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/UsersAndRolesModule.cs
new file mode 100644
index 000000000..099a36b21
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/UsersAndRolesModule.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media.Imaging;
+using Tango.BL.Enumerations;
+using Tango.FSE.Common;
+using Tango.FSE.UsersAndRoles.Views;
+
+namespace Tango.FSE.UsersAndRoles
+{
+ [FSEModule(index: 1)]
+ public class UsersAndRolesModule : FSEModuleBase
+ {
+ public override string Name { get; } = "Users & Roles";
+ public override string Description { get; } = "Users & Roles module";
+ public override Type MainViewType { get; } = typeof(MainView);
+ public override Permissions Permission { get; } = Permissions.FSE_RunFSE;
+
+ public override void Dispose()
+ {
+
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/UsersAndRolesViewModel.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/UsersAndRolesViewModel.cs
new file mode 100644
index 000000000..3c12d4dc7
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/UsersAndRolesViewModel.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.FSE.Common.Navigation;
+using Tango.FSE.UsersAndRoles.Navigation;
+
+namespace Tango.FSE.UsersAndRoles
+{
+ public class UsersAndRolesViewModel : ModularNavigationFSEViewModel<UsersAndRolesView>
+ {
+
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModelLocator.cs
new file mode 100644
index 000000000..7c98fb55b
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModelLocator.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.DI;
+using Tango.FSE.UsersAndRoles.Navigation;
+using Tango.FSE.UsersAndRoles.ViewModels;
+using Tango.FSE.UsersAndRoles.Views;
+
+namespace Tango.FSE.UsersAndRoles
+{
+ public static class ViewModelLocator
+ {
+ static ViewModelLocator()
+ {
+ TangoIOC.Default.Register<UsersAndRolesNavigationManager>(new UsersAndRolesNavigationManager(MainView.Instance));
+ TangoIOC.Default.Register<MainViewVM>();
+ TangoIOC.Default.Register<OrganizationSelectionViewVM>();
+ TangoIOC.Default.Register<OrganizationUsersViewVM>();
+ TangoIOC.Default.Register<UserDetailsViewVM>();
+ }
+
+ public static MainViewVM MainViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<MainViewVM>();
+ }
+ }
+
+ public static OrganizationSelectionViewVM OrganizationSelectionViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<OrganizationSelectionViewVM>();
+ }
+ }
+
+ public static OrganizationUsersViewVM OrganizationUsersViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<OrganizationUsersViewVM>();
+ }
+ }
+
+ public static UserDetailsViewVM UserDetailsViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<UserDetailsViewVM>();
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/MainViewVM.cs
new file mode 100644
index 000000000..fdc9c2000
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/MainViewVM.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+using Tango.FSE.Common;
+using Tango.FSE.Common.Navigation;
+using Tango.FSE.UsersAndRoles.Navigation;
+using Tango.SharedUI.Helpers;
+
+namespace Tango.FSE.UsersAndRoles.ViewModels
+{
+ [ModularNavigationContainer]
+ public class MainViewVM : UsersAndRolesViewModel
+ {
+ public override void OnApplicationReady()
+ {
+ if (CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_ManageOrganizationUsersAndRoles) || CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.FSE_ManageAllOrganizationsUsersAndRoles))
+ {
+ InvokeUI(() =>
+ {
+ NavigationManager.MenuItems.Add(new NavigationMenuItem(() =>
+ {
+ NavigationManager.NavigateTo<UsersAndRolesModule>();
+ })
+ {
+ Name = "Users & Roles",
+ Index = 10,
+ Description = "Manage users and their permissions on your organization",
+ Image = ResourceHelper.GetImageFromResources("Images/users_and_roles.png"),
+ });
+ });
+ }
+ }
+
+ public async override Task<bool> OnApplicationLogout()
+ {
+ while (ModularNavigationManager.CurrentView != UsersAndRolesView.OrganizationSelectionView)
+ {
+ if (!await ModularNavigationManager.NavigateBack())
+ {
+ return false;
+ }
+ }
+
+ return await base.OnApplicationLogout();
+ }
+
+ public async override Task<bool> OnNavigateBackRequest()
+ {
+ if (ModularNavigationManager.CurrentView == UsersAndRolesView.OrganizationSelectionView)
+ {
+ return await base.OnNavigateBackRequest();
+ }
+ else
+ {
+ await ModularNavigationManager.NavigateBack();
+ return false;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationSelectionViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationSelectionViewVM.cs
new file mode 100644
index 000000000..9a84cca7d
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationSelectionViewVM.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+using Tango.Core.Commands;
+using Tango.FSE.Common;
+using Tango.FSE.Common.AutoComplete;
+using Tango.FSE.UsersAndRoles.Navigation;
+using Tango.FSE.UsersAndRoles.Views;
+
+namespace Tango.FSE.UsersAndRoles.ViewModels
+{
+ public class OrganizationSelectionViewVM : UsersAndRolesViewModel
+ {
+ /// <summary>
+ /// Gets or sets the organizations completion source.
+ /// </summary>
+ public AutoCompleteSource<Organization> Organizations { get; set; }
+
+ private Organization _selectedOrganization;
+ /// <summary>
+ /// Gets or sets the selected organization.
+ /// </summary>
+ public Organization SelectedOrganization
+ {
+ get { return _selectedOrganization; }
+ set { _selectedOrganization = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
+ }
+
+ /// <summary>
+ /// Navigates to the organization users list with the specified organization.
+ /// </summary>
+ public RelayCommand ManageOrganizationCommand { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OrganizationSelectionViewVM"/> class.
+ /// </summary>
+ public OrganizationSelectionViewVM()
+ {
+ Organizations = new AutoCompleteSource<Organization>(AutoCompleteOrganizations);
+ ManageOrganizationCommand = new RelayCommand(ManageSelectedOrganization, () => SelectedOrganization != null);
+ }
+
+ private void ManageSelectedOrganization()
+ {
+ if (SelectedOrganization == null)
+ {
+ NotificationProvider.ShowError("No organization selected.");
+ return;
+ }
+
+ ModularNavigationManager.NavigateTo(UsersAndRolesView.OrganizationUsersView, new OrganizationUsersViewVM.NavigationObject()
+ {
+ Organization = SelectedOrganization
+ });
+ }
+
+ private List<Organization> AutoCompleteOrganizations(string key)
+ {
+ key = key ?? String.Empty;
+
+ try
+ {
+ return Services.OrganizationsService.GetCurrentUserOrganizations().Result.Where(x => x.Name.ToLower().StartsWith(key.ToLower())).Take(4).ToList();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error on auto complete organizations filter.");
+ return new List<Organization>();
+ }
+ }
+
+ public async override void OnNavigatedTo()
+ {
+ base.OnNavigatedTo();
+
+ if (SelectedOrganization == null)
+ {
+ await Task.Delay(200);
+ SelectedOrganization = AuthenticationProvider.CurrentUser.Organization;
+ }
+ }
+
+ public override Task<bool> OnApplicationLogout()
+ {
+ SelectedOrganization = null;
+ return base.OnApplicationLogout();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationUsersViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationUsersViewVM.cs
new file mode 100644
index 000000000..334c8c263
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/OrganizationUsersViewVM.cs
@@ -0,0 +1,230 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using Tango.BL.Entities;
+using Tango.Core.Commands;
+using Tango.FSE.Common;
+using Tango.FSE.Common.Navigation;
+using Tango.FSE.UsersAndRoles.Navigation;
+using Tango.FSE.UsersAndRoles.Views;
+using static Tango.FSE.UsersAndRoles.ViewModels.OrganizationUsersViewVM;
+
+namespace Tango.FSE.UsersAndRoles.ViewModels
+{
+ public class OrganizationUsersViewVM : UsersAndRolesViewModel, INavigationObjectReceiver<NavigationObject>
+ {
+ public class NavigationObject
+ {
+ public Organization Organization { get; set; }
+ public User SelectedUser { get; set; }
+ }
+
+ private bool _requiresReloading;
+ private User _initialUser;
+
+ private Organization _organization;
+ /// <summary>
+ /// Gets or sets the organization.
+ /// </summary>
+ public Organization Organization
+ {
+ get { return _organization; }
+ set { _organization = value; RaisePropertyChangedAuto(); }
+ }
+
+ private ObservableCollection<User> _users;
+ /// <summary>
+ /// Gets or sets the users.
+ /// </summary>
+ public ObservableCollection<User> Users
+ {
+ get { return _users; }
+ set { _users = value; RaisePropertyChangedAuto(); }
+ }
+
+ private User _selectedUser;
+ public User SelectedUser
+ {
+ get { return _selectedUser; }
+ set { _selectedUser = value; RaisePropertyChangedAuto(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the users view source.
+ /// </summary>
+ public ICollectionView UsersView { get; set; }
+
+ private String _filter;
+ /// <summary>
+ /// Gets or sets the users search filter.
+ /// </summary>
+ public String Filter
+ {
+ get { return _filter; }
+ set { _filter = value; RaisePropertyChangedAuto(); OnFilterChanged(); }
+ }
+
+ private bool _showDeleted;
+ public bool ShowDeleted
+ {
+ get { return _showDeleted; }
+ set { _showDeleted = value; RaisePropertyChangedAuto(); UsersView?.Refresh(); }
+ }
+
+ /// <summary>
+ /// Navigates to the user details view with the specified user.
+ /// </summary>
+ public RelayCommand<User> EditUserCommand { get; set; }
+
+ /// <summary>
+ /// Removes the specified user.
+ /// </summary>
+ public RelayCommand<User> RemoveUserCommand { get; set; }
+
+ /// <summary>
+ /// Adds a new user.
+ /// </summary>
+ public RelayCommand AddUserCommand { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OrganizationUsersViewVM"/> class.
+ /// </summary>
+ public OrganizationUsersViewVM()
+ {
+ Users = new ObservableCollection<User>();
+ EditUserCommand = new RelayCommand<User>(EditUser);
+ RemoveUserCommand = new RelayCommand<User>(SuspendUser);
+ AddUserCommand = new RelayCommand(AddUser, () => IsFree);
+ }
+
+ private void AddUser()
+ {
+ ModularNavigationManager.NavigateTo(UsersAndRolesView.UserDetailsView, new UserDetailsViewVM.NavigationObject()
+ {
+ IsNewUser = true,
+ Organization = Organization
+ });
+ }
+
+ private async void SuspendUser(User user)
+ {
+ if (await NotificationProvider.ShowWarningQuestion($"Are you sure you want to suspend '{user.Contact.FullName}' ?"))
+ {
+ try
+ {
+ IsFree = false;
+
+ using (NotificationProvider.PushTaskItem("Suspending account..."))
+ {
+ var updatedUser = await Services.OrganizationsService.SuspendUser(user);
+ Users.Replace(user, updatedUser);
+ }
+
+ await NotificationProvider.ShowSuccess("The selected user is now suspended and can be reactivated.");
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error suspending user '{user.Email}'.");
+ await NotificationProvider.ShowError($"Error suspending the selected user\n{ex.FlattenMessage()}");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ }
+
+ private void EditUser(User user)
+ {
+ ModularNavigationManager.NavigateTo(UsersAndRolesView.UserDetailsView, new UserDetailsViewVM.NavigationObject()
+ {
+ User = user
+ });
+ }
+
+ private async Task LoadUsers()
+ {
+ if (Organization != null)
+ {
+ try
+ {
+ IsFree = false;
+ var users = await Services.OrganizationsService.GetOrganizationUsers(Organization.Guid, true);
+ var usersCollection = new ObservableCollection<User>(users);
+ UsersView = CollectionViewSource.GetDefaultView(usersCollection);
+ UsersView.Filter = FilterUsers;
+ Users = usersCollection;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error loading organization users for organization '{Organization.Name}'.");
+ await NotificationProvider.ShowError($"Error loading the selected organization users.\n{ex.FlattenMessage()}");
+ await NavigationManager.NavigateBack();
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ else
+ {
+ await NotificationProvider.ShowError("No organization selected.");
+ }
+ }
+
+ private void OnFilterChanged()
+ {
+ UsersView?.Refresh();
+ }
+
+ private bool FilterUsers(object obj)
+ {
+ var user = obj as User;
+ String filter = Filter ?? String.Empty;
+
+ if (user != null)
+ {
+ return (!filter.IsNotNullOrEmpty() || user.Contact.FullName.ToLower().Contains(filter.ToLower()) || user.Email.ToLower().Contains(filter.ToLower())) && (!user.Deleted || ShowDeleted);
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Called when the navigation system has navigated to this VM view.
+ /// </summary>
+ public async override void OnNavigatedTo()
+ {
+ base.OnNavigatedTo();
+
+ if (_requiresReloading)
+ {
+ await LoadUsers();
+
+ if (_initialUser != null)
+ {
+ SelectedUser = Users.SingleOrDefault(x => x.Guid == _initialUser.Guid);
+ }
+ }
+
+ _requiresReloading = false;
+ _initialUser = null;
+ }
+
+ /// <summary>
+ /// Called when navigation system is going to navigate to this instance with the specified object.
+ /// </summary>
+ /// <param name="obj">The object.</param>
+ public void OnNavigatedToWithObject(NavigationObject obj)
+ {
+ Organization = obj.Organization;
+ _initialUser = obj.SelectedUser;
+ _requiresReloading = true;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/UserDetailsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/UserDetailsViewVM.cs
new file mode 100644
index 000000000..dec2651d1
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/ViewModels/UserDetailsViewVM.cs
@@ -0,0 +1,387 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.Core.Commands;
+using Tango.FSE.Common;
+using Tango.FSE.Common.Navigation;
+using Tango.FSE.UsersAndRoles.Models;
+using Tango.FSE.UsersAndRoles.Navigation;
+using Tango.FSE.UsersAndRoles.Views;
+using Tango.SharedUI.Components;
+using static Tango.FSE.UsersAndRoles.ViewModels.UserDetailsViewVM;
+
+namespace Tango.FSE.UsersAndRoles.ViewModels
+{
+ public class UserDetailsViewVM : UsersAndRolesViewModel, INavigationObjectReceiver<NavigationObject>
+ {
+ private String userToLoadGuid;
+ private bool _requiresLoading;
+
+ public class NavigationObject
+ {
+ public Organization Organization { get; set; }
+ public User User { get; set; }
+ public bool IsNewUser { get; set; }
+ }
+
+ private Organization _organization;
+ public Organization Organization
+ {
+ get { return _organization; }
+ set { _organization = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isNewUser;
+ public bool IsNewUser
+ {
+ get { return _isNewUser; }
+ set { _isNewUser = value; RaisePropertyChangedAuto(); }
+ }
+
+ private User _user;
+ public User User
+ {
+ get { return _user; }
+ set { _user = value; RaisePropertyChangedAuto(); OnUserChanged(); }
+ }
+
+ private String _firstName;
+ [Required(ErrorMessage = "First name is required")]
+ public String FirstName
+ {
+ get { return _firstName; }
+ set { _firstName = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _lastName;
+ [Required(ErrorMessage = "Last name is required")]
+ public String LastName
+ {
+ get { return _lastName; }
+ set { _lastName = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _email;
+ [Required(ErrorMessage = "Email is required")]
+ [EmailAddress(ErrorMessage = "Please enter a valid email address")]
+ public String Email
+ {
+ get { return _email; }
+ set { _email = value; RaisePropertyChangedAuto(); OnEmailChanged(); }
+ }
+
+ private String _password;
+ public String Password
+ {
+ get { return _password; }
+ set { _password = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isCheckingEmail;
+ public bool IsCheckingEmail
+ {
+ get { return _isCheckingEmail; }
+ set { _isCheckingEmail = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isEmailTaken;
+ public bool IsEmailTaken
+ {
+ get { return _isEmailTaken; }
+ set { _isEmailTaken = value; RaisePropertyChangedAuto(); }
+ }
+
+ private RolesCollection _rolesCollection;
+ public RolesCollection RolesCollection
+ {
+ get { return _rolesCollection; }
+ set { _rolesCollection = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _sendInvitation;
+ public bool SendInvitation
+ {
+ get { return _sendInvitation; }
+ set { _sendInvitation = value; RaisePropertyChangedAuto(); }
+ }
+
+ public RelayCommand SaveCommand { get; set; }
+
+ public RelayCommand GeneratePasswordCommand { get; set; }
+
+ public UserDetailsViewVM()
+ {
+ SaveCommand = new RelayCommand(Save, () => IsFree);
+ GeneratePasswordCommand = new RelayCommand(GeneratePassword);
+ SendInvitation = true;
+ }
+
+ private void GeneratePassword()
+ {
+ if (IsNewUser)
+ {
+ Password = Services.OrganizationsService.GenerateRandomPassword();
+ }
+ }
+
+ public async override void OnNavigatedTo()
+ {
+ base.OnNavigatedTo();
+
+ if (!IsNewUser)
+ {
+ if (_requiresLoading)
+ {
+ await LoadUserDetails();
+ }
+ }
+ else
+ {
+ await CreateNewUser();
+ GeneratePassword();
+ }
+
+ _requiresLoading = false;
+ }
+
+ private async Task CreateNewUser()
+ {
+ try
+ {
+ IsFree = false;
+
+ var user = new User();
+ user.Address = new Address();
+ user.Contact = new Contact();
+
+ User = user;
+
+ var roles = await Services.OrganizationsService.GetAllRoles();
+ InitRolesCollection(User, roles, true);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error initializing new user creation.");
+ await NotificationProvider.ShowError($"Error initializing new user details.\n{ex.FlattenMessage()}");
+ await NavigationManager.NavigateBack();
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+
+ private void InitRolesCollection(User user, List<Role> roles, bool isNew = false)
+ {
+ bool user_is_current_user_and_fse_admin_and_not_twine_admin = user.Guid == CurrentUser.Guid && user.HasRole(Roles.FSEAdministrator) && !user.HasRole(Roles.FSETwineAdministrator);
+
+ var collection = new RolesCollection();
+ collection.Add(new RoleModel(roles.SingleOrDefault(x => x.RoleEnum == Roles.FSETechnician)) { IsSelected = isNew });
+ collection.Add(new RoleModel(roles.SingleOrDefault(x => x.RoleEnum == Roles.FSEAdvancedTechnician), Roles.FSETechnician));
+ collection.Add(new RoleModel(roles.SingleOrDefault(x => x.RoleEnum == Roles.FSEAdministrator), Roles.FSETechnician, Roles.FSEAdvancedTechnician) { IsEnabled = !user_is_current_user_and_fse_admin_and_not_twine_admin });
+
+ if (CurrentUser.HasRole(Roles.FSETwineAdministrator))
+ {
+ collection.Add(new RoleModel(roles.SingleOrDefault(x => x.RoleEnum == Roles.FSETwineTechnician), Roles.FSETechnician, Roles.FSEAdvancedTechnician));
+ collection.Add(new RoleModel(roles.SingleOrDefault(x => x.RoleEnum == Roles.FSETwineAdministrator), Roles.FSETechnician, Roles.FSEAdministrator));
+ collection.Add(new RoleModel(roles.SingleOrDefault(x => x.RoleEnum == Roles.FSETwineTestDesigner), Roles.FSETechnician));
+ collection.Add(new RoleModel(roles.SingleOrDefault(x => x.RoleEnum == Roles.FSETwineTestPublisher), Roles.FSETechnician, Roles.FSETwineTestDesigner));
+ collection.Add(new RoleModel(roles.SingleOrDefault(x => x.RoleEnum == Roles.FSETwineDeveloper), Roles.FSETechnician));
+ }
+
+ collection.ToList().ForEach(x => x.IsSelected = user.FSERoles.Any(y => y.Code == x.Role.Code));
+
+ RolesCollection = collection;
+ }
+
+ private async Task LoadUserDetails()
+ {
+ try
+ {
+ IsFree = false;
+
+ User = await Services.OrganizationsService.GetUserDetails(userToLoadGuid);
+ var roles = await Services.OrganizationsService.GetAllRoles();
+
+ InitRolesCollection(User, roles);
+
+ Validate();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error loading user details for user '{userToLoadGuid}'");
+ await NotificationProvider.ShowError($"Error loading the selected user details.\n{ex.FlattenMessage()}");
+ await NavigationManager.NavigateBack();
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+
+ private async void Save()
+ {
+ try
+ {
+ if (!Validate()) return;
+
+ IsFree = false;
+
+ using (var task = NotificationProvider.PushTaskItem("Saving user details..."))
+ {
+ var rolesToAdd = RolesCollection.Where(x => x.IsSelected).ToList().Where(x => !User.FSERoles.Exists(y => y.Guid == x.Role.Guid)).ToList();
+ var rolesToRemove = User.FSERoles.ToList().Where(x => !RolesCollection.Where(z => z.IsSelected).ToList().Exists(y => y.Role.Guid == x.Guid)).ToList();
+
+ foreach (var role in rolesToAdd.Select(x => x.Role))
+ {
+ User.UsersRoles.Add(new UsersRole()
+ {
+ UserGuid = User.Guid,
+ RoleGuid = role.Guid,
+ Role = role,
+ User = User,
+ });
+ }
+
+ foreach (var role in rolesToRemove)
+ {
+ var userRole = User.UsersRoles.SingleOrDefault(x => x.RoleGuid == role.Guid);
+ if (userRole != null)
+ {
+ User.UsersRoles.Remove(userRole);
+ }
+ }
+
+ User.Contact.FirstName = FirstName;
+ User.Contact.LastName = LastName;
+
+ if (!IsNewUser)
+ {
+ await Services.OrganizationsService.UpdateUser(User);
+ }
+ else
+ {
+ User.OrganizationGuid = Organization.Guid;
+ User.Email = Email;
+ User.Password = Password;
+
+ await Services.OrganizationsService.InsertUser(User);
+
+ if (SendInvitation)
+ {
+ bool invitationSent = false;
+ task.UpdateProgress("Sending email invitation...");
+
+ while (!invitationSent)
+ {
+ try
+ {
+ await Services.OrganizationsService.SendNewUserInvitationEmail(User.Guid, Password);
+ invitationSent = true;
+ }
+ catch (Exception ex)
+ {
+ if (!await NotificationProvider.ShowWarningQuestion($"The user was created but an error occurred while trying to send the invitation via email.{ex.Message}\nWould you like to try again?"))
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ await NotificationProvider.ShowSuccess("User created successfully!");
+
+ IsNewUser = false;
+ Password = null;
+ userToLoadGuid = User.Guid;
+ }
+
+ await LoadUserDetails();
+
+ await ModularNavigationManager.NavigateTo(UsersAndRolesView.OrganizationUsersView, new OrganizationUsersViewVM.NavigationObject()
+ {
+ Organization = User.Organization,
+ SelectedUser = User
+ }, false);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error saving user details for '{User.Email}'.");
+ await NotificationProvider.ShowError($"Error saving user details.\n{ex.FlattenMessage()}");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+
+ private void OnUserChanged()
+ {
+ if (User != null)
+ {
+ FirstName = User.Contact.FirstName;
+ LastName = User.Contact.LastName;
+ IsEmailTaken = false;
+ Email = User.Email;
+ }
+ else
+ {
+ FirstName = null;
+ LastName = null;
+ Email = null;
+ Password = null;
+ }
+ }
+
+ private async void OnEmailChanged()
+ {
+ if (IsNewUser && Email.IsNotNullOrEmpty())
+ {
+ try
+ {
+ IsCheckingEmail = true;
+ await Task.Delay(500);
+ IsEmailTaken = !await Services.OrganizationsService.CheckEmailAvailable(Email);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error checking for email availability.");
+ IsEmailTaken = false;
+ }
+ finally
+ {
+ IsCheckingEmail = false;
+ }
+ }
+ }
+
+ protected override void OnValidating()
+ {
+ base.OnValidating();
+
+ if (IsEmailTaken)
+ {
+ InsertError(nameof(Email), "Email address is already registered.");
+ }
+ }
+
+ public void OnNavigatedToWithObject(NavigationObject obj)
+ {
+ User = null;
+ IsNewUser = obj.IsNewUser;
+ Organization = obj.Organization;
+
+ if (!IsNewUser)
+ {
+ userToLoadGuid = obj.User.Guid;
+ _requiresLoading = true;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/MainView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/MainView.xaml
new file mode 100644
index 000000000..8e7db0116
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/MainView.xaml
@@ -0,0 +1,21 @@
+<UserControl x:Class="Tango.FSE.UsersAndRoles.Views.MainView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:global="clr-namespace:Tango.FSE.UsersAndRoles"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
+ xmlns:vm="clr-namespace:Tango.FSE.UsersAndRoles.ViewModels"
+ xmlns:local="clr-namespace:Tango.FSE.UsersAndRoles.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}" Background="{StaticResource FSE_PrimaryBackgroundBrush}">
+ <Grid>
+ <Image Source="../Images/users_roles_back.png" HorizontalAlignment="Right" VerticalAlignment="Bottom" Stretch="None" Opacity="0.05" />
+
+ <controls:NavigationControl TransitionType="Slide" TransitionDuration="00:00:0.2">
+ <local:OrganizationSelectionView/>
+ <local:OrganizationUsersView/>
+ <local:UserDetailsView/>
+ </controls:NavigationControl>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/MainView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/MainView.xaml.cs
new file mode 100644
index 000000000..b8c6f7b66
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/MainView.xaml.cs
@@ -0,0 +1,31 @@
+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.UsersAndRoles.Views
+{
+ /// <summary>
+ /// Interaction logic for MainView.xaml
+ /// </summary>
+ public partial class MainView : UserControl
+ {
+ public static MainView Instance { get; set; }
+
+ public MainView()
+ {
+ Instance = this;
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationSelectionView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationSelectionView.xaml
new file mode 100644
index 000000000..c57ea0ba5
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationSelectionView.xaml
@@ -0,0 +1,57 @@
+<UserControl x:Class="Tango.FSE.UsersAndRoles.Views.OrganizationSelectionView"
+ 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:global="clr-namespace:Tango.FSE.UsersAndRoles"
+ xmlns:vm="clr-namespace:Tango.FSE.UsersAndRoles.ViewModels"
+ xmlns:local="clr-namespace:Tango.FSE.UsersAndRoles.Views"
+ xmlns:autoComplete="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:OrganizationSelectionViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.OrganizationSelectionViewVM}" d:DesignStyle="{StaticResource FSE_User_Control_Designer}">
+ <Grid>
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+
+ <TextBlock HorizontalAlignment="Center" FontSize="{StaticResource FSE_ModuleHeaderFontSize}">Users &amp; Roles</TextBlock>
+ <TextBlock TextWrapping="Wrap" Margin="0 20 0 0" TextAlignment="Center" LineHeight="25">
+ <Run>As an organization administrator you will be able to manage/create organization users and assigned them appropriate roles.</Run>
+ </TextBlock>
+
+ <StackPanel Margin="0 40 0 0" Width="500" HorizontalAlignment="Center">
+ <Image Source="../Images/users_and_roles.png" Stretch="None" />
+
+ <TextBlock Margin="60" HorizontalAlignment="Center" FontWeight="SemiBold" Foreground="{StaticResource FSE_PrimaryAccentBrush}" FontSize="{StaticResource FSE_LargerFontSize}">Select Organization</TextBlock>
+ <autoComplete:AutoCompleteTextBox material:HintAssist.Hint="Name" MaxPopupHeight="300" Margin="0 5 0 0" Provider="{Binding Organizations}" SelectedItem="{Binding SelectedOrganization,Mode=TwoWay}" DisplayMember="Name">
+ <autoComplete:AutoCompleteTextBox.SelectedItemTemplate>
+ <DataTemplate>
+ <DockPanel VerticalAlignment="Center">
+ <material:PackIcon Kind="Company" Width="24" Height="24" />
+ <StackPanel VerticalAlignment="Center" Margin="10 0 0 0" Orientation="Horizontal">
+ <TextBlock Text="{Binding Name}" FontSize="{StaticResource FSE_LargerFontSize}"></TextBlock>
+ </StackPanel>
+ </DockPanel>
+ </DataTemplate>
+ </autoComplete:AutoCompleteTextBox.SelectedItemTemplate>
+ <autoComplete:AutoCompleteTextBox.ItemTemplate>
+ <DataTemplate>
+ <DockPanel VerticalAlignment="Center">
+ <material:PackIcon Kind="Company" Width="32" Height="32" />
+ <StackPanel Margin="5 0 0 0" VerticalAlignment="Center">
+ <TextBlock Text="{Binding Name}" FontSize="{StaticResource FSE_LargerFontSize}"></TextBlock>
+ </StackPanel>
+ </DockPanel>
+ </DataTemplate>
+ </autoComplete:AutoCompleteTextBox.ItemTemplate>
+ </autoComplete:AutoCompleteTextBox>
+
+ <Button material:ButtonAssist.CornerRadius="25" Command="{Binding ManageOrganizationCommand}" Margin="0 100 0 0" Height="50" Width="250">
+ <DockPanel>
+ <TextBlock>CONTINUE</TextBlock>
+ <material:PackIcon Margin="10 0 0 0" VerticalAlignment="Center" Kind="ArrowRight" />
+ </DockPanel>
+ </Button>
+ </StackPanel>
+ </StackPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationSelectionView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationSelectionView.xaml.cs
new file mode 100644
index 000000000..904700c9c
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationSelectionView.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.UsersAndRoles.Views
+{
+ /// <summary>
+ /// Interaction logic for OrganizationSelectionView.xaml
+ /// </summary>
+ public partial class OrganizationSelectionView : UserControl
+ {
+ public OrganizationSelectionView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationUsersView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationUsersView.xaml
new file mode 100644
index 000000000..547243944
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationUsersView.xaml
@@ -0,0 +1,140 @@
+<UserControl x:Class="Tango.FSE.UsersAndRoles.Views.OrganizationUsersView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:global="clr-namespace:Tango.FSE.UsersAndRoles"
+ xmlns:helpers="clr-namespace:Tango.SharedUI.Helpers;assembly=Tango.SharedUI"
+ xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
+ xmlns:vm="clr-namespace:Tango.FSE.UsersAndRoles.ViewModels"
+ xmlns:local="clr-namespace:Tango.FSE.UsersAndRoles.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:OrganizationUsersViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.OrganizationUsersViewVM}" d:DesignStyle="{StaticResource FSE_User_Control_Designer}">
+ <Grid Margin="40" IsEnabled="{Binding IsFree}">
+ <DockPanel>
+ <DockPanel DockPanel.Dock="Top" HorizontalAlignment="Left">
+ <Image Source="../Images/users_and_roles.png" Stretch="Uniform" Width="48" RenderOptions.BitmapScalingMode="Fant" />
+ <TextBlock Margin="20 0 0 0" FontSize="{StaticResource FSE_ModuleHeaderFontSize}" VerticalAlignment="Center">
+ <Run Text="{Binding Organization.Name}"></Run>
+ <Run>Users</Run>
+ </TextBlock>
+ </DockPanel>
+
+ <Grid Margin="0 40 0 0">
+ <DockPanel>
+ <Grid DockPanel.Dock="Top" Panel.ZIndex="100">
+ <!--TOP BAR-->
+
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 0 20 -45">
+ <DockPanel Margin="0 0 20 0" VerticalAlignment="Center">
+ <material:PackIcon Kind="Search" Foreground="{StaticResource FSE_PrimaryAccentBrush}" VerticalAlignment="Center" Width="24" Height="24" Margin="0 0 5 0" />
+ <TextBox material:HintAssist.Hint="Search" Text="{Binding Filter,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Delay=500}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" Width="300" Style="{StaticResource FSE_Rounded_Corners_TextBox}" Height="33"></TextBox>
+ </DockPanel>
+ <controls:ToggleIconButton IsChecked="{Binding ShowDeleted}" Width="24" Height="24" Cursor="Hand" UncheckedForeground="{StaticResource FSE_GrayBrush}" CheckedForeground="{StaticResource FSE_RedBrush}" ToolTip="Show suspended accounts" Margin="0 0 20 0" UncheckedIcon="EyeOutline" CheckedIcon="EyeCheckOutline"></controls:ToggleIconButton>
+ <controls:TextIconButton material:ButtonAssist.CornerRadius="15" Command="{Binding AddUserCommand}" Icon="Add" Width="150">ADD USER</controls:TextIconButton>
+ </StackPanel>
+ </Grid>
+
+ <Grid>
+ <Border Background="#8B202020" Padding="0 0 0 5" CornerRadius="5">
+ <Grid>
+ <Border VerticalAlignment="Top" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Height="47" CornerRadius="5 5 0 0">
+
+ </Border>
+ <DataGrid RowHeight="60" CanUserSortColumns="True" Style="{StaticResource FSE_DataGrid}" CellStyle="{StaticResource FSE_DataGrid_Cell}" ItemsSource="{Binding Users}" SelectedItem="{Binding SelectedUser}" helpers:DataGridHelper.DoubleClickCommand="{Binding EditUserCommand}">
+ <DataGrid.Columns>
+ <DataGridTemplateColumn Width="60">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <material:PackIcon Kind="User" VerticalAlignment="Center" Width="32" Height="32" />
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+
+ <DataGridTemplateColumn Header="NAME" SortMemberPath="Contact.FullName" Width="120">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <TextBlock VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Text="{Binding Contact.FullName}"></TextBlock>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+
+ <DataGridTemplateColumn Header="EMAIL" SortMemberPath="Email" Width="210">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <TextBlock VerticalAlignment="Center" Text="{Binding Email}" TextTrimming="CharacterEllipsis"></TextBlock>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+
+ <DataGridTemplateColumn Header="LAST MODIFIED" SortMemberPath="LastUpdated">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <TextBlock VerticalAlignment="Center" Text="{Binding LastUpdated,Converter={StaticResource DateTimeUtcHumanizeConverter}}"></TextBlock>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+
+ <DataGridTemplateColumn Header="ROLES" Width="1*">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <ItemsControl ItemsSource="{Binding FSERoles}">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <StackPanel IsItemsHost="True" Orientation="Horizontal"></StackPanel>
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <TextBlock FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_GrayBrush}" Margin="0 0 5 0" VerticalAlignment="Center">
+ <Run Text="{Binding Description}"></Run>,
+ </TextBlock>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+
+ <DataGridTemplateColumn Width="180">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <UniformGrid Columns="3">
+ <controls:IconButton ToolTip="Edit user details" Cursor="Hand" Width="28" Height="28" Icon="Edit" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.EditUserCommand}" CommandParameter="{Binding}" />
+ <material:PackIcon Margin="20 0 0 0" Width="12" Height="12" VerticalAlignment="Center" Kind="Circle" >
+ <material:PackIcon.Style>
+ <Style TargetType="material:PackIcon">
+ <Setter Property="Foreground" Value="{StaticResource FSE_GreenBrush}"></Setter>
+ <Setter Property="ToolTip" Value="Activated"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Deleted}" Value="True">
+ <Setter Property="Foreground" Value="{StaticResource FSE_GrayBrush}"></Setter>
+ <Setter Property="ToolTip" Value="Suspended"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </material:PackIcon.Style>
+ </material:PackIcon>
+ <controls:IconButton ToolTip="Suspend account" Cursor="Hand" Width="28" Height="28" Icon="Close" Foreground="{StaticResource FSE_RedBrush}" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RemoveUserCommand}" CommandParameter="{Binding}" />
+ </UniformGrid>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ </DataGrid.Columns>
+ </DataGrid>
+ </Grid>
+ </Border>
+ </Grid>
+ </DockPanel>
+
+ <Grid Background="{StaticResource FSE_SemiTransparentBrush}" Visibility="{Binding IsBusy,Converter={StaticResource BooleanToVisibilityConverter},FallbackValue='Visible'}">
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+ <ProgressBar IsIndeterminate="{Binding IsBusy}" HorizontalAlignment="Center" Width="150" Height="150" Style="{StaticResource FSE_CircularProgressBar}"></ProgressBar>
+ <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0">Loading...</TextBlock>
+ </StackPanel>
+ </Grid>
+ </Grid>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationUsersView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationUsersView.xaml.cs
new file mode 100644
index 000000000..e3fc173d8
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/OrganizationUsersView.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.UsersAndRoles.Views
+{
+ /// <summary>
+ /// Interaction logic for OrganizationUsersView.xaml
+ /// </summary>
+ public partial class OrganizationUsersView : UserControl
+ {
+ public OrganizationUsersView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml
new file mode 100644
index 000000000..a2ad81cf4
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml
@@ -0,0 +1,166 @@
+<UserControl x:Class="Tango.FSE.UsersAndRoles.Views.UserDetailsView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:global="clr-namespace:Tango.FSE.UsersAndRoles"
+ xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:commonControls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
+ xmlns:vm="clr-namespace:Tango.FSE.UsersAndRoles.ViewModels"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
+ xmlns:local="clr-namespace:Tango.FSE.UsersAndRoles.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:UserDetailsViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.UserDetailsViewVM}">
+ <Grid Margin="40" IsEnabled="{Binding IsFree}">
+ <DockPanel>
+ <DockPanel DockPanel.Dock="Top" HorizontalAlignment="Left">
+ <material:PackIcon Height="48" Width="48" Kind="User" />
+ <TextBlock Margin="20 0 0 0" FontSize="{StaticResource FSE_ModuleHeaderFontSize}" VerticalAlignment="Center">
+ <Run Text="{Binding FirstName}"></Run>
+ <Run Text="{Binding LastName}"></Run>
+ </TextBlock>
+ </DockPanel>
+
+ <Grid Margin="0 40 0 0">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="700"/>
+ <ColumnDefinition Width="1*"/>
+ </Grid.ColumnDefinitions>
+ <ScrollViewer Grid.ColumnSpan="2" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" FocusVisualStyle="{x:Null}">
+ <StackPanel>
+ <Grid Width="700" HorizontalAlignment="Left">
+ <StackPanel>
+ <DockPanel>
+ <Border DockPanel.Dock="Top" Padding="10 5 5 5" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" CornerRadius="5 5 0 0">
+ <DockPanel >
+ <material:PackIcon VerticalAlignment="Top" Kind="UserCardDetailsOutline" Width="32" Height="32" />
+ <StackPanel Margin="10 0 0 0" VerticalAlignment="Center">
+ <TextBlock FontSize="{StaticResource FSE_LargerFontSize}">Details</TextBlock>
+ </StackPanel>
+ </DockPanel>
+ </Border>
+
+ <Grid>
+ <Border Background="#8E202020" CornerRadius="0 0 5 5" Padding="0 0 40 40">
+ <StackPanel Margin="40 40 0 0">
+ <StackPanel>
+
+ <UniformGrid Columns="2">
+ <DockPanel>
+ <Grid Panel.ZIndex="5" DockPanel.Dock="Right" Margin="-16 0 0 -6" Visibility="{Binding IsNewUser,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <Grid.Style>
+ <Style>
+ <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"></Setter>
+ </Style>
+ </Grid.Style>
+ <ProgressBar HorizontalAlignment="Left" VerticalAlignment="Center" IsIndeterminate="{Binding IsCheckingEmail}" Visibility="{Binding IsCheckingEmail,Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource FSE_CircularProgressBar}" Width="16" Height="16" />
+
+ <Grid Background="Transparent" Visibility="{Binding IsCheckingEmail,Converter={StaticResource BooleanToVisibilityInverseConverter}}">
+ <material:PackIcon Width="16" ToolTip="Email address is already registered" VerticalAlignment="Center" Kind="Exclamation" Foreground="{StaticResource FSE_ErrorBrush}" Visibility="{Binding IsEmailTaken,Converter={StaticResource BooleanToVisibilityConverter}}" />
+ <material:PackIcon VerticalAlignment="Center" Kind="Check" Foreground="{StaticResource FSE_SuccessBrush}" Visibility="{Binding IsEmailTaken,Converter={StaticResource BooleanToVisibilityInverseConverter}}" />
+ </Grid>
+ </Grid>
+ <TextBox material:HintAssist.IsFloating="True" material:HintAssist.Hint="Email" IsReadOnly="{Binding IsNewUser,Converter={StaticResource BooleanInverseConverter}}" Text="{Binding Email,UpdateSourceTrigger=PropertyChanged,Delay=500,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True}"></TextBox>
+ </DockPanel>
+ </UniformGrid>
+
+ <UniformGrid Columns="2" Margin="0 30 0 0" Visibility="{Binding IsNewUser,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <TextBox Margin="0 0 0 0" material:HintAssist.IsFloating="True" material:HintAssist.Hint="Password" IsReadOnly="True" Text="{Binding Password,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True}"></TextBox>
+
+ <Button Margin="20 0 0 0" HorizontalAlignment="Left" Width="120" Style="{StaticResource FSE_RaisedButton_Dark_Hover_Accent_Foreground}" Command="{Binding GeneratePasswordCommand}" >GENERATE</Button>
+ </UniformGrid>
+
+ <UniformGrid Columns="2" Margin="0 30 0 0">
+ <TextBox Margin="0 0 0 0" material:HintAssist.IsFloating="True" material:HintAssist.Hint="First Name" Text="{Binding FirstName,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True}"></TextBox>
+
+ <TextBox Margin="20 0 0 0" material:HintAssist.IsFloating="True" material:HintAssist.Hint="Last Name" Text="{Binding LastName,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True}"></TextBox>
+ </UniformGrid>
+
+ <UniformGrid Columns="2" Margin="0 30 0 0">
+ <TextBox material:HintAssist.IsFloating="True" material:HintAssist.Hint="Phone Number" Text="{Binding User.Contact.PhoneNumber}"></TextBox>
+ </UniformGrid>
+
+ <UniformGrid Columns="2" Margin="0 30 0 0">
+ <TextBox material:HintAssist.IsFloating="True" material:HintAssist.Hint="Fax" Text="{Binding User.Contact.Fax}"></TextBox>
+ </UniformGrid>
+ </StackPanel>
+ </StackPanel>
+ </Border>
+
+ <Grid Visibility="{Binding IsBusy,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+ <ProgressBar IsIndeterminate="{Binding IsBusy}" HorizontalAlignment="Center" Width="150" Height="150" Style="{StaticResource FSE_CircularProgressBar}"></ProgressBar>
+ <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0">Loading...</TextBlock>
+ </StackPanel>
+ </Grid>
+ </Grid>
+ </DockPanel>
+
+ <DockPanel Margin="0 40 0 0">
+ <Border DockPanel.Dock="Top" Padding="10 5 5 5" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" CornerRadius="5 5 0 0">
+ <DockPanel >
+ <material:PackIcon VerticalAlignment="Top" Kind="UserBadgeOutline" Width="32" Height="32" />
+ <StackPanel Margin="10 0 0 0" VerticalAlignment="Center">
+ <TextBlock FontSize="{StaticResource FSE_LargerFontSize}">Roles</TextBlock>
+ </StackPanel>
+ </DockPanel>
+ </Border>
+
+ <Border Background="#8E202020" CornerRadius="0 0 5 5" Padding="0 0 40 40">
+ <StackPanel Margin="40 40 0 0">
+ <StackPanel>
+ <ListBox ScrollViewer.CanContentScroll="False" ScrollViewer.VerticalScrollBarVisibility="Disabled" Style="{StaticResource FSE_BlankListBox}" ItemsSource="{Binding RolesCollection}">
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <CheckBox Margin="0 10 0 0" IsChecked="{Binding IsSelected}" IsEnabled="{Binding IsEnabled}" Content="{Binding Role.Description}"></CheckBox>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
+ </StackPanel>
+ </StackPanel>
+ </Border>
+ </DockPanel>
+ </StackPanel>
+
+ </Grid>
+ </StackPanel>
+ </ScrollViewer>
+
+ <StackPanel Margin="20 0 0 0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top" Width="380">
+ <DockPanel>
+ <Border DockPanel.Dock="Top" Padding="10 5 5 5" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" CornerRadius="5 5 0 0">
+ <DockPanel>
+ <material:PackIcon VerticalAlignment="Top" Kind="UserCheck" Width="32" Height="32" />
+ <StackPanel Margin="10 0 0 0" VerticalAlignment="Center">
+ <TextBlock FontSize="{StaticResource FSE_LargerFontSize}">Status</TextBlock>
+ </StackPanel>
+ </DockPanel>
+ </Border>
+
+ <Border Background="#8E202020" CornerRadius="0 0 5 5" Padding="0 0 40 40" IsEnabled="{Binding IsNewUser,Converter={StaticResource BooleanInverseConverter}}">
+ <StackPanel Margin="40 40 0 0">
+ <UniformGrid Columns="2">
+ <RadioButton x:Name="chkActive" IsChecked="{Binding User.Deleted,Converter={StaticResource BooleanInverseConverter},Mode=TwoWay}">Activated</RadioButton>
+ <RadioButton IsChecked="{Binding ElementName=chkActive,Path=IsChecked,Converter={StaticResource BooleanInverseConverter},Mode=TwoWay}">Suspended</RadioButton>
+ </UniformGrid>
+ </StackPanel>
+ </Border>
+ </DockPanel>
+
+ <DockPanel Margin="0 50 0 0" HorizontalAlignment="Center" Visibility="{Binding IsNewUser,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <CheckBox IsChecked="{Binding SendInvitation}" ToolTip="Send the new user invitation to login to this system with the initial password" Foreground="{StaticResource FSE_PrimaryAccentBrush}">Send invitation via email</CheckBox>
+ </DockPanel>
+
+ <Button Margin="0 60 0 0" material:ButtonAssist.CornerRadius="25" Width="250" Height="50" Padding="12" Command="{Binding SaveCommand}">
+ <DockPanel>
+ <material:PackIcon Kind="ContentSave"/>
+ <TextBlock Margin="10 0 0 0">SAVE</TextBlock>
+ </DockPanel>
+ </Button>
+ </StackPanel>
+ </Grid>
+ </Grid>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.xaml.cs
new file mode 100644
index 000000000..8b76c0229
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/Views/UserDetailsView.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.UsersAndRoles.Views
+{
+ /// <summary>
+ /// Interaction logic for UserDetailsView.xaml
+ /// </summary>
+ public partial class UserDetailsView : UserControl
+ {
+ public UserDetailsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/app.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/app.config
new file mode 100644
index 000000000..36bc04f85
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/app.config
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <configSections>
+ <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
+ <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+ </configSections>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-5.0.5.0" newVersion="5.0.5.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Data.Services.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+ <entityFramework>
+ <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
+ <providers>
+ <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+ </providers>
+ </entityFramework>
+</configuration> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/packages.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/packages.config
new file mode 100644
index 000000000..dd8c723e4
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.UsersAndRoles/packages.config
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="ControlzEx" version="3.0.2.4" targetFramework="net461" />
+ <package id="EntityFramework" version="6.2.0" targetFramework="net461" />
+ <package id="Google.Protobuf" version="3.4.1" targetFramework="net461" />
+ <package id="MahApps.Metro" version="1.6.5" targetFramework="net461" />
+ <package id="MaterialDesignColors" version="1.2.2" targetFramework="net461" />
+ <package id="MaterialDesignThemes" version="3.0.1" targetFramework="net461" />
+ <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" />
+</packages> \ No newline at end of file