diff --git a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchElementViewModel.cs b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchElementViewModel.cs index 783035dfe4b..f04c2d5692f 100644 --- a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchElementViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchElementViewModel.cs @@ -113,6 +113,24 @@ public PackageManagerSearchElementViewModel(PackageManagerSearchElement element, public PackageManagerSearchElementViewModel(PackageManagerSearchElement element, bool canLogin) : this(element, canLogin, true) {} + /// + /// A property showing if the currently logged-in user owns the package + /// + private bool isOwner = false; + public bool IsOnwer + { + get + { + return isOwner; + } + + internal set + { + isOwner = value; + RaisePropertyChanged(nameof(IsOnwer)); + } + } + private bool canInstall; /// /// A Boolean flag reporting whether or not the user can install this SearchElement's package. diff --git a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs index 36cb8d1bd11..fd57ae6fd81 100644 --- a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs @@ -651,8 +651,12 @@ private void PopulateMyPackages() var pkgs = PackageManagerClientViewModel.CachedPackageList.Where(x => x.Maintainers != null && x.Maintainers.Contains(name)).ToList(); foreach(var pkg in pkgs) { - var p = new PackageManagerSearchElementViewModel(pkg, false); + var p = new PackageManagerSearchElementViewModel(pkg, + PackageManagerClientViewModel.AuthenticationManager.HasAuthProvider, + CanInstallPackage(pkg.Name)); p.RequestDownload += this.PackageOnExecuted; + p.RequestShowFileDialog += this.OnRequestShowFileDialog; + p.IsOnwer = true; myPackages.Add(p); } @@ -666,6 +670,7 @@ private void ClearMySearchResults() foreach (var ele in this.SearchMyResults) { ele.RequestDownload -= PackageOnExecuted; + ele.RequestShowFileDialog -= OnRequestShowFileDialog; } this.SearchMyResults = null; diff --git a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerViewModel.cs b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerViewModel.cs index 8474cf4e3ce..84897abc499 100644 --- a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerViewModel.cs @@ -1,5 +1,8 @@ using System; using System.Collections.ObjectModel; +using System.Linq; +using Dynamo.PackageManager.ViewModels; +using Dynamo.UI.Commands; using Dynamo.ViewModels; using NotificationObject = Dynamo.Core.NotificationObject; @@ -25,7 +28,20 @@ public class PackageManagerViewModel : NotificationObject, IDisposable /// /// PublishPackageViewModel containing information about all the published packages /// - public PublishPackageViewModel PublishPackageViewModel { get; set; } + /// + private PublishPackageViewModel publishPackageViewModel; + public PublishPackageViewModel PublishPackageViewModel + { + get { return publishPackageViewModel; } + set + { + if (publishPackageViewModel != value) + { + publishPackageViewModel = value; + RaisePropertyChanged(nameof(PublishPackageViewModel)); + } + } + } /// /// Returns all installed packages @@ -37,6 +53,7 @@ public class PackageManagerViewModel : NotificationObject, IDisposable /// public ObservableCollection Filters => installedPackagesViewModel.Filters; + public DelegateCommand PublishNewVersionCommand { get; set; } //Width of the PackageManagerView the default value is 1076 public double Width @@ -90,6 +107,21 @@ public PackageManagerViewModel(DynamoViewModel dynamoViewModel, PackageManagerSe { PreferencesViewModel.SelectedPackagePathForInstall = dynamoViewModel.PreferenceSettings.SelectedPackagePathForInstall; } + + PublishNewVersionCommand = new DelegateCommand(PublishNewPackageVersionRelayCommand); + } + + + private void PublishNewPackageVersionRelayCommand(object obj) + { + var searchElement = obj as PackageManagerSearchElementViewModel; + if(searchElement != null) + { + var localPackage = LocalPackages.First(x => x.Model.Name.Equals(searchElement.Name)); + + if (localPackage == null) { return; } + localPackage.PublishNewPackageVersionCommand.Execute(); + } } private void LocalPackages_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) diff --git a/src/DynamoCoreWpf/ViewModels/PackageManager/PublishPackageViewModel.cs b/src/DynamoCoreWpf/ViewModels/PackageManager/PublishPackageViewModel.cs index 192e73c9006..008886c7046 100644 --- a/src/DynamoCoreWpf/ViewModels/PackageManager/PublishPackageViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/PackageManager/PublishPackageViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; @@ -92,7 +93,7 @@ public DynamoViewModel DynamoViewModel /// /// Package Publish entry, binded to the host multi-selection option /// - public class HostComboboxEntry + public class HostComboboxEntry : NotificationObject { /// /// Name of the host @@ -102,7 +103,19 @@ public class HostComboboxEntry /// /// Boolean indicates if the host entry is selected /// - public bool IsSelected { get; set; } + private bool _isSelected; + public bool IsSelected + { + get { return _isSelected; } + set + { + if (_isSelected != value) + { + _isSelected = value; + RaisePropertyChanged(nameof(IsSelected)); + } + } + } /// /// Constructor @@ -190,6 +203,7 @@ public bool IsNewVersion { _isNewVersion = value; RaisePropertyChanged("IsNewVersion"); + RaisePropertyChanged("CanEditName"); } } } @@ -1134,8 +1148,9 @@ private void ClearAllEntries() this.AdditionalFiles = new ObservableCollection(); this.Dependencies = new ObservableCollection(); this.Assemblies = new List(); - this.SelectedHosts = new List(); + this.KnownHosts.ForEach(host => { host.IsSelected = false; }); this.SelectedHostsString = string.Empty; + this.SelectedHosts = new List(); this.copyrightHolder = string.Empty; this.copyrightYear = string.Empty; this.RootFolder = string.Empty; diff --git a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs index 58be0f74b2d..7e792419834 100644 --- a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs +++ b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs @@ -1493,6 +1493,10 @@ private void DynamoViewModelRequestPackageManager(PublishPackageViewModel model) if (packageManagerWindow.IsLoaded && IsLoaded) packageManagerWindow.Owner = this; } + if (_pkgVM != null) + { + _pkgVM.PublishPackageViewModel = model; + } packageManagerWindow.Focus(); packageManagerWindow.Navigate(Wpf.Properties.Resources.PackageManagerPublishTab); diff --git a/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerPublishControl.xaml.cs b/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerPublishControl.xaml.cs index 84bc4d07653..555ac3a8bf2 100644 --- a/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerPublishControl.xaml.cs +++ b/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerPublishControl.xaml.cs @@ -32,9 +32,35 @@ public PackageManagerPublishControl() InitializeComponent(); this.Loaded += InitializeContext; + this.DataContextChanged += PackageManagerPublishControl_DataContextChanged; + } + + private void PackageManagerPublishControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (!(this.DataContext is PublishPackageViewModel)) return; + + ResetDataContext(); + SetDataContext(); } private void InitializeContext(object sender, RoutedEventArgs e) + { + SetDataContext(); + + this.Loaded -= InitializeContext; + } + + private void ResetDataContext() + { + if (PublishPackageViewModel != null) + { + PublishPackageViewModel.PublishSuccess -= PackageViewModelOnPublishSuccess; + PublishPackageViewModel.RequestShowFolderBrowserDialog -= OnRequestShowFolderBrowserDialog; + } + + PublishPackageViewModel = null; + } + private void SetDataContext() { // Set the owner of this user control this.Owner = Window.GetWindow(this); @@ -42,7 +68,7 @@ private void InitializeContext(object sender, RoutedEventArgs e) PublishPackageViewModel = this.DataContext as PublishPackageViewModel; PublishPackageViewModel.Owner = this.Owner; - if(PublishPackageViewModel != null ) + if (PublishPackageViewModel != null) { PublishPackageViewModel.PublishSuccess += PackageViewModelOnPublishSuccess; PublishPackageViewModel.RequestShowFolderBrowserDialog += OnRequestShowFolderBrowserDialog; @@ -78,6 +104,8 @@ public void Dispose() NavButtonStacks = null; Breadcrumbs?.Clear(); + + this.DataContextChanged -= PackageManagerPublishControl_DataContextChanged; } private void InitializePages() diff --git a/src/DynamoCoreWpf/Views/PackageManager/Pages/PublishPackagePublishPage.xaml.cs b/src/DynamoCoreWpf/Views/PackageManager/Pages/PublishPackagePublishPage.xaml.cs index 84e1a796522..72004e438f8 100644 --- a/src/DynamoCoreWpf/Views/PackageManager/Pages/PublishPackagePublishPage.xaml.cs +++ b/src/DynamoCoreWpf/Views/PackageManager/Pages/PublishPackagePublishPage.xaml.cs @@ -2,6 +2,7 @@ using System.Globalization; using System.Windows; using System.Windows.Controls; +using System.Windows.Input; using System.Windows.Media; using System.Windows.Navigation; @@ -11,7 +12,7 @@ public class PackageNameLengthValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { - if (value is string name && name.TrimEnd().Length > 2) + if (IsValidName((string)value)) { // Validation succeeded return ValidationResult.ValidResult; @@ -20,6 +21,11 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo) // Validation failed return new ValidationResult(false, Wpf.Properties.Resources.NameNeedMoreCharacters); } + public static bool IsValidName(string value) + { + return (value is string name && name.TrimEnd().Length > 2); + } + } @@ -136,11 +142,36 @@ private void textBoxInput_PreviewKeyDown(object sender, System.Windows.Input.Key { var textBox = sender as TextBox; if (textBox == null) return; + if (e.Key == Key.System) return; + + int caretIndex = textBox.CaretIndex; // Store the caret index // Prevents text starting with a space if (e.Key == System.Windows.Input.Key.Space && string.IsNullOrWhiteSpace(textBox.Text)) { - e.Handled = true; + e.Handled = true; + return; + } + + if (string.IsNullOrEmpty(textBox.Text)) { return; } + + // In case we are using the Backspace to remove characters, the validation error will stop the Name property from being updated + if (textBox.Name.Equals("packageNameInput") && e.Key == Key.Back && !PackageNameLengthValidationRule.IsValidName(textBox.Text.Substring(0, textBox.Text.Length - 1))) + { + e.Handled = true; + + if (!string.IsNullOrEmpty(PublishPackageViewModel.Name)) + { + // Manually remove the last character from the Name property, as the validation error will not update the Name property + PublishPackageViewModel.Name = PublishPackageViewModel.Name.Substring(0, PublishPackageViewModel.Name.Length - 1); + + // Trigger re-validation explicitly + var expression = textBox.GetBindingExpression(TextBox.TextProperty); + expression?.UpdateSource(); + + textBox.CaretIndex = caretIndex - 1 >= 0 ? caretIndex - 1 : 0; + return; + } } } }