Skip to content

Commit a0b572b

Browse files
committed
Feature: Profile filter
1 parent f0e6884 commit a0b572b

22 files changed

+2727
-317
lines changed

Source/NETworkManager/ProfileDialogManager.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
using NETworkManager.Views;
1010
using System;
1111
using System.Collections.Generic;
12+
using System.Diagnostics;
1213
using System.Security;
1314
using System.Threading.Tasks;
1415
using System.Windows;
16+
using NETworkManager.Controls;
1517

1618
namespace NETworkManager;
1719

@@ -21,13 +23,18 @@ public static class ProfileDialogManager
2123

2224
private static ProfileInfo ParseProfileInfo(ProfileViewModel instance)
2325
{
26+
foreach (var tag in instance.TagsCollection)
27+
{
28+
Debug.WriteLine(tag);
29+
}
30+
2431
return new ProfileInfo
2532
{
2633
Name = instance.Name.Trim(),
2734
Host = instance.Host.Trim(),
2835
Description = instance.Description?.Trim(),
2936
Group = instance.Group.Trim(),
30-
TagsCollection = instance.TagsCollection,
37+
TagsCollection = new ObservableSetCollection<string> (instance.TagsCollection),
3138

3239
// Network Interface
3340
NetworkInterface_Enabled = instance.NetworkInterface_Enabled,

Source/NETworkManager/ViewModels/AWSSessionManagerHostViewModel.cs

Lines changed: 138 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,70 @@ public bool IsSearching
239239
OnPropertyChanged();
240240
}
241241
}
242+
243+
private bool _profileFilterIsOpen;
244+
245+
public bool ProfileFilterIsOpen
246+
{
247+
get => _profileFilterIsOpen;
248+
set
249+
{
250+
if (value == _profileFilterIsOpen)
251+
return;
252+
253+
_profileFilterIsOpen = value;
254+
OnPropertyChanged();
255+
}
256+
}
257+
258+
public ICollectionView ProfileFilterTagsView { get; }
259+
260+
private ObservableCollection<ProfileFilterTagsInfo> ProfileFilterTags { get; } = [];
261+
262+
private bool _profileFilterTagsMatchAny = GlobalStaticConfiguration.Profile_TagsMatchAny;
263+
264+
public bool ProfileFilterTagsMatchAny
265+
{
266+
get => _profileFilterTagsMatchAny;
267+
set
268+
{
269+
if (value == _profileFilterTagsMatchAny)
270+
return;
271+
272+
_profileFilterTagsMatchAny = value;
273+
OnPropertyChanged();
274+
}
275+
}
276+
277+
private bool _profileFilterTagsMatchAll;
278+
279+
public bool ProfileFilterTagsMatchAll
280+
{
281+
get => _profileFilterTagsMatchAll;
282+
set
283+
{
284+
if (value == _profileFilterTagsMatchAll)
285+
return;
286+
287+
_profileFilterTagsMatchAll = value;
288+
OnPropertyChanged();
289+
}
290+
}
291+
292+
private bool _isProfileFilterSet;
293+
294+
public bool IsProfileFilterSet
295+
{
296+
get => _isProfileFilterSet;
297+
set
298+
{
299+
if (value == _isProfileFilterSet)
300+
return;
301+
302+
_isProfileFilterSet = value;
303+
OnPropertyChanged();
304+
}
305+
}
242306

243307
private bool _canProfileWidthChange = true;
244308
private double _tempProfileWidth;
@@ -333,7 +397,12 @@ public AWSSessionManagerHostViewModel(IDialogCoordinator instance)
333397
TabItems = [];
334398

335399
// Profiles
336-
SetProfilesView();
400+
CreateTags();
401+
402+
ProfileFilterTagsView = CollectionViewSource.GetDefaultView(ProfileFilterTags);
403+
ProfileFilterTagsView.SortDescriptions.Add(new SortDescription(nameof(ProfileFilterTagsInfo.Name), ListSortDirection.Ascending));
404+
405+
SetProfilesView(new ProfileFilterInfo());
337406

338407
ProfileManager.OnProfilesUpdated += ProfileManager_OnProfilesUpdated;
339408

@@ -520,6 +589,36 @@ private void ClearSearchAction()
520589
{
521590
Search = string.Empty;
522591
}
592+
593+
public ICommand OpenProfileFilterCommand => new RelayCommand(_ => OpenProfileFilterAction());
594+
595+
private void OpenProfileFilterAction()
596+
{
597+
ProfileFilterIsOpen = true;
598+
}
599+
600+
public ICommand ApplyProfileFilterCommand => new RelayCommand(_ => ApplyProfileFilterAction());
601+
602+
private void ApplyProfileFilterAction()
603+
{
604+
RefreshProfiles();
605+
606+
IsProfileFilterSet = true;
607+
ProfileFilterIsOpen = false;
608+
}
609+
610+
public ICommand ClearProfileFilterCommand => new RelayCommand(_ => ClearProfileFilterAction());
611+
612+
private void ClearProfileFilterAction()
613+
{
614+
foreach (var tag in ProfileFilterTags)
615+
tag.IsSelected = false;
616+
617+
RefreshProfiles();
618+
619+
IsProfileFilterSet = false;
620+
ProfileFilterIsOpen = false;
621+
}
523622

524623
public ICommand OpenDocumentationCommand
525624
{
@@ -986,36 +1085,42 @@ public void OnProfileLoaded()
9861085
SyncAllInstanceIDsFromAWS().ConfigureAwait(false);
9871086
}
9881087

