using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using IssueVision.Data.Web;
using IssueVision.Common;
namespace IssueVision.ViewModel
{
[Export(ViewModelTypes.UserMaintenanceViewModel, typeof(ViewModelBase))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class UserMaintenanceViewModel : ViewModelBase
{
#region "Private Data Members"
private enum UserMaintenanceOperation
{
Add,
Delete,
Update
}
private IIssueVisionModel _issueVisionModel;
private UserMaintenanceOperation _operation;
private string _userNameToDisplay;
#endregion "Private Data Members"
#region "Constructor"
[ImportingConstructor]
public UserMaintenanceViewModel(IIssueVisionModel issueVisionModel)
{
_issueVisionModel = issueVisionModel;
// set up event handling
_issueVisionModel.GetUsersComplete += _issueVisionModel_GetUsersComplete;
_issueVisionModel.SaveChangesComplete += _issueVisionModel_SaveChangesComplete;
_issueVisionModel.PropertyChanged += _issueVisionModel_PropertyChanged;
// set initial user maintenance operation
_userNameToDisplay = string.Empty;
_operation = UserMaintenanceOperation.Update;
IsUpdateUser = true;
IsAddUser = false;
// load all users
_issueVisionModel.GetUsersAsync();
}
#endregion "Constructor"
#region "ICleanup interface implementation"
public override void Cleanup()
{
if (_issueVisionModel != null)
{
// unregister all events
_issueVisionModel.GetUsersComplete -= _issueVisionModel_GetUsersComplete;
_issueVisionModel.SaveChangesComplete -= _issueVisionModel_SaveChangesComplete;
_issueVisionModel.PropertyChanged -= _issueVisionModel_PropertyChanged;
_issueVisionModel = null;
}
// set properties back to null
_allUsers = null;
CurrentUser = null;
// unregister any messages for this ViewModel
base.Cleanup();
}
#endregion "ICleanup interface implementation"
#region "Public Properties"
private IEnumerable<User> _allUsers;
private CollectionViewSource _allUsersSource;
public CollectionViewSource AllUsersSource
{
get { return _allUsersSource; }
private set
{
if (!ReferenceEquals(_allUsersSource, value))
{
_allUsersSource = value;
RaisePropertyChanged("AllUsersSource");
}
}
}
private IEnumerable<string> _userTypeEntries;
public IEnumerable<string> UserTypeEntries
{
get
{
if (_userTypeEntries == null)
{
_userTypeEntries = new[]
{
IssueVisionServiceConstant.UserTypeUser,
IssueVisionServiceConstant.UserTypeAdmin
};
}
return _userTypeEntries;
}
}
private User _currentUser;
public User CurrentUser
{
get { return _currentUser; }
private set
{
if (!ReferenceEquals(_currentUser, value))
{
_currentUser = value;
RaisePropertyChanged("CurrentUser");
}
}
}
private bool _isAddUser;
public bool IsAddUser
{
get { return _isAddUser; }
private set
{
if (value != _isAddUser)
{
_isAddUser = value;
RaisePropertyChanged("IsAddUser");
}
}
}
private bool _isUpdateUser;
public bool IsUpdateUser
{
get { return _isUpdateUser; }
private set
{
if (value != _isUpdateUser)
{
_isUpdateUser = value;
RaisePropertyChanged("IsUpdateUser");
}
}
}
#endregion "Public Properties"
#region "Public Commands"
private RelayCommand _addUserCommand;
public RelayCommand AddUserCommand
{
get
{
if (_addUserCommand == null)
{
_addUserCommand = new RelayCommand(
OnAddUserCommand,
() => (_issueVisionModel != null) && !(_issueVisionModel.HasChanges));
}
return _addUserCommand;
}
}
private void OnAddUserCommand()
{
try
{
if (!_issueVisionModel.IsBusy)
{
// cancel any changes before adding a new user
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
CurrentUser = _issueVisionModel.AddNewUser();
_operation = UserMaintenanceOperation.Add;
IsUpdateUser = false;
IsAddUser = true;
}
}
catch (Exception ex)
{
// notify user if there is any error
AppMessages.RaiseErrorMessage.Send(ex);
}
}
private RelayCommand<User> _removeUserCommand;
public RelayCommand<User> RemoveUserCommand
{
get
{
if (_removeUserCommand == null)
{
_removeUserCommand = new RelayCommand<User>(
OnRemoveUserCommand,
g => (_issueVisionModel != null) && !(_issueVisionModel.HasChanges) && (g != null));
}
return _removeUserCommand;
}
}
private void OnRemoveUserCommand(User g)
{
try
{
if (!_issueVisionModel.IsBusy)
{
// cancel any changes before deleting a user
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
// ask to confirm deleting the current user
var dialogMessage = new DialogMessage(
this,
CommonResources.DeleteCurrentUserMessageBoxText,
s =>
{
if (s == MessageBoxResult.OK)
{
// if confirmed, removing CurrentUser
_issueVisionModel.RemoveUser(g);
// cache the current user name as empty string
_userNameToDisplay = string.Empty;
_operation = UserMaintenanceOperation.Delete;
IsUpdateUser = true;
IsAddUser = false;
_issueVisionModel.SaveChangesAsync();
}
})
{
Button = MessageBoxButton.OKCancel,
Caption = CommonResources.ConfirmMessageBoxCaption
};
AppMessages.PleaseConfirmMessage.Send(dialogMessage);
}
}
catch (Exception ex)
{
// notify user if there is any error
AppMessages.RaiseErrorMessage.Send(ex);
}
}
private RelayCommand _submitChangeCommand;
public RelayCommand SubmitChangeCommand
{
get
{
if (_submitChangeCommand == null)
{
_submitChangeCommand = new RelayCommand(
OnSubmitChangeCommand,
() => (_issueVisionModel != null) && (_issueVisionModel.HasChanges));
}
return _submitChangeCommand;
}
}
private void OnSubmitChangeCommand()
{
try
{
if (!_issueVisionModel.IsBusy)
{
if (CurrentUser != null)
{
// this should trigger validation even if the following field is not changed and is null
if (string.IsNullOrWhiteSpace(CurrentUser.Name))
CurrentUser.Name = string.Empty;
if (string.IsNullOrWhiteSpace(CurrentUser.FirstName))
CurrentUser.FirstName = string.Empty;
if (string.IsNullOrWhiteSpace(CurrentUser.LastName))
CurrentUser.LastName = string.Empty;
if (string.IsNullOrWhiteSpace(CurrentUser.Email))
CurrentUser.Email = null;
if (string.IsNullOrWhiteSpace(CurrentUser.NewPassword))
CurrentUser.NewPassword = string.Empty;
if (string.IsNullOrWhiteSpace(CurrentUser.NewPasswordConfirmation))
CurrentUser.NewPasswordConfirmation = string.Empty;
if (CurrentUser.TryValidateProperty("Name") && CurrentUser.TryValidateProperty("FirstName")
&& CurrentUser.TryValidateProperty("LastName") && CurrentUser.TryValidateProperty("Email")
&& CurrentUser.TryValidateProperty("NewPassword") && CurrentUser.TryValidateProperty("NewPasswordConfirmation")
&& CurrentUser.TryValidateProperty("UserType"))
{
// following settings are there to prevent validation errors
CurrentUser.Password = CurrentUser.NewPassword;
CurrentUser.PasswordAnswer = "PasswordAnswer";
CurrentUser.PasswordAnswerConfirmation = "PasswordAnswer";
// cache the current user name
_userNameToDisplay = CurrentUser.Name;
// change is from User Maintenance screen
CurrentUser.IsUserMaintenance = true;
_issueVisionModel.SaveChangesAsync();
}
}
}
}
catch (Exception ex)
{
// notify user if there is any error
AppMessages.RaiseErrorMessage.Send(ex);
}
}
private RelayCommand _cancelChangeCommand;
public RelayCommand CancelChangeCommand
{
get
{
if (_cancelChangeCommand == null)
{
_cancelChangeCommand = new RelayCommand(
OnCancelChangeCommand,
() => (_issueVisionModel != null) && (_issueVisionModel.HasChanges));
}
return _cancelChangeCommand;
}
}
private void OnCancelChangeCommand()
{
try
{
if (!_issueVisionModel.IsBusy)
{
// ask to confirm canceling the current user in edit
var dialogMessage = new DialogMessage(
this,
CommonResources.CancelCurrentUserMessageBoxText,
s =>
{
if (s == MessageBoxResult.OK)
{
// if confirmed, cancel any change to CurrentUser
_issueVisionModel.RejectChanges();
if (_operation == UserMaintenanceOperation.Update)
{
// if in update operation, just refresh CurrentUser
RaisePropertyChanged("CurrentUser");
}
else
{
// if in add operation, reload all users again
_issueVisionModel.GetUsersAsync();
}
}
})
{
Button = MessageBoxButton.OKCancel,
Caption = CommonResources.ConfirmMessageBoxCaption
};
AppMessages.PleaseConfirmMessage.Send(dialogMessage);
}
}
catch (Exception ex)
{
// notify user if there is any error
AppMessages.RaiseErrorMessage.Send(ex);
}
}
#endregion "Public Commands"
#region "Private Methods"
private void _issueVisionModel_GetUsersComplete(object sender, EntityResultsArgs<User> e)
{
if (!e.HasError)
{
// cancel any changes before setting AllUsersSource
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
// set AllUsersSource
_allUsers = e.Results.OrderBy(g => g.Name);
AllUsersSource = new CollectionViewSource { Source = _allUsers };
AllUsersSource.View.CurrentChanging += View_CurrentChanging;
AllUsersSource.View.CurrentChanged += View_CurrentChanged;
// set CurrentUser
if (_allUsers.Count() >= 1)
{
if (_allUsers.FirstOrDefault(n => n.Name == _userNameToDisplay) == null)
{
// set the first row as the current user
var enumerator = _allUsers.GetEnumerator();
enumerator.MoveNext();
CurrentUser = enumerator.Current;
}
else
{
CurrentUser = _allUsers.FirstOrDefault(n => n.Name == _userNameToDisplay);
AllUsersSource.View.MoveCurrentTo(CurrentUser);
}
}
// set operation back to update
_operation = UserMaintenanceOperation.Update;
IsUpdateUser = true;
IsAddUser = false;
}
else
{
// notify user if there is any error
AppMessages.RaiseErrorMessage.Send(e.Error);
}
}
private void View_CurrentChanging(object sender, CurrentChangingEventArgs e)
{
MessageBoxResult theResult = MessageBoxResult.OK;
if (_issueVisionModel.HasChanges)
{
// ask to confirm canceling the current user in edit
var dialogMessage = new DialogMessage(
this,
CommonResources.CancelCurrentUserMessageBoxText,
s => theResult = s)
{
Button = MessageBoxButton.OKCancel,
Caption = CommonResources.ConfirmMessageBoxCaption
};
AppMessages.PleaseConfirmMessage.Send(dialogMessage);
if (theResult == MessageBoxResult.Cancel)
{
e.Cancel = true;
}
}
}
private void View_CurrentChanged(object sender, EventArgs e)
{
// cancel any changes before editing another user
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
// assign the new current item to CurrentUser
CurrentUser = (User)AllUsersSource.View.CurrentItem;
}
private void _issueVisionModel_SaveChangesComplete(object sender, SubmitOperationEventArgs e)
{
if (!e.HasError)
{
if (_operation == UserMaintenanceOperation.Update)
{
// user update successful
var dialogMessage = new DialogMessage(
this,
CommonResources.UserMaintenanceUpdatedText,
null)
{
Button = MessageBoxButton.OK,
Caption = CommonResources.UserMaintenanceUpdatedCaption
};
AppMessages.StatusUpdateMessage.Send(dialogMessage);
}
// reload the user list after add/delete/update
_issueVisionModel.GetUsersAsync();
}
else
{
if (e.SubmitOp != null &&
(e.SubmitOp.EntitiesInError != null && e.SubmitOp.EntitiesInError.Count() == 1))
{
ValidationResult validationResult = e.SubmitOp.EntitiesInError.First()
.ValidationErrors.FirstOrDefault();
if (validationResult != null &&
string.Equals(validationResult.ErrorMessage, ErrorResources.CannotInsertDuplicateUser))
{
// no permission to add duplicate user
var dialogMessage = new DialogMessage(
this,
ErrorResources.CannotInsertDuplicateUser,
null)
{
Button = MessageBoxButton.OK,
Caption = CommonResources.UserMaintenanceErrorCaption
};
AppMessages.StatusUpdateMessage.Send(dialogMessage);
return;
}
if (validationResult != null &&
string.Equals(validationResult.ErrorMessage, ErrorResources.NoPermissionToDeleteUser))
{
// no permission to delete user
var dialogMessage = new DialogMessage(
this,
ErrorResources.NoPermissionToDeleteUser,
null)
{
Button = MessageBoxButton.OK,
Caption = CommonResources.UserMaintenanceErrorCaption
};
AppMessages.StatusUpdateMessage.Send(dialogMessage);
// cancel any changes
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
return;
}
if (validationResult != null &&
string.Equals(validationResult.ErrorMessage, ErrorResources.CannotDeleteUserAssignedToID))
{
// delete user failed because there are still issues assigned to this user
var dialogMessage = new DialogMessage(
this,
ErrorResources.CannotDeleteUserAssignedToID,
null)
{
Button = MessageBoxButton.OK,
Caption = CommonResources.UserMaintenanceErrorCaption
};
AppMessages.StatusUpdateMessage.Send(dialogMessage);
// cancel any changes
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
return;
}
if (validationResult != null &&
string.Equals(validationResult.ErrorMessage, ErrorResources.CannotDeleteUserChangedByID))
{
// delete user failed because there are still issues changed by this user
var dialogMessage = new DialogMessage(
this,
ErrorResources.CannotDeleteUserChangedByID,
null)
{
Button = MessageBoxButton.OK,
Caption = CommonResources.UserMaintenanceErrorCaption
};
AppMessages.StatusUpdateMessage.Send(dialogMessage);
// cancel any changes
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
return;
}
if (validationResult != null &&
string.Equals(validationResult.ErrorMessage, ErrorResources.CannotDeleteUserOpenedByID))
{
// delete user failed because there are still issues opened by this user
var dialogMessage = new DialogMessage(
this,
ErrorResources.CannotDeleteUserOpenedByID,
null)
{
Button = MessageBoxButton.OK,
Caption = CommonResources.UserMaintenanceErrorCaption
};
AppMessages.StatusUpdateMessage.Send(dialogMessage);
// cancel any changes
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
return;
}
if (validationResult != null &&
string.Equals(validationResult.ErrorMessage, ErrorResources.CannotDeleteUserResolvedByID))
{
// delete user failed because there are still issues resolved by this user
var dialogMessage = new DialogMessage(
this,
ErrorResources.CannotDeleteUserResolvedByID,
null)
{
Button = MessageBoxButton.OK,
Caption = CommonResources.UserMaintenanceErrorCaption
};
AppMessages.StatusUpdateMessage.Send(dialogMessage);
// cancel any changes
if (_issueVisionModel.HasChanges)
{
_issueVisionModel.RejectChanges();
}
return;
}
}
// notify user if there is any unexpected error
AppMessages.RaiseErrorMessage.Send(e.Error);
}
}
private void _issueVisionModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("HasChanges"))
{
AddUserCommand.RaiseCanExecuteChanged();
RemoveUserCommand.RaiseCanExecuteChanged();
SubmitChangeCommand.RaiseCanExecuteChanged();
CancelChangeCommand.RaiseCanExecuteChanged();
}
}
#endregion "Private Methods"
}
}