using System.ComponentModel; using System.ComponentModel.Composition; using System.Threading.Tasks; using DTS.Common.Events; using GroupList.Model; using DTS.Common.Interface.Groups.GroupTemplateList; using DTS.Common.Enums.Groups.GroupList; using System.Collections.Generic; using System.Collections.ObjectModel; using System; using System.Collections.Specialized; using System.Linq; using DTS.Common.Events.Groups.GroupList; using DTS.Common.Interface.Groups.GroupList; using System.Windows; using DTS.Common.Storage; using DTS.Common.Interface.Groups; using Prism.Events; using Prism.Regions; using Unity; using DTS.Common.Interactivity; // ReSharper disable CheckNamespace // ReSharper disable MemberCanBePrivate.Global // ReSharper disable InconsistentNaming namespace GroupList { /// /// this class handles GroupList functionality /// [PartCreationPolicy(CreationPolicy.Shared)] public class GroupListViewModel : IGroupListViewModel { /// /// The GroupList view /// public IGroupListView View { get; set; } private IEventAggregator _eventAggregator { get; } private IRegionManager _regionManager; private IUnityContainer UnityContainer { get; } public InteractionRequest NotificationRequest { get; } public InteractionRequest ConfirmationRequest { get; } /// /// /// Occurs when a property value changes. /// public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #region constructors and initializers /// /// Creates a new instance of the GroupListViewModel /// /// /// The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed. /// The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other. /// The unityContainer. public GroupListViewModel(IGroupListView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer) { View = view; View.DataContext = this; NotificationRequest = new InteractionRequest(); ConfirmationRequest = new InteractionRequest(); _eventAggregator = eventAggregator; UnityContainer = unityContainer; _regionManager = regionManager; _eventAggregator.GetEvent().Subscribe(OnRaiseNotification); _eventAggregator.GetEvent() .Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true); SelectedGroupItems = new ObservableCollection(); } #endregion #region Methods public void ClearAllFilters() { _filterByField.Clear(); } public void MouseDoubleClick(int index) { if (index >= 0 && index < Groups.Length && SelectedGroupItems.Count == 1) { _eventAggregator.GetEvent().Publish(Groups[index].Id); } } public void Filter(string term) { CurrentSearchTerm = term; Sort(_sortField.ToString(), false); } public IGroup GetGroup(int? id, bool updateTags = true) { if (id >= 0) { if (updateTags) { //Update the Tags in case they were modified by a different user DTS.Common.Classes.Tags.TagsInstance.GetTagsInstance(DbOperations.TagsGet).UpdateList(DbOperations.TagsGet); } var groups = Group.GetAllGroups(id); if (groups.Any()) { return groups[0]; } } return new Group(); } public IGroup GetGroup(string displayName) { //Get all of the groups with this DisplayName. This consists of both embedded and non-embedded //if it was a pre-2.0 static Group or just the embedded, if it was a pre-2.0 Added Group. //If the Group was first created in 2.0, it may have both embedded and non-embedded or just embedded. var groups = Group.GetAllGroups(displayName); foreach (var group in groups) { if (!group.Embedded) { //Return the corresponding non-embedded Group return group; } } return null; } public IGroup[] GetGroups(int[] ids) { var allGroups = Group.GetAllGroups().ToList(); for (var i = allGroups.Count - 1; i >= 0; i--) { if (ids.Contains(allGroups[i].Id)) { continue; } allGroups.RemoveAt(i); } return allGroups.ToArray(); } public IGroup[] GetAllGroups() { var allGroups = Group.GetAllGroups(); return allGroups; } public void DeleteGroups(int[] ids) { try { foreach (var id in ids) { //Set any embedded Groups' that have the to-be-deleted //Group's Id as their StaticGroupId to null. var relatedEmbeddedGroups = Group.GetAllRelatedEmbeddedGroups(id); foreach (var embeddedGroup in relatedEmbeddedGroups) { Group.SetNullStaticGroupId(embeddedGroup); } Group.Delete(id); } var list = AllGroups.ToList(); for (var i = AllGroups.Length - 1; i >= 0; i--) { if (ids.Contains(AllGroups[i].Id)) { list.RemoveAt(i); } } AllGroups = list.ToArray(); Filter(CurrentSearchTerm); } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new PageErrorArg(new[] { ex.Message }, Page)); } } public IGroup CreateGroup() { return new Group(true); } public IGroup CreateGroup(System.Data.SqlClient.SqlDataReader reader, List includedHardwareStringList, List dasIdList) { return new Group(reader, includedHardwareStringList, dasIdList); } public IGroup CreateGroup(IGroupDbRecord groupRecord, List includedHardwareStringList, List dasIdList) { return new Group(groupRecord, includedHardwareStringList, dasIdList); } public IGroup CreateGroup(List includedHardwareStringList) { return new Group(includedHardwareStringList); } public void Filter(object tag, string term) { if (!Enum.TryParse((string)tag, out GroupFields field)) return; _filterByField[field] = term; _sortField = field; Filter(term); } public void OnSetActive(object page, bool groupTile, object o) { try { var currentUser = (DTS.Slice.Users.User)o; Page = page; var groups = Group.GetAllGroups().Where(@group => currentUser.Role == DTS.Slice.Users.User.DefaultRoles.Administrator || currentUser.TagCompatible(@group.TagIDs)).ToList(); if (groupTile) { AllGroups = groups.ToArray(); Task.Run(() => GetTestSetupListsAsync()); } else { AllGroups = groups.ToArray(); Sort(_sortField.ToString(), false); } } catch (Exception ex) { _eventAggregator.GetEvent().Publish(new PageErrorArg(new[] { ex.Message }, Page)); } } private void GetTestSetupListsAsync() { _eventAggregator.GetEvent().Publish(AppStatusArg.Busy); var groups = AllGroups.ToArray(); _eventAggregator.GetEvent().Publish(new ProgressBarEventArg() { ProgressBarText = $"Getting groups", SetText = true }); groups.AsParallel().ForAll(g => { _eventAggregator.GetEvent().Publish(new ProgressBarEventArg() { ProgressBarText = $"Getting group {g.DisplayName}", SetText = true }); g.SetTestSetupLists(); }); Application.Current.Dispatcher.Invoke(new Action(() => { Sort(_sortField.ToString(), false); })); _eventAggregator.GetEvent().Publish(new ProgressBarEventArg() { ProgressBarText = $"Waiting for user input", SetText = true }); _eventAggregator.GetEvent().Publish(AppStatusArg.Available); } public void Unset() { AllGroups = new IGroup[0]; Groups = new IGroup[0]; ClearAllFilters(); _eventAggregator.GetEvent() .Publish(new ListViewStatusArg(ListViewStatusArg.ListViewStatus.Unloaded, ListViewId)); } public void Sort(object o, bool bColumnClick) { if (!(o is string s)) { return; } if (!Enum.TryParse(s, out GroupFields tag)) { return; } if (bColumnClick) { if (tag != _sortField) { _sortField = tag; _sortAscending = true; } else { _sortAscending = !_sortAscending; } } _comparer.SortAscending = _sortAscending; _comparer.SortField = _sortField; var list = new List(); foreach (var group in AllGroups) { if (group.Filter(CurrentSearchTerm)) { if (GroupFilter(group)) { list.Add(group); } } } var originalList = list.ToList(); list.Sort(_comparer); //this doesn't seem right, should just use the _sortField and sort ascending //logic already present //if (originalList.SequenceEqual(list) && originalList.Count > 1 && // !(_comparer.SortAscending && _comparer.SortField == GroupFields.LastModified))//AllGroups already ordered by lastmodified, ascending //{ // //list was already in order. flip it for the user // _sortAscending = !_sortAscending; // _comparer.SortAscending = _sortAscending; // list.Sort(_comparer); //} Groups = list.ToArray(); OnPropertyChanged("Groups"); } private bool GroupFilter(IGroup group) { var fields = Enum.GetValues(typeof(GroupFields)).Cast().ToArray(); foreach (var field in fields) { if (!_filterByField.ContainsKey(field)) { continue; } var term = _filterByField[field]; if (string.IsNullOrWhiteSpace(term)) { continue; } switch (field) { case GroupFields.DisplayName: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(group.DisplayName, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case GroupFields.Description: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(group.Description, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case GroupFields.ChannelCount: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(group.ChannelCount.ToString(), term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case GroupFields.LastModified: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(group.LastModified.ToString(), term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case GroupFields.LastModifiedBy: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(group.LastModifiedBy, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case GroupFields.AssociatedTestSetups: { var testSetups = new List(); foreach (var assoc in group.AssociatedTestSetups) { testSetups.Add(assoc.Name); } var s = string.Join(", ", testSetups.ToArray()); if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(s, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } } break; default: throw new ArgumentOutOfRangeException(); } } return true; } public void Cleanup() { } public Task CleanupAsync() { return Task.CompletedTask; } public void Initialize() { } public void Initialize(object parameter) { } public void Initialize(object parameter, object model) { } public Task InitializeAsync() { return Task.CompletedTask; } public Task InitializeAsync(object parameter) { return Task.CompletedTask; } public void Activated() { } /// /// Private Event handler for RaiseNotification event. /// private void OnBusyIndicatorNotification(bool eventArg) { IsBusy = eventArg; } private void FireSelectionChanged() { _eventAggregator.GetEvent().Publish(_selectedGroupItems.Select(grp => grp.Id).ToArray()); } /// /// Private Event handler for RaiseNotification event. /// private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle) { // The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window // Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string. var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "", eventArgsWithTitle.Image, string.Empty); NotificationRequest.Raise(new Notification { Content = eventArgsWithoutTitle, Title = eventArgsWithTitle.Title }); } #endregion #region Properties private readonly Dictionary _filterByField = new Dictionary(); private string CurrentSearchTerm = ""; public int SelectedGroupIndex { get; set; } = -1; public ObservableCollection _selectedGroupItems; public ObservableCollection SelectedGroupItems { get => _selectedGroupItems; set { if (_selectedGroupItems != null) { _selectedGroupItems.CollectionChanged -= SelectedGroupItemsOnCollectionChanged; } _selectedGroupItems = value; if (_selectedGroupItems != null) { _selectedGroupItems.CollectionChanged += SelectedGroupItemsOnCollectionChanged; } FireSelectionChanged(); } } private void SelectedGroupItemsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) { if (DTS.Common.Enums.SelectedItemsStatus.GetUpdating(SelectedGroupItems)) { return; } FireSelectionChanged(); } private IGroup[] AllGroups { get; set; } //sort by last modified descending by default private bool _sortAscending = false; private GroupFields _sortField = GroupFields.LastModified; private readonly GroupComparer _comparer = new GroupComparer(); public IGroup[] Groups { get; set; } public bool IsDirty { get; private set; } private bool _isBusy; public bool IsBusy { get => _isBusy; set { _isBusy = value; OnPropertyChanged("IsBusy"); } } private bool _isMenuIncluded; public bool IsMenuIncluded { get => _isMenuIncluded; set { _isMenuIncluded = value; OnPropertyChanged("IsMenuIncluded"); } } private bool _isNavigationIncluded; public bool IsNavigationIncluded { get => _isNavigationIncluded; set { _isNavigationIncluded = value; OnPropertyChanged("IsNavigationIncluded"); } } public string ListViewId => "GroupListView"; private object Page { get; set; } #endregion Properties #region Commands #endregion } }