diff --git a/src/SharpDockerizer.AppLayer/Services/Project/ProjectDataExporter.cs b/src/SharpDockerizer.AppLayer/Services/Project/ProjectDataExporter.cs index d5ed73d..922063e 100644 --- a/src/SharpDockerizer.AppLayer/Services/Project/ProjectDataExporter.cs +++ b/src/SharpDockerizer.AppLayer/Services/Project/ProjectDataExporter.cs @@ -24,7 +24,7 @@ public async Task GetProjectData(string path) var projectName = Path.GetFileNameWithoutExtension(path); - + var isAspNetProject = xml.Root.Attribute("Sdk")?.Value == "Microsoft.NET.Sdk.Web"; var targetFramework = xml.Root.Descendants().Where(element => element.Name == "TargetFramework" || element.Name == "TargetFrameworks").FirstOrDefault(); var version = targetFramework is not null ? ParseDotNetVersion(targetFramework.Value) : null; @@ -33,7 +33,8 @@ public async Task GetProjectData(string path) ProjectName = projectName, DotNetVersion = version, AbsolutePathToProjFile = path, - RelativePath = relativePath + RelativePath = relativePath, + IsAspNetProject = isAspNetProject }; Log.Information($"Project data: {projectData}"); diff --git a/src/SharpDockerizer.AvaloniaUI/Properties/Resources.Designer.cs b/src/SharpDockerizer.AvaloniaUI/Properties/Resources.Designer.cs index 9a34956..8cc5596 100644 --- a/src/SharpDockerizer.AvaloniaUI/Properties/Resources.Designer.cs +++ b/src/SharpDockerizer.AvaloniaUI/Properties/Resources.Designer.cs @@ -1,9 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. +// Этот код создан программой. +// Исполняемая версия:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае +// повторной генерации кода. // //------------------------------------------------------------------------------ @@ -12,12 +13,12 @@ namespace SharpDockerizer.AvaloniaUI.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. + // Этот класс создан автоматически классом StronglyTypedResourceBuilder + // с помощью такого средства, как ResGen или Visual Studio. + // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen + // с параметром /str или перестройте свой проект VS. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -32,7 +33,7 @@ internal Resources() { } /// - /// Returns the cached ResourceManager instance used by this class. + /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { @@ -46,8 +47,8 @@ internal Resources() { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// Перезаписывает свойство CurrentUICulture текущего потока для всех + /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { @@ -60,7 +61,7 @@ internal Resources() { } /// - /// Looks up a localized string similar to About. + /// Ищет локализованную строку, похожую на About. /// public static string AboutMenu { get { @@ -69,7 +70,7 @@ public static string AboutMenu { } /// - /// Looks up a localized string similar to Add new NuGet source. + /// Ищет локализованную строку, похожую на Add new NuGet source. /// public static string AddNuGetSource { get { @@ -78,7 +79,7 @@ public static string AddNuGetSource { } /// - /// Looks up a localized string similar to Add Port. + /// Ищет локализованную строку, похожую на Add Port. /// public static string AddPort { get { @@ -87,7 +88,7 @@ public static string AddPort { } /// - /// Looks up a localized string similar to Authentication Required?. + /// Ищет локализованную строку, похожую на Authentication Required?. /// public static string AuthenticationRequired { get { @@ -96,7 +97,7 @@ public static string AuthenticationRequired { } /// - /// Looks up a localized string similar to Choose folder, where Dockerfile will be saved. + /// Ищет локализованную строку, похожую на Choose folder, where Dockerfile will be saved. /// public static string ChooseSaveFolder { get { @@ -105,7 +106,7 @@ public static string ChooseSaveFolder { } /// - /// Looks up a localized string similar to Choose .sln file. + /// Ищет локализованную строку, похожую на Choose .sln file. /// public static string ChooseSlnFile { get { @@ -114,7 +115,7 @@ public static string ChooseSlnFile { } /// - /// Looks up a localized string similar to Copy To Clipboard. + /// Ищет локализованную строку, похожую на Copy To Clipboard. /// public static string CopyToClipboard { get { @@ -123,7 +124,7 @@ public static string CopyToClipboard { } /// - /// Looks up a localized string similar to Exit. + /// Ищет локализованную строку, похожую на Exit. /// public static string Exit { get { @@ -132,7 +133,7 @@ public static string Exit { } /// - /// Looks up a localized string similar to Exposed Ports. + /// Ищет локализованную строку, похожую на Exposed Ports. /// public static string ExposedPorts { get { @@ -141,7 +142,7 @@ public static string ExposedPorts { } /// - /// Looks up a localized string similar to File. + /// Ищет локализованную строку, похожую на File. /// public static string FileMenu { get { @@ -150,7 +151,7 @@ public static string FileMenu { } /// - /// Looks up a localized string similar to Generated Dockerfile. + /// Ищет локализованную строку, похожую на Generated Dockerfile. /// public static string GeneratedDockerfileTitle { get { @@ -159,7 +160,7 @@ public static string GeneratedDockerfileTitle { } /// - /// Looks up a localized string similar to Generate Dockerfile. + /// Ищет локализованную строку, похожую на Generate Dockerfile. /// public static string GenerateDockerfileButton { get { @@ -168,7 +169,7 @@ public static string GenerateDockerfileButton { } /// - /// Looks up a localized string similar to Open GitHub Page. + /// Ищет локализованную строку, похожую на Open GitHub Page. /// public static string GitHubButton { get { @@ -177,7 +178,7 @@ public static string GitHubButton { } /// - /// Looks up a localized string similar to Language. + /// Ищет локализованную строку, похожую на Language. /// public static string LanguageLabel { get { @@ -186,7 +187,7 @@ public static string LanguageLabel { } /// - /// Looks up a localized string similar to Load a .NET solution to view included projects.. + /// Ищет локализованную строку, похожую на Load a .NET solution to view included projects.. /// public static string LoadSolutionFiller { get { @@ -195,7 +196,7 @@ public static string LoadSolutionFiller { } /// - /// Looks up a localized string similar to NuGet Sources. + /// Ищет локализованную строку, похожую на NuGet Sources. /// public static string NuGetSources { get { @@ -204,7 +205,7 @@ public static string NuGetSources { } /// - /// Looks up a localized string similar to Open Solution. + /// Ищет локализованную строку, похожую на Open Solution. /// public static string OpenSolution { get { @@ -213,7 +214,7 @@ public static string OpenSolution { } /// - /// Looks up a localized string similar to Port. + /// Ищет локализованную строку, похожую на Port. /// public static string Port { get { @@ -222,7 +223,7 @@ public static string Port { } /// - /// Looks up a localized string similar to Recently Opened. + /// Ищет локализованную строку, похожую на Recently Opened. /// public static string RecentlyOpened { get { @@ -231,7 +232,7 @@ public static string RecentlyOpened { } /// - /// Looks up a localized string similar to Refresh Solution Projects. + /// Ищет локализованную строку, похожую на Refresh Solution Projects. /// public static string RefreshButton { get { @@ -240,7 +241,7 @@ public static string RefreshButton { } /// - /// Looks up a localized string similar to Remove NuGet source. + /// Ищет локализованную строку, похожую на Remove NuGet source. /// public static string RemoveNuGetSource { get { @@ -249,7 +250,7 @@ public static string RemoveNuGetSource { } /// - /// Looks up a localized string similar to Remove Port. + /// Ищет локализованную строку, похожую на Remove Port. /// public static string RemovePort { get { @@ -258,7 +259,7 @@ public static string RemovePort { } /// - /// Looks up a localized string similar to Restart App. + /// Ищет локализованную строку, похожую на Restart App. /// public static string RestartAppButton { get { @@ -267,7 +268,7 @@ public static string RestartAppButton { } /// - /// Looks up a localized string similar to Requires app restart to fully take effect.. + /// Ищет локализованную строку, похожую на Requires app restart to fully take effect.. /// public static string RestartRequiredWarningText { get { @@ -276,7 +277,7 @@ public static string RestartRequiredWarningText { } /// - /// Looks up a localized string similar to Save To.... + /// Ищет локализованную строку, похожую на Save To.... /// public static string SaveTo { get { @@ -285,7 +286,7 @@ public static string SaveTo { } /// - /// Looks up a localized string similar to Save To Project Folder. + /// Ищет локализованную строку, похожую на Save To Project Folder. /// public static string SaveToProjectFolder { get { @@ -294,7 +295,16 @@ public static string SaveToProjectFolder { } /// - /// Looks up a localized string similar to Settings. + /// Ищет локализованную строку, похожую на Search. + /// + public static string SearchSolutionText { + get { + return ResourceManager.GetString("SearchSolutionText", resourceCulture); + } + } + + /// + /// Ищет локализованную строку, похожую на Settings. /// public static string Settings { get { @@ -303,7 +313,16 @@ public static string Settings { } /// - /// Looks up a localized string similar to Solution Viewer. + /// Ищет локализованную строку, похожую на Show all projects. + /// + public static string ShowAllProjectsLabel { + get { + return ResourceManager.GetString("ShowAllProjectsLabel", resourceCulture); + } + } + + /// + /// Ищет локализованную строку, похожую на Solution Viewer. /// public static string SolutionViewerTitle { get { @@ -312,7 +331,7 @@ public static string SolutionViewerTitle { } /// - /// Looks up a localized string similar to Source Name. + /// Ищет локализованную строку, похожую на Source Name. /// public static string SourceName { get { @@ -321,7 +340,7 @@ public static string SourceName { } /// - /// Looks up a localized string similar to Tools. + /// Ищет локализованную строку, похожую на Tools. /// public static string Tools { get { @@ -330,7 +349,7 @@ public static string Tools { } /// - /// Looks up a localized string similar to URL. + /// Ищет локализованную строку, похожую на URL. /// public static string URL { get { @@ -339,7 +358,7 @@ public static string URL { } /// - /// Looks up a localized string similar to Username. + /// Ищет локализованную строку, похожую на Username. /// public static string Username { get { diff --git a/src/SharpDockerizer.AvaloniaUI/Properties/Resources.resx b/src/SharpDockerizer.AvaloniaUI/Properties/Resources.resx index 405a8f4..ab1b693 100644 --- a/src/SharpDockerizer.AvaloniaUI/Properties/Resources.resx +++ b/src/SharpDockerizer.AvaloniaUI/Properties/Resources.resx @@ -213,4 +213,10 @@ Requires app restart to fully take effect. + + Search + + + Show all projects + \ No newline at end of file diff --git a/src/SharpDockerizer.AvaloniaUI/Properties/Resources.ru.resx b/src/SharpDockerizer.AvaloniaUI/Properties/Resources.ru.resx index 2a5db2f..6591ea6 100644 --- a/src/SharpDockerizer.AvaloniaUI/Properties/Resources.ru.resx +++ b/src/SharpDockerizer.AvaloniaUI/Properties/Resources.ru.resx @@ -213,4 +213,10 @@ Для применения изменений требуется перезагрузка. + + Поиск + + + Показать все проекты + \ No newline at end of file diff --git a/src/SharpDockerizer.AvaloniaUI/ViewModels/SolutionViewerViewModel.cs b/src/SharpDockerizer.AvaloniaUI/ViewModels/SolutionViewerViewModel.cs index e1903a2..be268eb 100644 --- a/src/SharpDockerizer.AvaloniaUI/ViewModels/SolutionViewerViewModel.cs +++ b/src/SharpDockerizer.AvaloniaUI/ViewModels/SolutionViewerViewModel.cs @@ -4,6 +4,7 @@ using SharpDockerizer.AppLayer.Contracts; using SharpDockerizer.AppLayer.Events; using SharpDockerizer.Core.Models; +using System; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; @@ -57,7 +58,37 @@ partial void OnSelectedProjectChanged(ProjectData value) /// /// Projects in .NET solution /// - public ObservableCollection SolutionProjects { get; set; } = new ObservableCollection(); + private ObservableCollection SolutionProjects { get; set; } = new ObservableCollection(); + + /// + /// Projects in .NET solution + /// + public ObservableCollection DisplayedSolutionProjects { get; set; } = new ObservableCollection(); + + + /// + /// Show all projects or only ASP.NET + /// + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(DisplayedSolutionProjects))] + private bool _showAllProjects = false; + + partial void OnShowAllProjectsChanged(bool value) + { + ApplyConditionsToDisplayedProjects(); + } + + /// + /// Search entry. Used to filter projects. + /// + [ObservableProperty] + + private string _searchString = string.Empty; + + partial void OnSearchStringChanged(string? oldValue, string newValue) + { + ApplyConditionsToDisplayedProjects(); + } #endregion @@ -76,6 +107,8 @@ private void SolutionLoadedHandler(object recipient, SolutionLoadedEvent message SolutionProjects.Add(project); } IsSolutionLoaded = true; + + ApplyConditionsToDisplayedProjects(); } else { @@ -115,6 +148,8 @@ private void SolutionRefreshedHandler(object recipient, SolutionRefreshedEvent m i--; } } + + ApplyConditionsToDisplayedProjects(); } #endregion @@ -131,4 +166,61 @@ public async Task RefreshSolution() } #endregion + + /// + /// Prepares a list of projects to be displayed in UI. + /// + /// + private void ApplyConditionsToDisplayedProjects() + { + // Create query + var displayedQuery = SolutionProjects.AsQueryable(); + if (!string.IsNullOrWhiteSpace(SearchString)) + { + displayedQuery = displayedQuery.Where(x => x.ProjectName.Contains(SearchString, StringComparison.OrdinalIgnoreCase)); + } + if (!ShowAllProjects) + { + displayedQuery = displayedQuery.Where(x => x.IsAspNetProject); + } + else + { + displayedQuery = displayedQuery.OrderByDescending(x => x.IsAspNetProject); + } + + // Apply query and get data + var result = displayedQuery.ToList(); + + // Update displayed list + foreach (ProjectData newProjectData in result) + { + // Check if such project already exists + var existingData = DisplayedSolutionProjects.Where(x => x.ProjectName == newProjectData.ProjectName).FirstOrDefault(); + if (existingData is not null) + { + // Update existing reference. + // By doing that, we don't break selected project reference. + existingData.UpdateWithData(newProjectData); + } + else + { + // This is a new project, so add it to solution data. + DisplayedSolutionProjects.Add(newProjectData); + } + } + + // Remove deleted projects + for (int i = 0; i < DisplayedSolutionProjects.Count; i++) + { + ProjectData? existingData = DisplayedSolutionProjects[i]; + if (!result.Where(newProj => newProj.ProjectName == existingData.ProjectName).Any()) + { + DisplayedSolutionProjects.RemoveAt(i); + i--; + } + } + + + OnPropertyChanged(nameof(DisplayedSolutionProjects)); + } } diff --git a/src/SharpDockerizer.AvaloniaUI/Views/SolutionViewer.axaml b/src/SharpDockerizer.AvaloniaUI/Views/SolutionViewer.axaml index 0612a4f..2f9997a 100644 --- a/src/SharpDockerizer.AvaloniaUI/Views/SolutionViewer.axaml +++ b/src/SharpDockerizer.AvaloniaUI/Views/SolutionViewer.axaml @@ -9,46 +9,87 @@ mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="650" x:Class="SharpDockerizer.AvaloniaUI.Views.SolutionViewer" xmlns:mati="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"> - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - + ItemsSource="{Binding DisplayedSolutionProjects}" SelectedItem="{Binding SelectedProject}"> + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/SharpDockerizer.Core/Models/ProjectData.cs b/src/SharpDockerizer.Core/Models/ProjectData.cs index 8ef60f4..de54bf5 100644 --- a/src/SharpDockerizer.Core/Models/ProjectData.cs +++ b/src/SharpDockerizer.Core/Models/ProjectData.cs @@ -19,6 +19,11 @@ public class ProjectData /// public required string RelativePath { get; set; } + /// + /// If ASP.NET SDK usage is detected in project - this property will be ; + /// + public required bool IsAspNetProject { get; set; } + /// /// Checks if all properties of ProjectData are equal. /// @@ -26,12 +31,13 @@ public override bool Equals(object? obj) { if (obj is ProjectData projectData) { - return ProjectName == projectData.ProjectName - && AbsolutePathToProjFile== projectData.AbsolutePathToProjFile + return ProjectName == projectData.ProjectName + && AbsolutePathToProjFile == projectData.AbsolutePathToProjFile && DotNetVersion == projectData.DotNetVersion - && RelativePath == projectData.RelativePath; + && RelativePath == projectData.RelativePath + && IsAspNetProject == projectData.IsAspNetProject; } - + return false; } @@ -44,6 +50,7 @@ public void UpdateWithData(ProjectData projectData) ProjectName = projectData.ProjectName; AbsolutePathToProjFile = projectData.AbsolutePathToProjFile; RelativePath = projectData.RelativePath; - DotNetVersion= projectData.DotNetVersion; + DotNetVersion = projectData.DotNetVersion; + IsAspNetProject = projectData.IsAspNetProject; } }