989-
private void SetProfilesView(ProfileInfo profile = null)
1088+
private void CreateTags()
9901089
{
991-
Profiles = new CollectionViewSource
992-
{
993-
Source = ProfileManager.Groups.SelectMany(x => x.Profiles).Where(x => x.AWSSessionManager_Enabled)
994-
.OrderBy(x => x.Group).ThenBy(x => x.Name)
995-
}.View;
1090+
var tags = ProfileManager.Groups.SelectMany(x => x.Profiles).Where(x => x.AWSSessionManager_Enabled).SelectMany(x => x.TagsCollection).Distinct().ToList();
9961091

997-
Profiles.GroupDescriptions.Add(new PropertyGroupDescription(nameof(ProfileInfo.Group)));
1092+
var tagSet = new HashSet<string>(tags);
9981093

999-
Profiles.Filter = o =>
1094+
for (var i = ProfileFilterTags.Count - 1; i >= 0; i--)
10001095
{
1001-
if (string.IsNullOrEmpty(Search))
1002-
return true;
1003-
1004-
if (o is not ProfileInfo info)
1005-
return false;
1096+
if (!tagSet.Contains(ProfileFilterTags[i].Name))
1097+
ProfileFilterTags.RemoveAt(i);
1098+
}
10061099

1007-
var search = Search.Trim();
1100+
var existingTagNames = new HashSet<string>(ProfileFilterTags.Select(ft => ft.Name));
10081101

1009-
// Search by: Tag=xxx (exact match, ignore case)
1010-
/*
1011-
if (search.StartsWith(ProfileManager.TagIdentifier, StringComparison.OrdinalIgnoreCase))
1012-
return !string.IsNullOrEmpty(info.Tags) && info.PingMonitor_Enabled && info.Tags.Replace(" ", "").Split(';').Any(str => search.Substring(ProfileManager.TagIdentifier.Length, search.Length - ProfileManager.TagIdentifier.Length).Equals(str, StringComparison.OrdinalIgnoreCase));
1013-
*/
1102+
foreach (var tag in tags.Where(tag => !existingTagNames.Contains(tag)))
1103+
{
1104+
ProfileFilterTags.Add(new ProfileFilterTagsInfo(false, tag));
1105+
}
1106+
}
1107+
1108+
private void SetProfilesView(ProfileFilterInfo filter, ProfileInfo profile = null)
1109+
{
1110+
Profiles = new CollectionViewSource
1111+
{
1112+
Source = ProfileManager.Groups.SelectMany(x => x.Profiles).Where(x => x.AWSSessionManager_Enabled && (
1113+
string.IsNullOrEmpty(filter.Search) || x.Name.IndexOf(filter.Search, StringComparison.Ordinal) > -1 || x.AWSSessionManager_InstanceID.IndexOf(filter.Search, StringComparison.Ordinal) > -1) && (
1114+
// If no tags are selected, show all profiles
1115+
(!filter.Tags.Any()) ||
1116+
// Any tag can match
1117+
(filter.TagsFilterMatch == ProfileFilterTagsMatch.Any && filter.Tags.Any(tag => x.TagsCollection.Contains(tag))) ||
1118+
// All tags must match
1119+
(filter.TagsFilterMatch == ProfileFilterTagsMatch.All && filter.Tags.All(tag => x.TagsCollection.Contains(tag))))
1120+
).OrderBy(x => x.Group).ThenBy(x => x.Name)
1121+
}.View;
10141122

1015-
// Search by: Name, AWSSessionManager_InstanceID
1016-
return info.Name.IndexOf(search, StringComparison.OrdinalIgnoreCase) > -1 ||
1017-
info.AWSSessionManager_InstanceID.IndexOf(search, StringComparison.OrdinalIgnoreCase) > -1;
1018-
};
1123+
Profiles.GroupDescriptions.Add(new PropertyGroupDescription(nameof(ProfileInfo.Group)));
10191124

10201125
// Set specific profile or first if null
10211126
SelectedProfile = null;
@@ -1032,7 +1137,12 @@ private void RefreshProfiles()
10321137
if (!_isViewActive)
10331138
return;
10341139

1035-
SetProfilesView(SelectedProfile);
1140+
SetProfilesView(new ProfileFilterInfo
1141+
{
1142+
Search = Search,
1143+
Tags = [.. ProfileFilterTags.Where(x => x.IsSelected).Select(x => x.Name)],
1144+
TagsFilterMatch = ProfileFilterTagsMatchAny ? ProfileFilterTagsMatch.Any : ProfileFilterTagsMatch.All
1145+
}, SelectedProfile);
10361146
}
10371147

10381148
public void OnProfileManagerDialogOpen()
@@ -1053,7 +1163,7 @@ private void WriteDefaultProfileToRegistry()
10531163
if (!IsExecutableConfigured)
10541164
return;
10551165

1056-
Log.Info("Write PowerShell profile to registry...");
1166+
Log.Debug("Write PowerShell profile to registry...");
10571167

10581168
PowerShell.WriteDefaultProfileToRegistry(
10591169
SettingsManager.Current.Appearance_Theme,
@@ -1111,6 +1221,8 @@ private void AWSSessionManager_AWSProfiles_CollectionChanged(object sender,
11111221

11121222
private void ProfileManager_OnProfilesUpdated(object sender, EventArgs e)
11131223
{
1224+
CreateTags();
1225+
11141226
RefreshProfiles();
11151227
}
11161228

0 commit comments

Comments
 (0)