From e50052d41e414b8420d0779ab84c8ffab859450b Mon Sep 17 00:00:00 2001 From: James Kolpack Date: Sat, 12 Jan 2013 14:58:33 -0500 Subject: [PATCH] Cleanup and fixes --- Web.Tests/ViewModels/Log/LogViewModelTests.cs | 2 +- Web/Attributes/ActionLogAttribute.cs | 5 +- Web/Content/Site.css | 4 ++ Web/Controllers/AccountController.cs | 44 ++++++++++----- Web/Controllers/CreateLogController.cs | 12 ++-- Web/Controllers/EmployeeController.cs | 13 ----- Web/Controllers/LogController.cs | 27 +++++---- Web/Controllers/UserController.cs | 48 ++++++++++++---- Web/Controllers/VehicleController.cs | 12 +++- Web/DAL/DataService.cs | 56 +++++++------------ Web/Email/EmailNotification.cs | 24 ++++++-- Web/Models/Vehicle.cs | 2 +- Web/Scripts/Shared/Site.js | 5 +- Web/Utility/ExcelWriter.cs | 3 - .../Account/ChangePasswordViewModel.cs | 27 +++++++++ .../CreateLog/CreateLogViewModel.cs | 8 ++- ...ViewModel.cs => DriverMileageViewModel.cs} | 4 +- Web/ViewModels/Log/LogViewModel.cs | 5 +- Web/ViewModels/User/CreateUserViewModel.cs | 2 +- Web/ViewModels/User/ExportUserViewModel.cs | 38 +++++++++++++ Web/Views/Account/Manage.cshtml | 5 +- Web/Views/Account/NewPassword.cshtml | 1 + Web/Views/Account/Register.cshtml | 33 ----------- Web/Views/Log/Index.cshtml | 2 +- ...age.cshtml => MonthlyDriverMileage.cshtml} | 6 +- Web/Views/User/Index.cshtml | 1 + Web/Web.csproj | 7 +-- 27 files changed, 240 insertions(+), 156 deletions(-) delete mode 100644 Web/Controllers/EmployeeController.cs rename Web/ViewModels/{EmployeeMileageViewModel.cs => DriverMileageViewModel.cs} (76%) create mode 100644 Web/ViewModels/User/ExportUserViewModel.cs delete mode 100644 Web/Views/Account/Register.cshtml rename Web/Views/Log/{MonthlyEmployeeMileage.cshtml => MonthlyDriverMileage.cshtml} (92%) diff --git a/Web.Tests/ViewModels/Log/LogViewModelTests.cs b/Web.Tests/ViewModels/Log/LogViewModelTests.cs index 77e1390..c9270ac 100644 --- a/Web.Tests/ViewModels/Log/LogViewModelTests.cs +++ b/Web.Tests/ViewModels/Log/LogViewModelTests.cs @@ -85,7 +85,7 @@ namespace Web.Tests.ViewModels.Log Source = logSource }; - viewModel.UpdateLog(log); + viewModel.SetProperties(log); Assert.That(log.LogId, Is.EqualTo(viewModelLogId)); Assert.That(log.CityName, Is.EqualTo(viewModelCityName)); diff --git a/Web/Attributes/ActionLogAttribute.cs b/Web/Attributes/ActionLogAttribute.cs index 0dc3e73..7918a6a 100644 --- a/Web/Attributes/ActionLogAttribute.cs +++ b/Web/Attributes/ActionLogAttribute.cs @@ -9,15 +9,16 @@ namespace MileageTraker.Web.Attributes { if (filterContext != null) { - // TODO: capture current user var controller = filterContext.RouteData.Values["controller"].ToString(); var action = filterContext.RouteData.Values["action"].ToString(); + var username = filterContext.HttpContext.User.Identity.Name; var loggerName = string.Format("{0}Controller.{1}", controller, action); var @params = string.Join(", ", filterContext.ActionParameters.Select(i => i.Key + ": " + i.Value)); var hostAddress = "UserHostAddress: " + filterContext.HttpContext.Request.UserHostAddress; - log4net.LogManager.GetLogger(loggerName).Info(hostAddress + ", " + @params); + log4net.LogManager.GetLogger(loggerName) + .InfoFormat("{0}, username: {1}, {2}", hostAddress, username, @params); } base.OnActionExecuting(filterContext); } diff --git a/Web/Content/Site.css b/Web/Content/Site.css index 048c793..2bbbe6e 100644 --- a/Web/Content/Site.css +++ b/Web/Content/Site.css @@ -143,6 +143,10 @@ dl.inline { margin-right: 30px; } +.setPassword label.checkbox { + padding-left: 10px; +} + @media print { header, footer, diff --git a/Web/Controllers/AccountController.cs b/Web/Controllers/AccountController.cs index ff78dd2..5696351 100644 --- a/Web/Controllers/AccountController.cs +++ b/Web/Controllers/AccountController.cs @@ -1,10 +1,9 @@ using System; using System.Web.Mvc; using System.Web.Security; +using MileageTraker.Web.Attributes; using MileageTraker.Web.DAL; using MileageTraker.Web.Email; -using MileageTraker.Web.Models; -using MileageTraker.Web.Utility; using MileageTraker.Web.ViewModels.Account; namespace MileageTraker.Web.Controllers @@ -74,23 +73,31 @@ namespace MileageTraker.Web.Controllers : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." : null; ViewBag.ReturnUrl = Url.Action("Manage"); - return View(); + + var user = DataService.FindUserByUsername(User.Identity.Name); + var viewModel = new ChangePasswordViewModel(user); + + return View(viewModel); } [HttpPost] [ValidateAntiForgeryToken] + [ActionLog] public ActionResult Manage(ChangePasswordViewModel model) { ViewBag.ReturnUrl = Url.Action("Manage"); + var membershipUser = Membership.GetUser(User.Identity.Name, true); + //var user = DataService.FindUserByUsername(User.Identity.Name); + //model.SetProperties(user); + if (ModelState.IsValid) { // ChangePassword will throw an exception rather than return false in certain failure scenarios. bool changePasswordSucceeded; try { - var currentUser = Membership.GetUser(User.Identity.Name, true); - changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword); + changePasswordSucceeded = membershipUser.ChangePassword(model.OldPassword, model.NewPassword); } catch (Exception) { @@ -130,7 +137,7 @@ namespace MileageTraker.Web.Controllers /// View the Reset Password form /// [AllowAnonymous] - [AcceptVerbs(HttpVerbs.Get)] + [HttpGet] public ViewResult ResetPassword(string username) { return View(new ResetPasswordViewModel{Username = username}); @@ -140,12 +147,13 @@ namespace MileageTraker.Web.Controllers /// Begins the Reset Password process /// [AllowAnonymous] - [AcceptVerbs(HttpVerbs.Post)] + [HttpPost] [ValidateAntiForgeryToken] + [ActionLog] public ActionResult ResetPassword(ResetPasswordViewModel viewModel) { var user = DataService.FindUserByUsername(viewModel.Username); - if (user != null && Request.Url != null) + if (user != null && user.IsApproved && Request.Url != null) { var email = new EmailNotificationService(); var resetPasswordUrl = ResetPassword(user); @@ -161,11 +169,12 @@ namespace MileageTraker.Web.Controllers /// Action users are sent to when they reset their password. /// [AllowAnonymous] - [AcceptVerbs(HttpVerbs.Get)] + [HttpGet] public ActionResult NewPassword(Guid userId, string passwordResetToken) { var user = DataService.GetUser(userId); - if (user != null && user.PasswordResetToken == passwordResetToken) + if (user != null && user.IsApproved && + user.PasswordResetToken == passwordResetToken) { var newPasswordViewModel = new NewPasswordViewModel @@ -185,18 +194,25 @@ namespace MileageTraker.Web.Controllers /// /// The view model. [AllowAnonymous] - [AcceptVerbs(HttpVerbs.Post)] + [HttpPost] [ValidateAntiForgeryToken] + [ActionLog] public ActionResult NewPassword(NewPasswordViewModel viewModel) { if (ModelState.IsValid) { var user = DataService.GetUser(viewModel.UserId); - if (user != null && user.PasswordResetToken == viewModel.PasswordResetToken) + if (user != null && user.IsApproved && + user.PasswordResetToken == viewModel.PasswordResetToken) { DataService.UpdateUserPassword(viewModel.UserId, viewModel.NewPassword); - TempData["StatusMessage"] = "Password set for " + viewModel.Username; - return RedirectToAction("Login", new {username = viewModel.Username}); + var success = Membership.ValidateUser(user.Username, viewModel.NewPassword); + if (success) + { + FormsAuthentication.SetAuthCookie(viewModel.Username, false); + TempData["StatusMessage"] = "Password set for " + viewModel.Username + ", logged in"; + return RedirectToAction("Index", "CreateLog"); + } } } diff --git a/Web/Controllers/CreateLogController.cs b/Web/Controllers/CreateLogController.cs index fff7f32..e9a57c7 100644 --- a/Web/Controllers/CreateLogController.cs +++ b/Web/Controllers/CreateLogController.cs @@ -22,17 +22,13 @@ namespace MileageTraker.Web.Controllers [HttpPost] public ActionResult Index(CreateLogViewModel model) { - if (!ModelState.IsValid) + if (ModelState.IsValid) { - ViewBag.updateError = "Create Failure"; - if (model.LogType == null) // WTF why doesn't the model binder get this - model.LogType = new MileageLogTypeWrapper(); - return View(model); + var confirmCreateLogViewModel = new ConfirmCreateLogViewModel(model); + return View("Confirm", confirmCreateLogViewModel); } - var confirmCreateLogViewModel = new ConfirmCreateLogViewModel(model); - - return View("Confirm", confirmCreateLogViewModel); + return View(model); } [HttpParamAction] diff --git a/Web/Controllers/EmployeeController.cs b/Web/Controllers/EmployeeController.cs deleted file mode 100644 index 3aa3e1b..0000000 --- a/Web/Controllers/EmployeeController.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Web.Mvc; - -namespace MileageTraker.Web.Controllers -{ - public class EmployeeController : ControllerBase - { - public JsonResult Autocomplete(string term) - { - var employees = DataService.GetEmployeeNamesAutocomplete(term); - return Json(employees, JsonRequestBehavior.AllowGet); - } - } -} diff --git a/Web/Controllers/LogController.cs b/Web/Controllers/LogController.cs index 8cda0fb..e01cfe9 100644 --- a/Web/Controllers/LogController.cs +++ b/Web/Controllers/LogController.cs @@ -52,13 +52,18 @@ namespace MileageTraker.Web.Controllers public ActionResult Export(LogQueryViewModel query) { var logs = DataService.GetLogs(); + var filteredLogs = + DataService.FilterLogs(logs, query) + .ToList() + .Select(log => new LogViewModel(log)); + var name = string.Format( "MileageLogs{0}-{1}{2}", query.Year, query.Month, query.LogType.HasValue ? "-" + query.LogType.Value.GetDisplayShortName() : ""); - var export = ExcelWriter.WriteXls(DataService.FilterLogs(logs, query), name, name); + var export = ExcelWriter.WriteXls(filteredLogs, name, name); return File(export, "application/ms-excel", name + ".xls"); } @@ -71,11 +76,11 @@ namespace MileageTraker.Web.Controllers return View(report); } - public ActionResult MonthlyEmployeeMileage(LogQueryViewModel query) + public ActionResult MonthlyDriverMileage(LogQueryViewModel query) { var items = DataService.GetMonthlyEmployeeMileageItems(query); - var report = new EmployeeMileageViewModel(items, query); + var report = new DriverMileageViewModel(items, query); return View(report); } @@ -119,15 +124,15 @@ namespace MileageTraker.Web.Controllers return RedirectToAction("Details", new { id = logId }); } - public ActionResult Create() + [HttpGet] + public ActionResult Create(string vehicleId) { - var viewModel = new LogViewModel { Date = DateTime.Today }; - var vehicleId = Request["vehicleId"]; + var viewModel = new LogViewModel + { + Date = DateTime.Today, + VehicleId = vehicleId + }; - if (vehicleId != null) - { - viewModel.VehicleId = vehicleId; - } return View(viewModel); } @@ -166,7 +171,7 @@ namespace MileageTraker.Web.Controllers if (ModelState.IsValid) { var log = DataService.GetLog(viewModel.LogId); - viewModel.UpdateLog(log); + viewModel.SetProperties(log); log.User = DataService.FindUserByFullName(viewModel.UserFullName); DataService.UpdateLog(log); diff --git a/Web/Controllers/UserController.cs b/Web/Controllers/UserController.cs index 01316b5..a705132 100644 --- a/Web/Controllers/UserController.cs +++ b/Web/Controllers/UserController.cs @@ -2,9 +2,10 @@ using System.Linq; using System.Web.Mvc; using System.Web.Security; +using MileageTraker.Web.Attributes; using MileageTraker.Web.Email; +using MileageTraker.Web.Utility; using MileageTraker.Web.ViewModels; -using MileageTraker.Web.ViewModels.Account; using MileageTraker.Web.ViewModels.User; namespace MileageTraker.Web.Controllers @@ -18,13 +19,28 @@ namespace MileageTraker.Web.Controllers DataService .GetUsers() .ToList() - //.Where(u => u.Filter(q)) .OrderBy(u => u.Username); return View(users); } - //todo: add export + [ActionLog] + public ActionResult Export() + { + var users = DataService.GetUsers(); + var userViewModels = + users + .ToList() + .OrderBy(u => u.Username) + .Select(log => new ExportUserViewModel(log)); + + var name = string.Format( + "MileageTrakerUsers_{0:MM-dd-yyyy}", DateTime.Today); + + var export = ExcelWriter.WriteXls(userViewModels, name, name); + return File(export, "application/ms-excel", name + ".xls"); + } + public ActionResult Details(Guid id) { @@ -78,6 +94,7 @@ namespace MileageTraker.Web.Controllers return View(vm); } + [ActionLog] [HttpPost] public ActionResult Create(CreateUserViewModel viewModel) { @@ -101,7 +118,7 @@ namespace MileageTraker.Web.Controllers return View(viewModel); } - if (viewModel.Roles.Selected != null && viewModel.Roles.Selected.Any()) + if (viewModel.Roles != null) { Roles.AddUserToRoles( membershipUser.UserName, @@ -150,14 +167,15 @@ namespace MileageTraker.Web.Controllers return View(vm); } + [ActionLog] [HttpPost] public ActionResult Edit(EditUserViewModel viewModel) - { - if (ModelState.IsValid) - { + { + if (ModelState.IsValid) + { var user = DataService.GetUser(viewModel.UserId); viewModel.UpdateUser(user); - DataService.UpdateUserPersonalInfo(user); + DataService.UpdateUserPersonalInfo(user); Roles.RemoveUserFromRoles(user.Username, Roles.GetAllRoles()); if (viewModel.Roles != null) @@ -169,9 +187,9 @@ namespace MileageTraker.Web.Controllers TempData["StatusMessage"] = "Changes saved for " + user.Username; return RedirectToAction("Details", new { id = viewModel.UserId}); - } + } return View(viewModel); - } + } public ActionResult SetPassword(Guid id) { @@ -197,6 +215,7 @@ namespace MileageTraker.Web.Controllers return View(viewModel); } + [ActionLog] public ActionResult DisableUser(Guid id) { var user = DataService.GetUser(id); @@ -214,6 +233,7 @@ namespace MileageTraker.Web.Controllers return RedirectToAction("Index"); } + [ActionLog] public ActionResult EnableUser(Guid id) { var user = DataService.GetUser(id); @@ -231,6 +251,7 @@ namespace MileageTraker.Web.Controllers return RedirectToAction("Index"); } + [ActionLog] public ActionResult UnlockUser(Guid id) { var user = DataService.GetUser(id); @@ -249,6 +270,13 @@ namespace MileageTraker.Web.Controllers return RedirectToAction("Index"); } + [Authorize(Roles = "Driver, Administrator, Developer")] + public JsonResult Autocomplete(string term) + { + var employees = DataService.GetUserFullNamesAutocomplete(term); + return Json(employees, JsonRequestBehavior.AllowGet); + } + private static string ErrorCodeToString(MembershipCreateStatus createStatus) { // See http://go.microsoft.com/fwlink/?LinkID=177550 for diff --git a/Web/Controllers/VehicleController.cs b/Web/Controllers/VehicleController.cs index bb7ea89..bcaed39 100644 --- a/Web/Controllers/VehicleController.cs +++ b/Web/Controllers/VehicleController.cs @@ -1,5 +1,6 @@ using System; using System.Web.Mvc; +using MileageTraker.Web.Attributes; using MileageTraker.Web.DAL; using MileageTraker.Web.Models; using MileageTraker.Web.ViewModels.Vehicle; @@ -33,12 +34,14 @@ namespace MileageTraker.Web.Controllers } [HttpPost] - public ActionResult Create(Vehicle vehicle) + [ActionLog] + public ActionResult Create(Vehicle vehicle) { if (ModelState.IsValid) { DataService.AddVehicle(vehicle); - TempData["StatusMessage"] = "Vehicle " + vehicle.VehicleId + "created"; + TempData["StatusMessage"] = + string.Format("Vehicle {0} created", vehicle.VehicleId); return RedirectToAction("Index"); } @@ -52,7 +55,8 @@ namespace MileageTraker.Web.Controllers } [HttpPost] - public ActionResult Edit(Vehicle vehicle) + [ActionLog] + public ActionResult Edit(Vehicle vehicle) { if (ModelState.IsValid) { @@ -63,12 +67,14 @@ namespace MileageTraker.Web.Controllers return View(vehicle); } + [AllowAnonymous] public JsonResult Exists(string vehicleId) { var vehicle = DataService.GetVehicle(vehicleId); return Json(vehicle != null, JsonRequestBehavior.AllowGet); } + [ActionLog] public FileResult Export() { var vehicles = DataService.GetVehicles(); diff --git a/Web/DAL/DataService.cs b/Web/DAL/DataService.cs index d00e637..6c955c2 100644 --- a/Web/DAL/DataService.cs +++ b/Web/DAL/DataService.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Data; using System.Linq; using System.Linq.Expressions; -using System.Text.RegularExpressions; using MileageTraker.Web.Context; using MileageTraker.Web.Models; using MileageTraker.Web.Utility; @@ -389,40 +388,6 @@ namespace MileageTraker.Web.DAL #endregion - #region Employee Name - - public string GetEmployeeNameCorrected(string term) - { - var names = GetEmployeeNames().ToList(); - return (from potentialName in names - let potentialNameClean = Regex.Replace(potentialName, @"\s*\(.*\)", "").ToLower() - let name = term.ToLower() - let similarity = Algorithms.Similarity(potentialNameClean, name) - where similarity > .7 || potentialNameClean.StartsWith(name) - orderby similarity descending - select potentialName).FirstOrDefault(); - } - - public IEnumerable GetEmployeeNamesAutocomplete(string term) - { - var termLower = term.ToLower(); - return from name in GetEmployeeNames() - let nameLower = name.ToLower() - where nameLower.StartsWith(termLower) || Algorithms.Similarity(nameLower, termLower) > .8 - select name; - } - - public IEnumerable GetEmployeeNames() - { - var names = _db.Vehicles.Select(v => v.Assigned).Where(n => !String.IsNullOrEmpty(n) && n != "to be sold"); - var logNames = - (from l in _db.Users - select l.FullName); - return names.Union(logNames).Distinct(); - } - - #endregion - #region City public string GetCitiesCorrected(string term) @@ -450,6 +415,8 @@ namespace MileageTraker.Web.DAL #endregion + #region Membership + public void AddUser(User user) { user.Created = DateTime.Now; @@ -530,5 +497,24 @@ namespace MileageTraker.Web.DAL { return _db.Roles; } + + public IEnumerable GetUserFullNamesAutocomplete(string term) + { + var termLower = term.ToLower(); + return from name in GetUserFullNames() + let nameLower = name.ToLower() + where nameLower.StartsWith(termLower) || Algorithms.Similarity(nameLower, termLower) > .8 + select name; + } + + public IEnumerable GetUserFullNames() + { + var logNames = + (from l in _db.Users + select l.FullName); + return logNames; + } + + #endregion } } \ No newline at end of file diff --git a/Web/Email/EmailNotification.cs b/Web/Email/EmailNotification.cs index a1b109f..091a918 100644 --- a/Web/Email/EmailNotification.cs +++ b/Web/Email/EmailNotification.cs @@ -1,5 +1,6 @@ using System.Configuration; using System.Net.Mail; +using System.Reflection; using MileageTraker.Web.Models; using log4net; @@ -10,15 +11,16 @@ namespace MileageTraker.Web.Email /// public class EmailNotificationService { - //private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private readonly string _emaialFromAddress; private readonly string _resetPasswordSubject; private readonly string _resetPasswordBody; + private readonly string _initializePasswordSubject; + private readonly string _initializePasswordBody; + private readonly SmtpClient _smtpClient; - private string _initializePasswordSubject; - private string _initializePasswordBody; /// /// Initializes a new instance of the class. @@ -45,13 +47,25 @@ namespace MileageTraker.Web.Email public void SendResetPassword(User user, string url) { var body = string.Format(_resetPasswordBody, url); - _smtpClient.Send(new MailMessage(_emaialFromAddress, user.Email, _resetPasswordSubject, body)); + SendMessage(new MailMessage(_emaialFromAddress, user.Email, _resetPasswordSubject, body)); } public void SendInitializePassword(User user, string url) { var body = string.Format(_initializePasswordBody, url, user.FullName); - _smtpClient.Send(new MailMessage(_emaialFromAddress, user.Email, _initializePasswordSubject, body)); + SendMessage(new MailMessage(_emaialFromAddress, user.Email, _initializePasswordSubject, body)); + } + + private void SendMessage(MailMessage mailMessage) + { + try + { + _smtpClient.Send(mailMessage); + } + catch (SmtpException ex) + { + Logger.Error("Failed to send mail", ex); + } } } } \ No newline at end of file diff --git a/Web/Models/Vehicle.cs b/Web/Models/Vehicle.cs index de00a5c..ee92b6f 100644 --- a/Web/Models/Vehicle.cs +++ b/Web/Models/Vehicle.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using MileageTraker.Web.Attributes; -using MileageTraker.Web.Utility; namespace MileageTraker.Web.Models { @@ -69,6 +68,7 @@ namespace MileageTraker.Web.Models [RegularExpression(@"Unassigned|[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Please enter the full name")] [DisplayFormat(NullDisplayText = "Unassigned")] + [FormatHint("Blank for Unassigned")] public string Assigned { get; set; } [InputSize("medium")] diff --git a/Web/Scripts/Shared/Site.js b/Web/Scripts/Shared/Site.js index 4d96a29..b38166d 100644 --- a/Web/Scripts/Shared/Site.js +++ b/Web/Scripts/Shared/Site.js @@ -7,7 +7,7 @@ $(function () { }); $("input#EmployeeName, input#Assigned, input#UserFullName").autocomplete({ - source: "/Employee/Autocomplete", + source: "/User/Autocomplete", minLength: 2 }); @@ -103,7 +103,7 @@ $(function () { 'Delete': 'trash', 'Add': 'plus', 'Export': 'download', - 'Employee Mileage': 'user', + 'Driver Mileage': 'user', 'Vehicle Mileage': 'car' }; $.each(textToIcon, function(text, icon) { @@ -138,6 +138,7 @@ $(function () { var names = fullName.split(' '); ///[a-z().]+(\s+[a-z().]+)+/i.test(fullName) if (names.length > 1) { var username = names[0][0] + names[names.length - 1]; + username = username.toLowerCase(); $('.create-user input#Username').val(username); $('.create-user input#Email').val(username + "@ethra.org"); } diff --git a/Web/Utility/ExcelWriter.cs b/Web/Utility/ExcelWriter.cs index 83b2cbf..7b15707 100644 --- a/Web/Utility/ExcelWriter.cs +++ b/Web/Utility/ExcelWriter.cs @@ -51,9 +51,6 @@ namespace MileageTraker.Web.Utility (item, r) => properties.Zip(CustomExtensions.GetNumbers(), (p, c) => { - // TODO: Fix this - if (item is User) - return (string)null; var value = p.GetValue(item); string formatString = null; diff --git a/Web/ViewModels/Account/ChangePasswordViewModel.cs b/Web/ViewModels/Account/ChangePasswordViewModel.cs index c66eccd..dd5785a 100644 --- a/Web/ViewModels/Account/ChangePasswordViewModel.cs +++ b/Web/ViewModels/Account/ChangePasswordViewModel.cs @@ -1,10 +1,20 @@ using System.ComponentModel.DataAnnotations; using System.Web.Mvc; +using AutoMapper; namespace MileageTraker.Web.ViewModels.Account { public class ChangePasswordViewModel { + [HiddenInput(DisplayValue = false)] + public string Username { get; set; } + + [HiddenInput(DisplayValue = false)] + public string FullName { get; set; } + + [HiddenInput(DisplayValue = false)] + public string Email { get; set; } + [Required] [DataType(DataType.Password)] [Display(Name = "Current password")] @@ -20,5 +30,22 @@ namespace MileageTraker.Web.ViewModels.Account [Display(Name = "Confirm new password")] [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] public string ConfirmPassword { get; set; } + + static ChangePasswordViewModel() + { + Mapper.CreateMap(); + } + + public ChangePasswordViewModel(){} + + public ChangePasswordViewModel(Models.User user) + { + Mapper.Map(user, this); + } + + public void SetProperties(Models.User user) + { + Mapper.Map(user, this); + } } } diff --git a/Web/ViewModels/CreateLog/CreateLogViewModel.cs b/Web/ViewModels/CreateLog/CreateLogViewModel.cs index d71f3fc..a069931 100644 --- a/Web/ViewModels/CreateLog/CreateLogViewModel.cs +++ b/Web/ViewModels/CreateLog/CreateLogViewModel.cs @@ -34,7 +34,7 @@ namespace MileageTraker.Web.ViewModels.CreateLog public MileageLogTypeWrapper LogType { get; set; } [Required(ErrorMessage = "Required")] - [Display(Name = "City Name")] + [Display(Name = "Destination City")] [InputSize("medium")] [StringLength(64, MinimumLength = 3, ErrorMessage = "Minimum 3 characters")] public string CityName { get; set; } @@ -64,6 +64,12 @@ namespace MileageTraker.Web.ViewModels.CreateLog Mapper.CreateMap(); } + public CreateLogViewModel() + { + // view will crash if this isn't instantiated + LogType = new MileageLogTypeWrapper(); + } + public Models.Log GetLog() { var log = new Models.Log(); diff --git a/Web/ViewModels/EmployeeMileageViewModel.cs b/Web/ViewModels/DriverMileageViewModel.cs similarity index 76% rename from Web/ViewModels/EmployeeMileageViewModel.cs rename to Web/ViewModels/DriverMileageViewModel.cs index 6dfe686..3cb59ad 100644 --- a/Web/ViewModels/EmployeeMileageViewModel.cs +++ b/Web/ViewModels/DriverMileageViewModel.cs @@ -4,7 +4,7 @@ using MileageTraker.Web.ViewModels.Log; namespace MileageTraker.Web.ViewModels { - public class EmployeeMileageViewModel + public class DriverMileageViewModel { public IEnumerable Items { get; set; } public LogQueryViewModel Query { get; set; } @@ -12,7 +12,7 @@ namespace MileageTraker.Web.ViewModels public int TotalMiles { get { return Items.Sum(i => i.Miles); } } public double TotalGasPurchased { get { return Items.Sum(i => i.GasPurchased); } } - public EmployeeMileageViewModel(IEnumerable items, LogQueryViewModel query) + public DriverMileageViewModel(IEnumerable items, LogQueryViewModel query) { Items = items; Query = query; diff --git a/Web/ViewModels/Log/LogViewModel.cs b/Web/ViewModels/Log/LogViewModel.cs index 51c40c5..ebf50d1 100644 --- a/Web/ViewModels/Log/LogViewModel.cs +++ b/Web/ViewModels/Log/LogViewModel.cs @@ -81,6 +81,8 @@ namespace MileageTraker.Web.ViewModels.Log public LogViewModel() { + // view will crash if this isn't instantiated + LogType = new MileageLogTypeWrapper(); } public LogViewModel(Models.Log log) @@ -95,10 +97,9 @@ namespace MileageTraker.Web.ViewModels.Log return log; } - public void UpdateLog(Models.Log log) + public void SetProperties(Models.Log log) { Mapper.DynamicMap(this, log); - //TODO use automapper somehow } public IEnumerable Validate(ValidationContext validationContext) diff --git a/Web/ViewModels/User/CreateUserViewModel.cs b/Web/ViewModels/User/CreateUserViewModel.cs index 685d74f..d4ee755 100644 --- a/Web/ViewModels/User/CreateUserViewModel.cs +++ b/Web/ViewModels/User/CreateUserViewModel.cs @@ -29,7 +29,7 @@ namespace MileageTraker.Web.ViewModels.User public CheckBoxViewModel Roles { get; set; } [Required] - [Display(Name = "Set password now instead of emailing ")] + [Display(Name = "Set password now instead of emailing invitation")] [NoEditLabel] public bool SetPassword { get; set; } diff --git a/Web/ViewModels/User/ExportUserViewModel.cs b/Web/ViewModels/User/ExportUserViewModel.cs new file mode 100644 index 0000000..7f8a819 --- /dev/null +++ b/Web/ViewModels/User/ExportUserViewModel.cs @@ -0,0 +1,38 @@ +using System.Web.Mvc; +using System.Linq; +using AutoMapper; + +namespace MileageTraker.Web.ViewModels.User +{ + public class ExportUserViewModel + { + public string FullName { get; set; } + + public string Username { get; set; } + + public string Email { get; set; } + + public string Roles { get; set; } + + public bool IsLockedOut { get; set; } + + public bool IsApproved { get; set; } + + public string LastActivityDate { get; set; } + public string LastLoginDate { get; set; } + public string LastPasswordChangedDate { get; set; } + + static ExportUserViewModel() + { + Mapper.CreateMap() + .ForMember(u => u.Roles, + opt => opt.MapFrom(u => + string.Join((", "), u.Roles.Select(r => r.RoleName)))); + } + + public ExportUserViewModel(Models.User user) + { + Mapper.Map(user, this); + } + } +} \ No newline at end of file diff --git a/Web/Views/Account/Manage.cshtml b/Web/Views/Account/Manage.cshtml index e97a995..dcfde75 100644 --- a/Web/Views/Account/Manage.cshtml +++ b/Web/Views/Account/Manage.cshtml @@ -9,7 +9,10 @@
-

You're logged in as @User.Identity.Name.

+

You're logged in as @User.Identity.Name. + Your name is @Model.FullName and + email is @Model.Email. +

@Html.Partial("_ChangePasswordPartial") diff --git a/Web/Views/Account/NewPassword.cshtml b/Web/Views/Account/NewPassword.cshtml index 659c6da..d3840d7 100644 --- a/Web/Views/Account/NewPassword.cshtml +++ b/Web/Views/Account/NewPassword.cshtml @@ -15,6 +15,7 @@

@ViewBag.Title

+

Hello @Model.Username, please enter a new password below.

@Html.AntiForgeryToken() @Html.Partial("_ValidationSummary") diff --git a/Web/Views/Account/Register.cshtml b/Web/Views/Account/Register.cshtml deleted file mode 100644 index 53a132e..0000000 --- a/Web/Views/Account/Register.cshtml +++ /dev/null @@ -1,33 +0,0 @@ -@model MileageTraker.Web.ViewModels.Account.RegisterModel -@{ - ViewBag.Title = "Register"; -} - -
-

@ViewBag.Title

-

Create a new account.

-
- -@using (Html.BeginForm()) { - @Html.AntiForgeryToken() - @Html.Partial("_ValidationSummary") - -
- Registration Form -
    -
  1. - @Html.LabelFor(m => m.UserName) - @Html.TextBoxFor(m => m.UserName) -
  2. -
  3. - @Html.LabelFor(m => m.Password) - @Html.PasswordFor(m => m.Password) -
  4. -
  5. - @Html.LabelFor(m => m.ConfirmPassword) - @Html.PasswordFor(m => m.ConfirmPassword) -
  6. -
- -
-} diff --git a/Web/Views/Log/Index.cshtml b/Web/Views/Log/Index.cshtml index d5cd80f..1af13cf 100644 --- a/Web/Views/Log/Index.cshtml +++ b/Web/Views/Log/Index.cshtml @@ -32,7 +32,7 @@ @Html.ActionLink("Vehicle Mileage", "MonthlyVehicleMileage", new { Year = Model.SelectedYear, Month = Model.SelectedMonth, LogType = Model.SelectedLogType })
  • - @Html.ActionLink("Employee Mileage", "MonthlyEmployeeMileage", new { Year = Model.SelectedYear, Month = Model.SelectedMonth, LogType = Model.SelectedLogType }) + @Html.ActionLink("Driver Mileage", "MonthlyDriverMileage", new { Year = Model.SelectedYear, Month = Model.SelectedMonth, LogType = Model.SelectedLogType })
  • diff --git a/Web/Views/Log/MonthlyEmployeeMileage.cshtml b/Web/Views/Log/MonthlyDriverMileage.cshtml similarity index 92% rename from Web/Views/Log/MonthlyEmployeeMileage.cshtml rename to Web/Views/Log/MonthlyDriverMileage.cshtml index 38d2a31..4433d5c 100644 --- a/Web/Views/Log/MonthlyEmployeeMileage.cshtml +++ b/Web/Views/Log/MonthlyDriverMileage.cshtml @@ -1,6 +1,6 @@ -@model MileageTraker.Web.ViewModels.EmployeeMileageViewModel +@model MileageTraker.Web.ViewModels.DriverMileageViewModel @{ - ViewBag.Title = "Employee Mileage Report"; + ViewBag.Title = "Driver Mileage Report"; } @{ Html.RenderPartial("BackToLogs"); } @@ -30,7 +30,7 @@
    - Employee + Driver Trips diff --git a/Web/Views/User/Index.cshtml b/Web/Views/User/Index.cshtml index 7666e62..f756278 100644 --- a/Web/Views/User/Index.cshtml +++ b/Web/Views/User/Index.cshtml @@ -19,6 +19,7 @@
    @Html.ActionLink("Add new User", "Create", null, new{@class="btn"}) + @Html.ActionLink("Export", "Export", null, new{@class="btn"})
    Users online now: @Membership.GetNumberOfUsersOnline()
    diff --git a/Web/Web.csproj b/Web/Web.csproj index 70deae9..8e2002d 100644 --- a/Web/Web.csproj +++ b/Web/Web.csproj @@ -120,7 +120,6 @@ - @@ -163,10 +162,11 @@ - + + @@ -280,7 +280,6 @@ - @@ -408,7 +407,7 @@ - +