From b4682a3abfe299c19b24752b2fb1ce2477611ec3 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Fri, 10 Apr 2020 15:06:42 +0300 Subject: Implemented FSE/PPC Logs. --- Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs | 3 +++ Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs | 2 ++ Software/Visual_Studio/Tango.FileSystem/Network/FileSystemItemDTO.cs | 2 ++ 3 files changed, 7 insertions(+) (limited to 'Software/Visual_Studio/Tango.FileSystem') diff --git a/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs b/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs index c8b2fce32..558251f3c 100644 --- a/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs +++ b/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs @@ -25,6 +25,8 @@ namespace Tango.FileSystem public DateTime DateModified { get; set; } + public DateTime DateCreated { get; set; } + public long Size { get; set; } public String Name @@ -75,6 +77,7 @@ namespace Tango.FileSystem } item.DateModified = dto.DateModified; + item.DateCreated = dto.DateCreated; item.Path = dto.Path; item.Size = dto.Size; item.Type = dto.Type; diff --git a/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs b/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs index c08304ca8..dc8efa7dd 100644 --- a/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs +++ b/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs @@ -71,6 +71,7 @@ namespace Tango.FileSystem Path = directory, Type = FileSystemItemType.Folder, DateModified = Directory.GetLastWriteTimeUtc(directory), + DateCreated = Directory.GetCreationTimeUtc(directory), }); } @@ -83,6 +84,7 @@ namespace Tango.FileSystem Path = file, Type = FileSystemItemType.File, DateModified = File.GetLastWriteTimeUtc(file), + DateCreated = File.GetCreationTimeUtc(file), Size = new FileInfo(file).Length }); } diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/FileSystemItemDTO.cs b/Software/Visual_Studio/Tango.FileSystem/Network/FileSystemItemDTO.cs index 900ba0628..43467f227 100644 --- a/Software/Visual_Studio/Tango.FileSystem/Network/FileSystemItemDTO.cs +++ b/Software/Visual_Studio/Tango.FileSystem/Network/FileSystemItemDTO.cs @@ -19,6 +19,8 @@ namespace Tango.FileSystem.Network public DateTime DateModified { get; set; } + public DateTime DateCreated { get; set; } + public long Size { get; set; } public bool IsRoot { get; set; } -- cgit v1.3.1 From 52813618e140c921ff653d9c227c35032207b495 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 15 Apr 2020 04:54:52 +0300 Subject: FSE Firmware FileSystem. --- .../FSE/Modules/Tango.FSE.Firmware/App.xaml | 16 + .../Modules/Tango.FSE.Firmware/FirmwareModule.cs | 26 ++ .../Modules/Tango.FSE.Firmware/Images/firmware.png | Bin 0 -> 771 bytes .../Tango.FSE.Firmware/Properties/AssemblyInfo.cs | 55 +++ .../Properties/Resources.Designer.cs | 71 +++ .../Tango.FSE.Firmware/Properties/Resources.resx | 117 +++++ .../Properties/Settings.Designer.cs | 30 ++ .../Properties/Settings.settings | 7 + .../Tango.FSE.Firmware/Tango.FSE.Firmware.csproj | 208 +++++++++ .../Modules/Tango.FSE.Firmware/ViewModelLocator.cs | 53 +++ .../ViewModels/FileSystemViewVM.cs | 508 +++++++++++++++++++++ .../Tango.FSE.Firmware/ViewModels/LogsViewVM.cs | 13 + .../Tango.FSE.Firmware/ViewModels/MainViewVM.cs | 52 +++ .../Tango.FSE.Firmware/ViewModels/UpdatesViewVM.cs | 13 + .../Tango.FSE.Firmware/Views/FileSystemView.xaml | 288 ++++++++++++ .../Views/FileSystemView.xaml.cs | 42 ++ .../Modules/Tango.FSE.Firmware/Views/LogsView.xaml | 17 + .../Tango.FSE.Firmware/Views/LogsView.xaml.cs | 28 ++ .../Modules/Tango.FSE.Firmware/Views/MainView.xaml | 37 ++ .../Tango.FSE.Firmware/Views/MainView.xaml.cs | 28 ++ .../Tango.FSE.Firmware/Views/UpdatesView.xaml | 17 + .../Tango.FSE.Firmware/Views/UpdatesView.xaml.cs | 28 ++ .../FSE/Modules/Tango.FSE.Firmware/app.config | 85 ++++ .../FSE/Modules/Tango.FSE.Firmware/packages.config | 10 + .../ViewModels/FileSystemViewVM.cs | 59 ++- .../Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs | 4 +- .../Modules/Tango.FSE.Upgrade/Images/firmware.png | Bin 1819 -> 771 bytes .../Tango.FSE.Upgrade/ViewModels/MainViewVM.cs | 2 +- .../Controls/FileSystemControl.xaml | 227 +++++++++ .../FSE/Tango.FSE.Common/FSEViewModel.cs | 7 + .../FileSystem/IFileSystemProvider.cs | 5 +- .../Firmware/IFirmwareStorageProvider.cs | 58 +++ .../FSE/Tango.FSE.Common/Tango.FSE.Common.csproj | 1 + .../Connection/DefaultMachineProvider.cs | 2 +- .../FileSystem/DefaultFileSystemProvider.cs | 16 +- .../Firmware/DefaultFirmwareStorageProvider.cs | 359 +++++++++++++++ .../FSE/Tango.FSE.UI/Tango.FSE.UI.csproj | 5 + .../FSE/Tango.FSE.UI/ViewModelLocator.cs | 4 + .../Tango.FileSystem/FileExplorerControl.cs | 10 +- .../Tango.FileSystem/FileSystemItem.cs | 21 + .../ExternalBridge/ExternalBridgeService.cs | 34 +- .../Tango.Integration/Storage/StorageDrive.cs | 2 +- Software/Visual_Studio/Tango.sln | 35 +- 43 files changed, 2555 insertions(+), 45 deletions(-) create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/App.xaml create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/FirmwareModule.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Images/firmware.png create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/AssemblyInfo.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Resources.Designer.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Resources.resx create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Settings.Designer.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Settings.settings create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModelLocator.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/FileSystemViewVM.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/LogsViewVM.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/MainViewVM.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/UpdatesViewVM.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/LogsView.xaml create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/LogsView.xaml.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/MainView.xaml create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/MainView.xaml.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/UpdatesView.xaml create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/UpdatesView.xaml.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/app.config create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/packages.config create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.Common/Firmware/IFirmwareStorageProvider.cs create mode 100644 Software/Visual_Studio/FSE/Tango.FSE.UI/Firmware/DefaultFirmwareStorageProvider.cs (limited to 'Software/Visual_Studio/Tango.FileSystem') diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/App.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/App.xaml new file mode 100644 index 000000000..f0c79dd5a --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/App.xaml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/FirmwareModule.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/FirmwareModule.cs new file mode 100644 index 000000000..b72fdc2ff --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/FirmwareModule.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.Firmware.Views; + +namespace Tango.FSE.Firmware +{ + [FSEModule(index: 5)] + public class FirmwareModule : FSEModuleBase + { + public override string Name { get; } = "Firmware"; + public override string Description { get; } = "Firmware 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.Firmware/Images/firmware.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Images/firmware.png new file mode 100644 index 000000000..3f8f87906 Binary files /dev/null and b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Images/firmware.png differ diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/AssemblyInfo.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..fff471c3d --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/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.Firmware")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tango.FSE.Firmware")] +[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 +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the 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.Firmware/Properties/Resources.Designer.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Resources.Designer.cs new file mode 100644 index 000000000..d18a30f88 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Tango.FSE.Firmware.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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.Firmware.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [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.Firmware/Properties/Resources.resx b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Settings.Designer.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Settings.Designer.cs new file mode 100644 index 000000000..f9ead22d2 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Tango.FSE.Firmware.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.Firmware/Properties/Settings.settings b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj new file mode 100644 index 000000000..c3e0d4850 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Tango.FSE.Firmware.csproj @@ -0,0 +1,208 @@ + + + + + Debug + AnyCPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174} + library + Tango.FSE.Firmware + Tango.FSE.Firmware + v4.6.1 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + + + true + full + false + ..\..\..\Build\FSE\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\..\Build\FSE\Release\ + TRACE + prompt + 4 + + + + ..\..\..\packages\ControlzEx.3.0.2.4\lib\net45\ControlzEx.dll + + + ..\..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll + + + ..\..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll + + + ..\..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll + + + ..\..\..\packages\MahApps.Metro.1.6.5\lib\net46\MahApps.Metro.dll + + + ..\..\..\packages\MaterialDesignColors.1.2.2\lib\net45\MaterialDesignColors.dll + + + ..\..\..\packages\MaterialDesignThemes.3.0.1\lib\net45\MaterialDesignThemes.Wpf.dll + + + ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + + + + + ..\..\..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll + + + + + + + + + 4.0 + + + + + + + + + + + + + + FileSystemView.xaml + + + LogsView.xaml + + + MainView.xaml + + + UpdatesView.xaml + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + {bb2abb74-ba58-4812-83aa-ec8171f42df4} + Tango.AutoComplete + + + {f441feee-322a-4943-b566-110e12fd3b72} + Tango.BL + + + {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} + Tango.Core + + + {c6ebbbbe-2123-44dc-aef7-a0d47d736ac0} + Tango.FileSystem + + + {4206ac58-3b57-4699-8835-90bf6db01a61} + Tango.Integration + + + {bc932dbd-7cdb-488c-99e4-f02cf441f55e} + Tango.Logging + + + {e4927038-348d-4295-aaf4-861c58cb3943} + Tango.PMR + + + {d8f1ad85-526a-4f50-b6dc-d437af63d8d8} + Tango.Settings + + + {8491d07b-c1f6-4b62-a412-41b9fd2d6538} + Tango.SharedUI + + + {74e700b0-1156-4126-be40-ee450d3c3026} + Tango.Transport + + + {834c81c3-09b5-45d7-be12-e7d1e6655a7c} + Tango.FSE.BL + + + {bc37cccb-7392-4f78-8d1c-e9629e6e046e} + Tango.FSE.Common + + + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + + + + + + 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}. + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModelLocator.cs new file mode 100644 index 000000000..b1bad5dcf --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModelLocator.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.DI; +using Tango.FSE.Firmware.ViewModels; + +namespace Tango.FSE.Firmware +{ + public static class ViewModelLocator + { + static ViewModelLocator() + { + TangoIOC.Default.Register(); + TangoIOC.Default.Register(); + TangoIOC.Default.Register(); + TangoIOC.Default.Register(); + } + + public static MainViewVM MainViewVM + { + get + { + return TangoIOC.Default.GetInstance(); + } + } + + public static FileSystemViewVM FileSystemViewVM + { + get + { + return TangoIOC.Default.GetInstance(); + } + } + + public static UpdatesViewVM UpdatesViewVM + { + get + { + return TangoIOC.Default.GetInstance(); + } + } + + public static LogsViewVM LogsViewVM + { + get + { + return TangoIOC.Default.GetInstance(); + } + } + } +} 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 new file mode 100644 index 000000000..bb655d27b --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/FileSystemViewVM.cs @@ -0,0 +1,508 @@ +using MaterialDesignThemes.Wpf; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using Tango.Core.Commands; +using Tango.FileSystem; +using Tango.FSE.Common; +using Tango.FSE.Common.Connection; +using Tango.FSE.Common.FileSystem; + +namespace Tango.FSE.Firmware.ViewModels +{ + public class FileSystemViewVM : FSEViewModel + { + #region Properties + + private FileSystemItem _currentItem; + /// + /// Gets or sets the current file system item. + /// + public FileSystemItem CurrentItem + { + get { return _currentItem; } + set { _currentItem = value; RaisePropertyChangedAuto(); OnCurrentItemChanged(); } + } + + private String _currentPath; + /// + /// Gets or sets the current remote path. + /// + public String CurrentPath + { + get { return _currentPath; } + set { _currentPath = value; RaisePropertyChangedAuto(); } + } + + /// + /// Gets or sets the selected file system items. + /// + public ObservableCollection SelectedItems { get; set; } + + /// + /// Gets or sets the list of file system handlers downloads/uploads. + /// + public ObservableCollection FileSystemHandlers { get; set; } + + #endregion + + #region Commands + + /// + /// Navigates to the current path. + /// + public RelayCommand NavigateCommand { get; set; } + + /// + /// Opens the current selected item (context menu). + /// + public RelayCommand OpenItemCommand { get; set; } + + /// + /// Navigates back. + /// + public RelayCommand BackCommand { get; set; } + + /// + /// Navigates to the specified folder. + /// + public RelayCommand NavigateToFolderCommand { get; set; } + + /// + /// Deletes the specified file system item (context menu or DEL key). + /// + public RelayCommand> DeleteCommand { get; set; } + + /// + /// Handles the drag & drop of items from the operation system shell onto the file system view. + /// + public RelayCommand> DropCommand { get; set; } + + /// + /// Handles the drag & drop of items from the file system view onto the operation system shell. + /// + public RelayCommand> DragCommand { get; set; } + + /// + /// Removes the specified file system handler. + /// + public RelayCommand DeleteFileSystemHandlerCommand { get; set; } + + /// + /// Opens the parent directory of a file system handler item. + /// A download will execute the local explorer.exe. + /// An upload will navigate to the remote parent folder. + /// + public RelayCommand OpenFileSystemHandlerDestinationCommand { get; set; } + + /// + /// Downloads the specified remote items. + /// + public RelayCommand> DownloadCommand { get; set; } + + /// + /// Invokes a dialog for choosing items to upload and starts the upload. + /// + public RelayCommand UploadCommand { get; set; } + + /// + /// Creates a new folder at the current remote path. + /// + public RelayCommand NewFolderCommand { get; set; } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public FileSystemViewVM() + { + SelectedItems = new ObservableCollection(); + FileSystemHandlers = new ObservableCollection(); + NavigateCommand = new RelayCommand(NavigateToCurrentPath); + OpenItemCommand = new RelayCommand(OpenFileSystemItem); + BackCommand = new RelayCommand(NavigateBack, () => !(CurrentItem is FolderItem) || !(CurrentItem as FolderItem).IsRoot); + NavigateToFolderCommand = new RelayCommand(async (x) => await Navigate(x)); + DeleteCommand = new RelayCommand>(DeleteSelectedItems); + DragCommand = new RelayCommand>(OnItemsDraggedOut); + DropCommand = new RelayCommand>(OnItemsDroppedIn); + DeleteFileSystemHandlerCommand = new RelayCommand(DeleteFileSystemHandler); + OpenFileSystemHandlerDestinationCommand = new RelayCommand(OpenFileSystemHandlerDestination); + DownloadCommand = new RelayCommand>(DownloadSelectedItems); + NewFolderCommand = new RelayCommand(CreateNewFolder); + UploadCommand = new RelayCommand(UploadFilesAndFolder); + } + + #endregion + + #region Override Methods + + /// + /// Called when the application has been started. + /// + public override void OnApplicationStarted() + { + base.OnApplicationStarted(); + MachineProvider.MachineConnected += MachineProvider_MachineConnected; + } + + #endregion + + #region Event Handlers + + private async void MachineProvider_MachineConnected(object sender, MachineConnectedEventArgs e) + { + if (e.DifferentFromPrevious) + { + try + { + await Navigate(null, true); + } + catch (Exception ex) + { + NotificationProvider.PushErrorReportingSnackbar(ex, "Firmware Module Error", "Could not initialize the remote firmware file system provider."); + } + } + } + + #endregion + + #region Private Methods + + private async void NavigateBack() + { + if (CurrentItem.Path.Length == 1) + { + await Navigate(null); + } + else + { + String parent = Path.GetDirectoryName(CurrentItem.Path); + await Navigate(parent); + } + } + + private void NavigateToCurrentPath() + { + InvokeUI(async () => + { + await Navigate(CurrentPath); + }); + } + + private async void OpenFileSystemItem(FileSystemItem item) + { + if (item == null) return; + + if (item.Type == FileSystemItemType.Folder || item.Type == FileSystemItemType.Drive) + { + await Navigate(item.Path); + } + else if (item.Type == FileSystemItemType.File) + { + //TODO: Download/Open file?... + } + } + + private async void DeleteSelectedItems(IList items) + { + if (items != null && items.Count > 0) + { + if (await NotificationProvider.ShowWarningQuestion($"Are you sure you want to delete {(items.Count == 1 ? $"'{items.First().Name}'" : $"the {items.Count} selected files/folders")}?", "DELETE")) + { + using (var task = NotificationProvider.PushTaskItem("Removing...")) + { + int remainingItems = items.Count; + + foreach (var item in items) + { + task.UpdateProgress($"Removing '{item.Name}'..."); + + try + { + remainingItems--; + await FirmwareStorageProvider.Delete(item); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Could not remove '{item.Name}'."); + + if (remainingItems > 0) + { + if (!await NotificationProvider.ShowWarningQuestion($"Could not remove '{item.Name}'.\n{ex.FlattenMessage()}\nDo you wish to continue removing the remaining items?")) + { + break; + } + } + else + { + await NotificationProvider.ShowError($"Could not remove '{item.Name}'.\n{ex.FlattenMessage()}"); + } + } + } + } + + NavigateToCurrentPath(); + } + } + } + + private async void OnItemsDraggedOut(List items) + { + if (items.Exists(x => x.FileSystemItem.Type != FileSystemItemType.File)) + { + await NotificationProvider.ShowError("Firmware file system does not support folder downloads."); + return; + } + + foreach (var item in items) + { + String destination = Path.Combine(item.Destination, item.FileSystemItem.Name); + + if (File.Exists(destination)) + { + if (!await NotificationProvider.ShowWarningQuestion($"'{item.FileSystemItem.Name}' already exists on '{item.Destination}'. Do you want to overwrite?")) + { + continue; + } + } + + try + { + var handler = await FirmwareStorageProvider.Download(item.FileSystemItem as FileItem, destination); + FileSystemHandlers.Insert(0, handler); + } + catch (Exception ex) + { + await NotificationProvider.ShowError(ex.FlattenMessage()); + } + } + } + + private void OnItemsDroppedIn(List items) + { + UploadFiles(items.Select(x => x.Path).ToList()); + } + + private async void DeleteFileSystemHandler(FileSystemHandler handler) + { + if (handler.Status != FileSystemHandlerStatus.Completed && handler.Status != FileSystemHandlerStatus.Failed) + { + if (await NotificationProvider.ShowWarningQuestion($"This item is currently {handler.Status}. Do you wish to abort and delete this item?")) + { + try + { + handler.Abort(); + } + catch { } + + FileSystemHandlers.Remove(handler); + } + } + else + { + FileSystemHandlers.Remove(handler); + } + } + + private async void OpenFileSystemHandlerDestination(FileSystemHandler handler) + { + if (handler.Type == FileSystemHandlerType.FileDownload || handler.Type == FileSystemHandlerType.FolderDownload) + { + await StorageProvider.ShowInExplorer(handler.Destination); + } + else + { + await Navigate(Path.GetDirectoryName(handler.Destination)); + } + } + + private async Task Navigate(String path, bool throwError = false) + { + try + { + IsFree = false; + + Mouse.OverrideCursor = Cursors.AppStarting; + + if (path != null) + { + CurrentItem = await FirmwareStorageProvider.GetFolder(path) as FileSystemItem; + } + else + { + CurrentItem = await FirmwareStorageProvider.GetRoot() as FileSystemItem; + } + } + catch (Exception ex) + { + IsFree = true; + Mouse.OverrideCursor = null; + if (!throwError) + { + await NotificationProvider.ShowError($"Error navigating to the specified path.\n{ex.FlattenMessage()}"); + } + else + { + throw ex; + } + } + finally + { + IsFree = true; + Mouse.OverrideCursor = null; + } + } + + private async void DownloadSelectedItems(List items) + { + if (items.Exists(x => x.Type != FileSystemItemType.File)) + { + await NotificationProvider.ShowError("Firmware file system does not support folder downloads."); + return; + } + + if (items.Count == 1) + { + var fileItem = items.First() as FileItem; + + var result = await StorageProvider.SaveFile("Select download destination file", $"{fileItem.Description}|*{fileItem.Extension}", fileItem.Name, fileItem.Extension); + if (result) + { + try + { + var handler = await FirmwareStorageProvider.Download(fileItem, result.SelectedItem); + FileSystemHandlers.Insert(0, handler); + } + catch (Exception ex) + { + await NotificationProvider.ShowError(ex.FlattenMessage()); + } + } + } + else + { + var result = await StorageProvider.SelectFolder("Select download destination folder"); + if (result) + { + foreach (var item in items.OfType()) + { + String destination = Path.Combine(result.SelectedItem, item.Name); + + if (File.Exists(destination)) + { + if (!await NotificationProvider.ShowWarningQuestion($"'{item.Name}' already exists on '{result.SelectedItem}'. Do you want to overwrite?")) + { + continue; + } + } + + try + { + var handler = await FirmwareStorageProvider.Download(item, destination); + FileSystemHandlers.Insert(0, handler); + } + catch (Exception ex) + { + await NotificationProvider.ShowError(ex.FlattenMessage()); + } + } + } + } + } + + private async void UploadFilesAndFolder() + { + var result = await StorageProvider.OpenFiles("Select files to upload"); + if (result) + { + UploadFiles(result.SelectedItems); + } + } + + private async void UploadFiles(List files) + { + String currentPathBefore = CurrentPath; + + foreach (var file in files) + { + if (!File.Exists(file)) + { + await NotificationProvider.ShowError($"File '{file}' cannot be uploaded."); + return; + } + } + + foreach (var file in files) + { + String itemName = Path.GetFileName(file); + + if ((CurrentItem as IFileSystemContainer).Items.ToList().Exists(x => x.Name.ToLower() == itemName.ToLower())) + { + if (!await NotificationProvider.ShowWarningQuestion($"'{itemName}' already exists on '{CurrentItem.Name}'. Do you want to overwrite?")) + { + continue; + } + } + + var handler = await FirmwareStorageProvider.Upload(file, Path.Combine(CurrentItem.Path, Path.GetFileName(file))); + + handler.StatusChanged += (x, status) => + { + if (status == FileSystemHandlerStatus.Completed && currentPathBefore == CurrentPath) + { + NavigateToCurrentPath(); + } + }; + + FileSystemHandlers.Insert(0, handler); + } + } + + private async void CreateNewFolder() + { + if (CurrentItem == null) return; + + var result = await NotificationProvider.ShowInputBox( + "New Folder", + $"Please enter a folder name and press 'ENTER'.", + PackIconKind.FolderAdd, "untitled", + "folder name", + 100, + "CREATE"); + + if (result.Confirmed) + { + try + { + using (NotificationProvider.PushTaskItem("Creating new folder...")) + { + var folderItem = await FirmwareStorageProvider.CreateFolder(CurrentItem, result.Input); + NavigateToCurrentPath(); //Instead of inserting folder item just refresh the current path... + } + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error creating new folder '{Path.Combine(CurrentItem.Path, result.Input)}."); + await NotificationProvider.ShowError($"Error creating folder '{result.Input}'.\n{ex.FlattenMessage()}"); + } + } + } + + private void OnCurrentItemChanged() + { + CurrentPath = CurrentItem.Path; + InvalidateRelayCommands(); + } + + #endregion + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/LogsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/LogsViewVM.cs new file mode 100644 index 000000000..690649497 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/LogsViewVM.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FSE.Common; + +namespace Tango.FSE.Firmware.ViewModels +{ + public class LogsViewVM : FSEViewModel + { + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/MainViewVM.cs new file mode 100644 index 000000000..4cdfb25ee --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/MainViewVM.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FSE.Common; +using Tango.FSE.Common.Navigation; +using Tango.SharedUI.Helpers; + +namespace Tango.FSE.Firmware.ViewModels +{ + public class MainViewVM : FSEViewModel + { + public enum NavigationView + { + FileSystemView, + UpdatesView, + LogsView, + } + + private NavigationView _selectedView; + public NavigationView SelectedView + { + get { return _selectedView; } + set + { + _selectedView = value; + RaisePropertyChangedAuto(); + } + } + + public override void OnApplicationReady() + { + base.OnApplicationReady(); + + InvokeUI(() => + { + NavigationManager.MenuItems.Add(new NavigationMenuItem(() => + { + NavigationManager.NavigateTo(); + }) + { + Name = "Firmware", + Index = 3, + Description = "Manage the remote machine's firmware device.", + Image = ResourceHelper.GetImageFromResources("Images/firmware.png"), + }); + }); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/UpdatesViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/UpdatesViewVM.cs new file mode 100644 index 000000000..5727726a2 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/ViewModels/UpdatesViewVM.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FSE.Common; + +namespace Tango.FSE.Firmware.ViewModels +{ + public class UpdatesViewVM : FSEViewModel + { + } +} 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 new file mode 100644 index 000000000..6ebeb6b60 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Transfer Queue + + () + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / + + + + /s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml.cs new file mode 100644 index 000000000..a742ca7cf --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/FileSystemView.xaml.cs @@ -0,0 +1,42 @@ +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.Firmware.Views +{ + /// + /// Interaction logic for FileSystemView.xaml + /// + public partial class FileSystemView : UserControl + { + private object _lastSelectedItem; + + public FileSystemView() + { + InitializeComponent(); + } + + private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (listView.SelectedItem != null) + { + _lastSelectedItem = listView.SelectedItem; + } + else + { + listView.SelectedItem = _lastSelectedItem; + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/LogsView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/LogsView.xaml new file mode 100644 index 000000000..872bf5cff --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/LogsView.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/LogsView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/LogsView.xaml.cs new file mode 100644 index 000000000..5317b355a --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/LogsView.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.Firmware.Views +{ + /// + /// Interaction logic for LogsView.xaml + /// + public partial class LogsView : UserControl + { + public LogsView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/MainView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/MainView.xaml new file mode 100644 index 000000000..a9b18c62e --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/MainView.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/MainView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/MainView.xaml.cs new file mode 100644 index 000000000..b6d559265 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/MainView.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.Firmware.Views +{ + /// + /// Interaction logic for MainView.xaml + /// + public partial class MainView : UserControl + { + public MainView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/UpdatesView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/UpdatesView.xaml new file mode 100644 index 000000000..a38e8acf5 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/UpdatesView.xaml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/UpdatesView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/UpdatesView.xaml.cs new file mode 100644 index 000000000..f461d14de --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/Views/UpdatesView.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.Firmware.Views +{ + /// + /// Interaction logic for UpdatesView.xaml + /// + public partial class UpdatesView : UserControl + { + public UpdatesView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/app.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/app.config new file mode 100644 index 000000000..36bc04f85 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/app.config @@ -0,0 +1,85 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/packages.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/packages.config new file mode 100644 index 000000000..dd8c723e4 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Firmware/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs index 4ed6629b5..b34c8c527 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs @@ -387,13 +387,23 @@ namespace Tango.FSE.PPCConsole.ViewModels } } - private async void RetryFailedFileSystemHandler(FileSystemHandler handler) + private void RetryFailedFileSystemHandler(FileSystemHandler handler) { - if (handler.Status == FileSystemHandlerStatus.Failed) - { - var newHandler = await FileSystemProvider.Download(handler.FileSystemItem, Path.GetDirectoryName(handler.Destination)); - FileSystemHandlers.Replace(handler, newHandler); - } + //Not supported Yet! + + //if (handler.Status == FileSystemHandlerStatus.Failed) + //{ + // if (handler.Type == FileSystemHandlerType.FileDownload || handler.Type == FileSystemHandlerType.FolderDownload) + // { + // var newHandler = await FileSystemProvider.Download(handler.FileSystemItem, Path.GetDirectoryName(handler.Destination)); + // FileSystemHandlers.Replace(handler, newHandler); + // } + // else + // { + // var newHandler = await FileSystemProvider.Upload(Path.GetDirectoryName(handler.Destination), handler.FileSystemItem); + // FileSystemHandlers.Replace(handler, newHandler); + // } + //} } private async void NavigateToSpecialFolder(string folder) @@ -502,26 +512,37 @@ namespace Tango.FSE.PPCConsole.ViewModels private async void DownloadSelectedItems(List items) { - var result = await StorageProvider.SelectFolder("Select download destination folder"); - if (result) + if (items.Count == 1 && items.First().Type == FileSystemItemType.File) { + var fileItem = items.First() as FileItem; - String destination = result.SelectedItem; - - Debug.WriteLine($"Download to {result.SelectedItem}"); - - foreach (var item in items.Where(x => x.Type != FileSystemItemType.Drive)) + var result = await StorageProvider.SaveFile("Select download destination file", $"{fileItem.Description}|*{fileItem.Extension}", fileItem.Name, fileItem.Extension); + if (result) + { + var handler = await FileSystemProvider.Download(fileItem, result.SelectedItem, true); + FileSystemHandlers.Insert(0, handler); + } + } + else + { + var result = await StorageProvider.SelectFolder("Select download destination folder"); + if (result) { - if (File.Exists(Path.Combine(destination, item.Name)) || Directory.Exists(Path.Combine(destination, item.Name))) + String destination = result.SelectedItem; + + foreach (var item in items.Where(x => x.Type != FileSystemItemType.Drive)) { - if (!await NotificationProvider.ShowWarningQuestion($"'{item.Name}' already exists on '{Path.GetDirectoryName(destination)}'. Do you want to overwrite?")) + if (File.Exists(Path.Combine(destination, item.Name)) || Directory.Exists(Path.Combine(destination, item.Name))) { - continue; + if (!await NotificationProvider.ShowWarningQuestion($"'{item.Name}' already exists on '{Path.GetDirectoryName(destination)}'. Do you want to overwrite?")) + { + continue; + } } - } - var handler = await FileSystemProvider.Download(item, destination); - FileSystemHandlers.Insert(0, handler); + var handler = await FileSystemProvider.Download(item, destination); + FileSystemHandlers.Insert(0, handler); + } } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs index 83852abe3..aeccb012f 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs @@ -47,9 +47,9 @@ namespace Tango.FSE.PPCConsole.ViewModels NavigationManager.NavigateTo(); }) { - Name = "Console", + Name = "Application", Index = 2, - Description = "Monitor the current connected machine telemetry", + Description = "Manage the remote machine panel PC.", Image = ResourceHelper.GetImageFromResources("Images/ppc_console.png"), }); }); diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Images/firmware.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Images/firmware.png index 2ec10ffc3..3f8f87906 100644 Binary files a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Images/firmware.png and b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Images/firmware.png differ 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 e41021b78..2907d8d5c 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 @@ -24,7 +24,7 @@ namespace Tango.FSE.Upgrade.ViewModels }) { Name = "Remote Upgrade", - Index = 3, + Index = 4, Description = "Upgrade or downgrade the machine application and firmware versions remotely.", Image = ResourceHelper.GetImageFromResources("Images/remote_upgrade.png"), }); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml index 63d90c171..779657de3 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml @@ -276,4 +276,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs index d53c0483c..4c58321e9 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs @@ -36,6 +36,7 @@ using Tango.FSE.Common.BugReporting; using Tango.FSE.Common.RemoteUpgrade; using Tango.FSE.Common.AutoComplete; using Tango.BL.Entities; +using Tango.FSE.Common.Firmware; namespace Tango.FSE.Common { @@ -155,6 +156,12 @@ namespace Tango.FSE.Common [TangoInject] public IRemoteUpgradeManager RemoteUpgradeManager { get; set; } + /// + /// Gets or sets the firmware storage provider. + /// + [TangoInject] + public IFirmwareStorageProvider FirmwareStorageProvider { get; set; } + /// /// Gets or sets the FSE service. /// diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs index cade631fa..9f54b6958 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs @@ -48,9 +48,10 @@ namespace Tango.FSE.Common.FileSystem /// Downloads the specified file or folder item. /// /// The file or folder. - /// The local target folder. + /// The local target folder or file. + /// Indicates whether the localTargetFolder is a file. /// - Task Download(FileSystemItem item, String localTargetFolder); + Task Download(FileSystemItem item, String localTargetFolderOrFile, bool isSingleFile = false); /// /// Uploads the specified local file or folder. diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Firmware/IFirmwareStorageProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Firmware/IFirmwareStorageProvider.cs new file mode 100644 index 000000000..32d19d778 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Firmware/IFirmwareStorageProvider.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FileSystem; +using Tango.FSE.Common.FileSystem; + +namespace Tango.FSE.Common.Firmware +{ + public interface IFirmwareStorageProvider + { + /// + /// Gets a folder by the specified path. + /// + /// The path. + /// + Task GetFolder(String path); + + /// + /// Gets the ThisPC (the root path of the storage device). + /// + /// + Task GetRoot(); + + /// + /// Downloads the specified file item. + /// + /// The file item. + /// The local target path. + /// + Task Download(FileItem item, String localTargetPath); + + /// + /// Uploads the specified local file or folder. + /// + /// The local source path. + /// The remote destination path. + /// + /// Could not locate the local file or directory to upload. + Task Upload(String localSourcePath, String remoteTargetPath); + + /// + /// Deletes the specified file or folder. + /// + /// The remote file or folder. + /// + Task Delete(FileSystemItem item); + + /// + /// Creates a new folder at the specified remote parent. + /// + /// The remote parent path. + /// Name of the new folder. + /// + Task CreateFolder(FileSystemItem parent, String folderName); + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj index ad9855566..5ca1ca85b 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj @@ -129,6 +129,7 @@ + diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs index c3a115b92..e4d788b03 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs @@ -116,7 +116,7 @@ namespace Tango.FSE.UI.Connection /// public bool IsPPCAvailable { - get { return ConnectionType.IsRemote(); } + get { return IsConnected && ConnectionType.IsRemote(); } } private TimeSpan _connectionTime; diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs index 49dc35f72..6bc667b32 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs @@ -268,11 +268,12 @@ namespace Tango.FSE.UI.FileSystem /// Downloads the specified file or folder item. /// /// The file or folder. - /// The local target folder. + /// The local target folder or file. + /// Indicates whether the localTargetFolder is a file. /// - public Task Download(FileSystemItem item, string localTargetFolder) + public Task Download(FileSystemItem item, String localTargetFolderOrFile, bool isSingleFile = false) { - LogManager.Log($"Downloading remote item '{item.Path}' to local path '{localTargetFolder}'..."); + LogManager.Log($"Downloading remote item '{item.Path}' to local path '{localTargetFolderOrFile}'..."); String operationId = String.Empty; String destination = String.Empty; @@ -281,7 +282,14 @@ namespace Tango.FSE.UI.FileSystem FileSystemHandler handler = null; - destination = Path.Combine(localTargetFolder, item.Name); + if (isSingleFile) + { + destination = localTargetFolderOrFile; + } + else + { + destination = Path.Combine(localTargetFolderOrFile, item.Name); + } handler = new FileSystemHandler(item.Type == FileSystemItemType.Folder ? FileSystemHandlerType.FolderDownload : FileSystemHandlerType.FileDownload, item, destination, async () => { diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Firmware/DefaultFirmwareStorageProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Firmware/DefaultFirmwareStorageProvider.cs new file mode 100644 index 000000000..e8ed4badb --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Firmware/DefaultFirmwareStorageProvider.cs @@ -0,0 +1,359 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Core.DI; +using Tango.Core.Threading; +using Tango.FileSystem; +using Tango.FSE.Common.Connection; +using Tango.FSE.Common.FileSystem; +using Tango.FSE.Common.Firmware; +using Tango.FSE.Common.Notifications; +using Tango.Integration.Storage; + +namespace Tango.FSE.UI.Firmware +{ + [TangoCreateWhenRegistered] + public class DefaultFirmwareStorageProvider : ExtendedObject, IFirmwareStorageProvider + { + private StorageManager _manager; + private IMachineProvider _machineProvider; + private List _activeHandlers; + private StorageDrive _storageDrive; + + [TangoInject] + private INotificationProvider NotificationProvider { get; set; } + + public DefaultFirmwareStorageProvider(IMachineProvider machineProvider) + { + _activeHandlers = new List(); + _machineProvider = machineProvider; + _manager = machineProvider.MachineOperator.CreateStorageManager(); + machineProvider.MachineConnected += MachineProvider_MachineConnected; + } + + private void MachineProvider_MachineConnected(object sender, MachineConnectedEventArgs e) + { + _manager = e.MachineOperator.CreateStorageManager(); + } + + public async Task GetFolder(string path) + { + try + { + LogManager.Log($"Retrieving remote firmware folder '{path}'..."); + + var storageFolder = await _manager.GetFolder(path); + var folderItem = storageFolder.ToFileSystemItem() as IFileSystemContainer; + + if (_storageDrive != null) + { + if ((folderItem as FolderItem).Path == _storageDrive.Root) + { + (folderItem as FolderItem).IsRoot = true; + } + } + + return folderItem; + } + catch (Exception ex) + { + throw LogManager.Log(ex, "Error retrieving remote firmware folder."); + } + } + + public async Task GetRoot() + { + _storageDrive = await _manager.GetStorageDrive(); + return await GetFolder(_storageDrive.Root); + } + + public Task Download(FileItem item, string localTargetPath) + { + LogManager.Log($"Downloading remote firmware item '{item.Path}' to local path '{localTargetPath}'..."); + + bool aborted = false; + + FileSystemHandler handler = null; + StorageFileHandler storageHandler = null; + + handler = new FileSystemHandler(FileSystemHandlerType.FileDownload, item, localTargetPath, async () => + { + if (!aborted) + { + LogManager.Log($"Download aborted by user for '{item.Name}'. Aborting download..."); + + aborted = true; + try + { + LogManager.Log("Aborting download operation..."); + + await storageHandler.Cancel(); + + LogManager.Log($"Download operation for '{item.Name} 'aborted successfully."); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error aborting the download operation for '{item.Name}'."); + } + finally + { + handler.RaiseAborted(); + } + } + }); + + _activeHandlers.Add(handler); + + ThreadFactory.StartNew(async () => + { + FileStream fileStream = null; + + try + { + TaskCompletionSource completion = new TaskCompletionSource(); + + fileStream = new FileStream(localTargetPath, FileMode.Create); + storageHandler = await _manager.DownloadFile(item.ToStorageItem() as StorageFile, fileStream); + storageHandler.Progress += (_, e) => + { + handler.InvalidateProgress(e.Current, e.Total); + }; + storageHandler.Canceled += (_, e) => + { + completion.SetException(new OperationCanceledException()); + }; + storageHandler.Failed += (_, ex) => + { + completion.SetException(ex); + }; + storageHandler.Completed += (_, e) => + { + LogManager.Log($"'{item.Name}' downloaded successfully."); + + try + { + fileStream?.Dispose(); + } + catch { } + handler.RaiseCompleted(); + completion.SetResult(true); + }; + + await completion.Task; + } + catch (OperationCanceledException) + { + handler.RaiseAborted(); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Download failed for '{item.Name}'."); + handler.RaiseFailed(ex); + } + finally + { + _activeHandlers.Remove(handler); + try + { + fileStream?.Dispose(); + } + catch { } + } + }); + + return Task.FromResult(handler); + } + + public Task Upload(string localSourcePath, string remoteTargetPath) + { + LogManager.Log($"Uploading file '{localSourcePath}' to remote path '{remoteTargetPath}'..."); + + bool aborted = false; + + FileSystemHandler handler = null; + StorageFileHandler storageHandler = null; + var item = new FileItem() { Path = localSourcePath }; + + handler = new FileSystemHandler(FileSystemHandlerType.FileUpload, item, remoteTargetPath, async () => + { + if (!aborted) + { + LogManager.Log($"Upload aborted by user for '{item.Name}'. Aborting download..."); + + aborted = true; + try + { + LogManager.Log("Aborting upload operation..."); + + await storageHandler.Cancel(); + + LogManager.Log($"Upload operation for '{item.Name} 'aborted successfully."); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error aborting the upload operation for '{item.Name}'."); + } + finally + { + handler.RaiseAborted(); + } + } + }); + + _activeHandlers.Add(handler); + + ThreadFactory.StartNew(async () => + { + FileStream fileStream = null; + + try + { + TaskCompletionSource completion = new TaskCompletionSource(); + + fileStream = new FileStream(localSourcePath, FileMode.Open); + storageHandler = await _manager.UploadFile(remoteTargetPath, fileStream); + storageHandler.Progress += (_, e) => + { + handler.InvalidateProgress(e.Current, e.Total); + }; + storageHandler.Canceled += (_, e) => + { + completion.SetException(new OperationCanceledException()); + }; + storageHandler.Failed += (_, ex) => + { + completion.SetException(ex); + }; + storageHandler.Completed += (_, e) => + { + LogManager.Log($"'{item.Name}' uploaded successfully."); + try + { + fileStream?.Dispose(); + } + catch { } + handler.RaiseCompleted(); + completion.SetResult(true); + }; + + await completion.Task; + } + catch (OperationCanceledException) + { + handler.RaiseAborted(); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Upload failed for '{item.Name}'."); + handler.RaiseFailed(ex); + } + finally + { + _activeHandlers.Remove(handler); + try + { + fileStream?.Dispose(); + } + catch { } + } + }); + + return Task.FromResult(handler); + } + + public Task Delete(FileSystemItem item) + { + try + { + return _manager.DeleteItem(item.ToStorageItem()); + } + catch (Exception ex) + { + throw LogManager.Log(ex, $"Error deleting firmware file system item '{item.Path}'."); + } + } + + public async Task CreateFolder(FileSystemItem parent, string folderName) + { + try + { + String remotePath = Path.Combine(parent.Path, folderName); + await _manager.CreateFolder(remotePath); + var storageFolder = await _manager.GetFolder(remotePath); + return storageFolder.ToFileSystemItem() as FolderItem; + } + catch (Exception ex) + { + throw LogManager.Log(ex, $"Error creating folder '{folderName}' on remote firmware device."); + } + } + } + + internal static class ExtensionMethods + { + internal static FileSystemItem ToFileSystemItem(this StorageItem storageItem) + { + FileSystemItem item = null; + + if (storageItem.GetType() == typeof(StorageDrive)) + { + item = new DriveItem(); + (item as DriveItem).Path = (storageItem as StorageDrive).Root; + (item as DriveItem).Label = "Root"; + (item as DriveItem).DriveType = System.IO.DriveType.Fixed; + } + else if (storageItem.GetType() == typeof(StorageFolder)) + { + item = new FolderItem(); + (item as FolderItem).Path = (storageItem as StorageFolder).Path; + (item as FolderItem).Items = (storageItem as StorageFolder).Items.Select(x => x.ToFileSystemItem()).ToObservableCollection(); + (item as FolderItem).IsRoot = (item as FolderItem).Path.Length == 1; + } + else if (storageItem.GetType() == typeof(StorageFile)) + { + item = new FileItem(); + (item as FileItem).Path = (storageItem as StorageFile).Path; + (item as FileItem).Size = (storageItem as StorageFile).Length; + } + + item.DateCreated = storageItem.LastModified; + item.DateCreated = storageItem.LastModified; + + return item; + } + + internal static StorageItem ToStorageItem(this FileSystemItem fileSystemItem) + { + StorageItem item = null; + + if (fileSystemItem.GetType() == typeof(DriveItem)) + { + item = new StorageDrive(); + (item as StorageDrive).Root = (fileSystemItem as DriveItem).Path; + } + else if (fileSystemItem.GetType() == typeof(FolderItem)) + { + item = new StorageFolder(); + (item as StorageFolder).Path = (fileSystemItem as FolderItem).Path; + (item as StorageFolder).Items = new ReadOnlyCollection((fileSystemItem as FolderItem).Items.Select(x => x.ToStorageItem()).ToList()); + (item as StorageFolder).LastModified = (fileSystemItem as FolderItem).DateModified; + (item as StorageFolder).Attribute = PMR.IO.FileAttribute.Directory; + } + else if (fileSystemItem.GetType() == typeof(FileItem)) + { + item = new StorageFile(); + (item as StorageFile).Path = (fileSystemItem as FileItem).Path; + (item as StorageFile).Length = (fileSystemItem as FileItem).Size; + (item as StorageFile).LastModified = (fileSystemItem as FileItem).DateModified; + (item as StorageFile).Attribute = PMR.IO.FileAttribute.Archive; + } + + return item; + } + } +} 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 ea997dcf7..31a2ec203 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 @@ -162,6 +162,7 @@ + @@ -441,6 +442,10 @@ {8cffa4fc-f46f-475d-a270-dafbfb532bc8} Tango.FSE.Diagnostics + + {7cb96d74-8b71-4a81-b4e1-6de7bfca6174} + Tango.FSE.Firmware + {866b916a-207c-43f0-b403-7c4a820c2e11} Tango.FSE.PPCConsole diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs index bd012aea0..e01883361 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs @@ -48,6 +48,8 @@ using Tango.FSE.Common.BugReporting; using Tango.FSE.UI.BugReporting; using Tango.FSE.Common.RemoteUpgrade; using Tango.FSE.UI.RemoteUpgrade; +using Tango.FSE.Common.Firmware; +using Tango.FSE.UI.Firmware; namespace Tango.FSE.UI { @@ -77,6 +79,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); + TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); //TangoIOC.Default.Unregister(); @@ -106,6 +109,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); + TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); diff --git a/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs b/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs index 0a7fe8ddc..58d0772f5 100644 --- a/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs +++ b/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs @@ -305,6 +305,14 @@ namespace Tango.FileSystem public static readonly DependencyProperty SelectionModeProperty = DependencyProperty.Register("SelectionMode", typeof(SelectionMode), typeof(FileExplorerControl), new PropertyMetadata(SelectionMode.Extended)); + public bool AllowFolderDownload + { + get { return (bool)GetValue(AllowFolderDownloadProperty); } + set { SetValue(AllowFolderDownloadProperty, value); } + } + public static readonly DependencyProperty AllowFolderDownloadProperty = + DependencyProperty.Register("AllowFolderDownload", typeof(bool), typeof(FileExplorerControl), new PropertyMetadata(true)); + static FileExplorerControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(FileExplorerControl), new FrameworkPropertyMetadata(typeof(FileExplorerControl))); @@ -369,7 +377,7 @@ namespace Tango.FileSystem DownloadCommand?.Execute(SelectedItems.ToList()); - }, () => SelectedItems != null && SelectedItems.Count > 0 && SelectedItems.All(x => x.Type != FileSystemItemType.Drive)); + }, () => SelectedItems != null && SelectedItems.Count > 0 && SelectedItems.All(x => x.Type != FileSystemItemType.Drive && (AllowFolderDownload || x.Type == FileSystemItemType.File))); OpenCommand = new RelayCommand(() => { diff --git a/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs b/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs index 558251f3c..c78a11732 100644 --- a/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs +++ b/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs @@ -84,5 +84,26 @@ namespace Tango.FileSystem return item; } + + public String GetParent() + { + if (Path == "/") return null; + + String root = System.IO.Path.GetPathRoot(Path); + var parent = Directory.GetParent(Path); + + if (root == "\\") + { + return parent.FullName.Replace(parent.Root.FullName, "/").Replace("\\", "/"); + } + else if (parent != null) + { + return parent.FullName; + } + else + { + return null; + } + } } } diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs index 456a5d5a5..a2ad9f9c9 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs @@ -413,12 +413,25 @@ namespace Tango.Integration.ExternalBridge if (e.Container.Type != MessageType.GenericRequest) //Handle standard PMR messages. { var handler = _requestHandlers[e.Container.Type.ToString()]; - handler.Method.Invoke(handler.Handler, new object[] + + if (handler.Method.ReturnType == typeof(Task)) { - message, - e.Container.Token, - sender, - }); + ((Task)handler.Method.Invoke(handler.Handler, new object[] + { + message, + e.Container.Token, + sender, + })).Wait(); + } + else + { + handler.Method.Invoke(handler.Handler, new object[] + { + message, + e.Container.Token, + sender, + }); + } } else //Handle GenericRequest with inner JSON formated generic message. { @@ -426,11 +439,11 @@ namespace Tango.Integration.ExternalBridge try { - if (_requestHandlers.ContainsKey(genericType.Name)) + if (_requestHandlers.ContainsKey(genericType.FullName)) { var innerMessage = GenericMessageSerializer.DeserializeFromByteString(genericType, (message as GenericRequest).Data); - var handler = _requestHandlers[genericType.Name]; + var handler = _requestHandlers[genericType.FullName]; if (handler.LoggingMode == RequestHandlerLoggingMode.LogRequestName || handler.LoggingMode == RequestHandlerLoggingMode.LogRequestNameAndContent) { @@ -479,6 +492,11 @@ namespace Tango.Integration.ExternalBridge catch (Exception ex) { LogManager.Log(ex, $"An error occurred while trying or invoking an external bridge request handler for '{e.Container.Type}'."); + try + { + (sender as ITransporter).SendErrorResponse(ex.GetFirstIfAggregate(), e.Container.Token); + } + catch { } } }); } @@ -723,7 +741,7 @@ namespace Tango.Integration.ExternalBridge var att = method.GetCustomAttribute(); if (att != null) { - _requestHandlers.Add(att.Type.Name, new RequestHandler() + _requestHandlers.Add(att.Type is IMessage ? att.Type.Name : att.Type.FullName, new RequestHandler() { Handler = handler, Method = method, diff --git a/Software/Visual_Studio/Tango.Integration/Storage/StorageDrive.cs b/Software/Visual_Studio/Tango.Integration/Storage/StorageDrive.cs index 28f390bc9..91dce12f5 100644 --- a/Software/Visual_Studio/Tango.Integration/Storage/StorageDrive.cs +++ b/Software/Visual_Studio/Tango.Integration/Storage/StorageDrive.cs @@ -7,7 +7,7 @@ using Tango.Core; namespace Tango.Integration.Storage { - public class StorageDrive : ExtendedObject + public class StorageDrive : StorageItem { public long Capacity { get; set; } public long FreeSpace { get; set; } diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 191743707..569f72726 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -373,6 +373,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PPC.Shared", "PPC\Tan EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.FSE.Upgrade", "FSE\Modules\Tango.FSE.Upgrade\Tango.FSE.Upgrade.csproj", "{0C0B24CB-79AF-4253-AAC3-B2BADF034675}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.FSE.Firmware", "FSE\Modules\Tango.FSE.Firmware\Tango.FSE.Firmware.csproj", "{7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -3466,6 +3468,26 @@ Global {0C0B24CB-79AF-4253-AAC3-B2BADF034675}.Release|x64.Build.0 = Release|Any CPU {0C0B24CB-79AF-4253-AAC3-B2BADF034675}.Release|x86.ActiveCfg = Release|Any CPU {0C0B24CB-79AF-4253-AAC3-B2BADF034675}.Release|x86.Build.0 = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|ARM.ActiveCfg = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|ARM.Build.0 = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|ARM64.Build.0 = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|x64.ActiveCfg = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|x64.Build.0 = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|x86.ActiveCfg = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Debug|x86.Build.0 = Debug|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|Any CPU.Build.0 = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|ARM.ActiveCfg = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|ARM.Build.0 = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|ARM64.ActiveCfg = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|ARM64.Build.0 = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|x64.ActiveCfg = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|x64.Build.0 = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|x86.ActiveCfg = Release|Any CPU + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3590,14 +3612,15 @@ Global {A07E6CB4-0132-4EB1-9A38-C8C057884DC2} = {EC62BC9C-F2FE-4333-B7E4-110E38D43958} {208C8BD8-72C6-4E3C-ACAA-351091A2ACC7} = {C81ED1A3-D18C-4D80-A8F5-061994A14A60} {0C0B24CB-79AF-4253-AAC3-B2BADF034675} = {4EE6DBA1-71BC-49E2-8DC7-266487E61050} + {7CB96D74-8B71-4A81-B4E1-6DE7BFCA6174} = {4EE6DBA1-71BC-49E2-8DC7-266487E61050} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} - BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear - BuildVersion_UpdateAssemblyVersion = True - BuildVersion_UpdateFileVersion = False - BuildVersion_StartDate = 2000/1/1 - BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs BuildVersion_UseGlobalSettings = False + BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs + BuildVersion_StartDate = 2000/1/1 + BuildVersion_UpdateFileVersion = False + BuildVersion_UpdateAssemblyVersion = True + BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear + SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} EndGlobalSection EndGlobal -- cgit v1.3.1