diff options
Diffstat (limited to 'Software')
14 files changed, 174 insertions, 62 deletions
diff --git a/Software/Graphics/FSE/Modules/logout.png b/Software/Graphics/FSE/Modules/logout.png Binary files differnew file mode 100644 index 000000000..178c56365 --- /dev/null +++ b/Software/Graphics/FSE/Modules/logout.png diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Authentication/IAuthenticationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Authentication/IAuthenticationProvider.cs index e5a772c58..5a4945540 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Authentication/IAuthenticationProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Authentication/IAuthenticationProvider.cs @@ -26,7 +26,7 @@ namespace Tango.FSE.Common.Authentication /// <param name="password">The password.</param> /// <param name="environment">The environment.</param> /// <returns></returns> - Task<AuthenticationResult> Login(String email, String password, EnvironmentConfiguration environment); + Task<AuthenticationResult> Login(String email, String password, EnvironmentConfiguration environment, Action<String> onStatusChanged = null); /// <summary> /// Logs-out the current logged-in user. diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs index 0433a2d01..176a7eefa 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Authentication/DefaultAuthenticationProvider.cs @@ -73,12 +73,14 @@ namespace Tango.FSE.UI.Authentication /// <param name="password">The password.</param> /// <param name="environment">The environment.</param> /// <returns></returns> - public Task<AuthenticationResult> Login(String email, String password, EnvironmentConfiguration environment) + public Task<AuthenticationResult> Login(String email, String password, EnvironmentConfiguration environment, Action<String> onStatusChanged = null) { return Task.Factory.StartNew<AuthenticationResult>(() => { LogManager.Log($"Logging in user {email}..."); + onStatusChanged?.Invoke($"Logging in user {email}..."); + var settings = SettingsManager.Default.GetOrCreate<FSESettings>(); settings.MachineServiceAddress = environment.MachineServiceAddress; @@ -102,6 +104,8 @@ namespace Tango.FSE.UI.Authentication try { + onStatusChanged?.Invoke($"Contacting machine service on '{_webClient.Address}'..."); + response = _webClient.Login(new LoginRequest() { @@ -128,23 +132,34 @@ namespace Tango.FSE.UI.Authentication return new AuthenticationResult() { Response = response }; } + User user = null; + using (var db = ObservablesContext.CreateDefault()) { - CurrentUser = new UserBuilder(db).Set(x => x.Email.ToLower() == email.ToLower()) + user = new UserBuilder(db).Set(x => x.Email.ToLower() == email.ToLower()) .WithOrganization() .WithRolesAndPermissions() .Build(); } - if (CurrentUser != null) + if (user != null) { - LogManager.Log($"Current user is now: {CurrentUser.Contact.FullName}."); + LogManager.Log($"Current user is now: {user.Contact.FullName}."); } else { throw new AuthenticationException("Login failed for some strange reason."); } + onStatusChanged?.Invoke("Loading static collections..."); + + ObservablesStaticCollections.Instance.Initialize((msg) => + { + onStatusChanged?.Invoke(msg); + }); + + CurrentUser = user; + settings.Save(); CurrentUserChanged?.Invoke(this, CurrentUser); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs index 3f975d009..92f38ab25 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs @@ -229,12 +229,23 @@ namespace Tango.FSE.UI.FSEApplication LogManager.Log("Loading internal modules..."); foreach (var type in internalModules) { - var module = Activator.CreateInstance(type) as IFSEModule; - LogManager.Log("Loading module view " + module.Name + "..."); - FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement; - SharedUI.Controls.NavigationControl.SetNavigationName(view, module.Name); - Views.LayoutView.Instance.NavigationControl.Elements.Add(view); - _moduleLoader.AllModules.Add(module); + var module = _moduleLoader.AllModules.SingleOrDefault(m => m.GetType() == type); + + if (module == null) + { + module = Activator.CreateInstance(type) as IFSEModule; + LogManager.Log("Loading module view " + module.Name + "..."); + FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement; + SharedUI.Controls.NavigationControl.SetNavigationName(view, module.Name); + Views.LayoutView.Instance.NavigationControl.Elements.Add(view); + _moduleLoader.AllModules.Add(module); + } + else + { + _moduleLoader.UserModules.Remove(module); + } + + //TODO: add only if has permissions.. _moduleLoader.UserModules.Add(module); } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Images/logout.png b/Software/Visual_Studio/FSE/Tango.FSE.UI/Images/logout.png Binary files differnew file mode 100644 index 000000000..178c56365 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Images/logout.png diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Modules/DefaultFSEModuleLoader.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Modules/DefaultFSEModuleLoader.cs index 7c5c6ce39..59d7dcd04 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Modules/DefaultFSEModuleLoader.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Modules/DefaultFSEModuleLoader.cs @@ -52,10 +52,17 @@ namespace Tango.FSE.UI.Modules /// Handles the authentication provider user changed event. /// </summary> /// <param name="sender">The sender.</param> - /// <param name="e">The e.</param> - private void _authenticationProvider_CurrentUserChanged(object sender, User e) + /// <param name="user">The e.</param> + private void _authenticationProvider_CurrentUserChanged(object sender, User user) { - LoadModules(); + if (user != null) + { + LoadModules(); + } + else + { + UnloadModules(); + } } private ObservableCollection<IFSEModule> _allModules; @@ -133,6 +140,11 @@ namespace Tango.FSE.UI.Modules ModulesLoaded?.Invoke(this, new EventArgs()); } + private void UnloadModules() + { + UserModules.Clear(); + } + /// <summary> /// Gets the PPC module of type T if loaded. /// </summary> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs index d6315d685..c65465a3e 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs @@ -103,6 +103,8 @@ namespace Tango.FSE.UI.Navigation NavigateBackCommand = new RelayCommand(async () => await NavigateBack()); _dispatcherProvider = dispatcherProvider; + + _moduleLoader.ModulesLoaded += (x,e) => MenuItems.Clear(); } /// <summary> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index 284fa84b1..cc995d342 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -386,6 +386,9 @@ <Resource Include="Images\Menu\account.png" /> <Resource Include="Images\Menu\settings.png" /> </ItemGroup> + <ItemGroup> + <Resource Include="Images\logout.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/Tango.FSE.UI/ViewModels/InternalModuleViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/InternalModuleViewVM.cs index 3a8a3c940..d682cf178 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/InternalModuleViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/InternalModuleViewVM.cs @@ -12,29 +12,32 @@ namespace Tango.FSE.UI.ViewModels { public class InternalModuleViewVM : FSEViewModel { - public override void OnApplicationStarted() + public override void OnApplicationReady() { - NavigationManager.MenuItems.Add(new NavigationMenuItem(() => + if (AuthenticationProvider.CurrentUser.HasPermission(Tango.BL.Enumerations.Permissions.RunPPC)) { - NavigationManager.NavigateTo<InternalModule>(nameof(AccountView)); - }) - { - Name = "Account", - Index = -1, - Description = "Manage your account details", - Image = ResourceHelper.GetImageFromResources("Images/Menu/account.png"), - }); + NavigationManager.MenuItems.Add(new NavigationMenuItem(() => + { + NavigationManager.NavigateTo<InternalModule>(nameof(AccountView)); + }) + { + Name = "Account", + Index = -1, + Description = "Manage your account details", + Image = ResourceHelper.GetImageFromResources("Images/Menu/account.png"), + }); - NavigationManager.MenuItems.Add(new NavigationMenuItem(() => - { - NavigationManager.NavigateTo<InternalModule>(nameof(SettingsView)); - }) - { - Name = "Settings", - Index = 2, - Description = "Configuration of your Tango FSE", - Image = ResourceHelper.GetImageFromResources("Images/Menu/settings.png"), - }); + NavigationManager.MenuItems.Add(new NavigationMenuItem(() => + { + NavigationManager.NavigateTo<InternalModule>(nameof(SettingsView)); + }) + { + Name = "Settings", + Index = 2, + Description = "Configuration of your Tango FSE", + Image = ResourceHelper.GetImageFromResources("Images/Menu/settings.png"), + }); + } } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs index 158b740e3..701ff4b79 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs @@ -46,6 +46,8 @@ namespace Tango.FSE.UI.ViewModels public RelayCommand ToggleConnectionPaneCommand { get; set; } + public RelayCommand LogoutCommand { get; set; } + public LayoutViewVM() { ToggleConnectionPaneCommand = new RelayCommand(() => IsConnectionPaneOpened = !IsConnectionPaneOpened); @@ -54,6 +56,8 @@ namespace Tango.FSE.UI.ViewModels ConnectedMachinePaneVM = new ConnectedMachinePaneVM(); ConnectedMachinePaneVM.DisconnectedFromMachine += ConnectedMachinePaneVM_DisconnectedFromMachine; + + LogoutCommand = new RelayCommand(Logout); } private async void ConnectedMachinePaneVM_DisconnectedFromMachine(object sender, EventArgs e) @@ -101,5 +105,10 @@ namespace Tango.FSE.UI.ViewModels { Debug.WriteLine("Diagnostics Received..."); } + + private void Logout() + { + AuthenticationProvider.LogOut(); + } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs index f9c378b8b..6e27097c1 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs @@ -81,9 +81,16 @@ namespace Tango.FSE.UI.ViewModels } + public override void OnBeforeNavigatedTo() + { + base.OnBeforeNavigatedTo(); + SelectedView = LoginViews.Login; + } + public override void OnNavigatedTo() { base.OnNavigatedTo(); + SelectedEnvironment = GatewayService.Environments.FirstOrDefault(x => x.MachineServiceAddress == Settings.MachineServiceAddress); if (SelectedEnvironment == null) @@ -121,7 +128,7 @@ namespace Tango.FSE.UI.ViewModels IsFree = false; SelectedView = LoginViews.Logging; - var result = await AuthenticationProvider.Login(Email, Password, SelectedEnvironment); + var result = await AuthenticationProvider.Login(Email, Password, SelectedEnvironment, (status) => Status = status); Settings.LastLoginEmail = Email; Settings.RememberMe = RememberMe; @@ -137,16 +144,6 @@ namespace Tango.FSE.UI.ViewModels Settings.Save(); - Status = "Loading static collections..."; - - await Task.Factory.StartNew(() => - { - ObservablesStaticCollections.Instance.Initialize((msg) => - { - Status = msg; - }); - }); - Status = "Starting application..."; await Task.Delay(500); @@ -158,14 +155,29 @@ namespace Tango.FSE.UI.ViewModels } catch (Exception ex) { + LogManager.Log(ex, "FSE logging error."); IsFree = true; SelectedView = LoginViews.Login; - await NotificationProvider.ShowError(ex.GetFirstIfAggregate().Message); + await NotificationProvider.ShowError(GetErrorMessage(ex)); } finally { IsFree = true; } } + + private String GetErrorMessage(Exception ex) + { + var fullError = ex.FlattenMessage(); + + if (fullError.Contains("Invalid column")) + { + return "There is a mismatch of data schema between your version of Tango FSE and the remote service.\nPlease check the following:\n\u2022 The remote environment supports this application version.\n\u2022 Try to update your this version to the latest."; + } + else + { + return fullError; + } + } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml index 14684185a..5d84b6b46 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml @@ -359,9 +359,9 @@ </Grid> <Grid Grid.Row="1"> - <ItemsControl ItemsSource="{Binding NavigationManager.MenuItems}" Margin="0 50 0 0"> - <ItemsControl.Style> - <Style TargetType="ItemsControl"> + <DockPanel Margin="0 50 0 0"> + <DockPanel.Style> + <Style TargetType="DockPanel"> <Setter Property="RenderTransform"> <Setter.Value> <TranslateTransform X="0" /> @@ -386,18 +386,22 @@ </DataTrigger> </Style.Triggers> </Style> - </ItemsControl.Style> - <ItemsControl.ItemTemplate> - <DataTemplate> - <DockPanel> + </DockPanel.Style> + <Grid DockPanel.Dock="Bottom" Width="55" Height="55" Margin="0 10"> + <Ellipse Stroke="{StaticResource FSE_PrimaryForegroundBrush}" StrokeThickness="1"></Ellipse> + <Image Source="/Images/logout.png" RenderOptions.BitmapScalingMode="Fant" Width="35" Stretch="Uniform" /> + </Grid> + <ItemsControl ItemsSource="{Binding NavigationManager.MenuItems}"> + <ItemsControl.ItemTemplate> + <DataTemplate> <Grid Width="55" Height="55" Margin="0 10"> <Ellipse Stroke="{StaticResource FSE_PrimaryForegroundBrush}" StrokeThickness="1"></Ellipse> <Image Source="{Binding Image}" RenderOptions.BitmapScalingMode="Fant" Width="35" Stretch="Uniform" /> </Grid> - </DockPanel> - </DataTemplate> - </ItemsControl.ItemTemplate> - </ItemsControl> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </DockPanel> <Border Margin="0 -90 0 0"> <Border.Background> @@ -430,8 +434,49 @@ </Style> </Border.Style> - <Grid> - <ItemsControl ItemsSource="{Binding NavigationManager.MenuItems}" Margin="0 140 0 0"> + <DockPanel Margin="0 140 0 0"> + <Grid DockPanel.Dock="Bottom"> + <Border ToolTipService.BetweenShowDelay="1000" ToolTipService.InitialShowDelay="1000" material:RippleAssist.Feedback="White" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Cursor="Hand"> + <i:Interaction.Triggers> + <i:EventTrigger EventName="PreviewMouseUp"> + <i:InvokeCommandAction Command="{Binding LogoutCommand}" /> + </i:EventTrigger> + </i:Interaction.Triggers> + <Border.ToolTip> + <ToolTip FontFamily="{StaticResource flexo}" Background="#545454" Foreground="{StaticResource FSE_PrimaryForegroundBrush}" Placement="RelativePoint" PlacementRectangle="330 21 100 100"> + <TextBlock Text="Sign out from Tango FSE" TextWrapping="Wrap"></TextBlock> + </ToolTip> + </Border.ToolTip> + <Border.Effect> + <DropShadowEffect Direction="-90" ShadowDepth="0" Color="DimGray" BlurRadius="10" /> + </Border.Effect> + <Border.Style> + <Style TargetType="Border"> + <Setter Property="Opacity" Value="0"></Setter> + <Style.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter Property="Opacity" Value="1"></Setter> + </Trigger> + </Style.Triggers> + </Style> + </Border.Style> + <Grid> + <Canvas HorizontalAlignment="Right"> + <Polygon Fill="#545454" Points="0,0 20,20 20,55 0,75"> + + </Polygon> + </Canvas> + <material:Ripple /> + </Grid> + </Border> + <DockPanel IsHitTestVisible="False"> + <Grid Width="55" Height="55" Margin="10 10" HorizontalAlignment="Left"> + <Image Source="/Images/logout.png" RenderOptions.BitmapScalingMode="Fant" Width="35" Stretch="Uniform" /> + </Grid> + <TextBlock Margin="10 0 0 0" FontSize="{StaticResource FSE_LargeFontSize}" Text="Logout" VerticalAlignment="Center"></TextBlock> + </DockPanel> + </Grid> + <ItemsControl ItemsSource="{Binding NavigationManager.MenuItems}"> <ItemsControl.ItemTemplate> <DataTemplate> <Grid> @@ -478,7 +523,7 @@ </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> - </Grid> + </DockPanel> </Border> </Grid> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LoginView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LoginView.xaml index 23d8d6e70..bcfb0d1c4 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LoginView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LoginView.xaml @@ -68,7 +68,7 @@ <Button IsDefault="True" Margin="0 40 0 0" Height="50" material:ButtonAssist.CornerRadius="24" Command="{Binding LoginCommand}">LOGIN</Button> </StackPanel> - <StackPanel Width="300" controls:NavigationControl.NavigationName="Logging"> + <StackPanel controls:NavigationControl.NavigationName="Logging"> <ProgressBar Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center" IsIndeterminate="{Binding IsBusy}" Style="{StaticResource MaterialDesignCircularProgressBar}" Value="0" /> <TextBlock HorizontalAlignment="Center" Margin="0 40 0 0" FontSize="18">Logging you in, please wait...</TextBlock> <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0" Text="{Binding Status}" Foreground="{StaticResource FSE_GrayBrush}"></TextBlock> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml index 26d6a7843..36c1cba6f 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml @@ -335,7 +335,7 @@ <commonControls:IconButton Icon="Close" Padding="8" Margin="0 0 5 0" Command="{Binding CloseCommand}" CommandParameter="{Binding}" HorizontalAlignment="Right" Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"/> </Grid> - <TextBlock Grid.Row="1" Margin="40" Text="{Binding Message}" VerticalAlignment="Top" HorizontalAlignment="Left" TextWrapping="Wrap"></TextBlock> + <TextBox Style="{x:Null}" Cursor="Arrow" Background="Transparent" Foreground="{StaticResource FSE_PrimaryForegroundBrush}" BorderThickness="0" IsReadOnly="True" AcceptsReturn="True" SelectionBrush="{StaticResource FSE_PrimaryBackgroundLightBrush}" Grid.Row="1" Margin="40" Text="{Binding Message}" VerticalAlignment="Top" HorizontalAlignment="Left" TextWrapping="Wrap"></TextBox> <StackPanel HorizontalAlignment="Right" Grid.Row="2" Margin="10" Orientation="Horizontal"> <Button MinWidth="150" x:Name="btnCancel" Height="Auto" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Margin="0 0 10 0" Command="{Binding CloseCommand}" Visibility="{Binding HasCancel,Converter={StaticResource BooleanToVisibilityConverter}}" Content="{Binding CancelText}"></Button> |
