Compare commits

..
10 Commits
Author SHA1 Message Date
poprhythm 273be34c98 Update smtp configuration 2021-06-24 10:45:09 -04:00
poprhythm 6a5b37eda9 SelectListViewModel tostring fix
Fix for links in the details to the right controller
2020-10-03 21:59:58 -04:00
poprhythm 4b44128d62 Vehicle Recall integrated into Vehicle Service 2020-09-30 21:44:38 -04:00
poprhythm 6f031c5cb6 Add vehicle recall 2020-09-20 22:07:13 -04:00
poprhythm b5589103ec Filter users by active/disabled 2020-08-27 21:41:36 -04:00
poprhythm c58cc951d8 Vehicle Service added for drivers 2020-08-26 21:46:12 -04:00
poprhythm 1acee219a9 Correct EHTRA typo 2020-08-22 21:10:14 -04:00
poprhythm 6fcaaf8657 Update Text 2018-09-29 14:43:30 -04:00
poprhythm 45e461df36 Update Entity Framwork to 6.2.0 2018-09-19 10:52:26 -04:00
poprhythm a662e822e7 Update Hangfire to 1.6.20 2018-09-19 10:50:47 -04:00
52 changed files with 1225 additions and 152 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassWithVirtualMembersNeverInherited_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassWithVirtualMembersNeverInherited_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Traker/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
+15
View File
@@ -0,0 +1,15 @@
using System;
namespace MileageTraker.Web.Attributes
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class OptionLabelAttribute : Attribute
{
public string Text { get; private set; }
public OptionLabelAttribute(string text)
{
Text = text;
}
}
}
+1
View File
@@ -13,6 +13,7 @@ namespace MileageTraker.Web.Context
public DbSet<Role> Roles { get; set; }
public DbSet<PurposeType> PurposeTypes { get; set; }
public DbSet<FuelLog> FuelLogs { get; set; }
public DbSet<VehicleRecall> VehicleRecalls { get; set; }
public DbSet<VehicleService> VehicleServices { get; set; }
public DbSet<ServiceReminder> ServiceReminders { get; set; }
+9 -6
View File
@@ -15,15 +15,18 @@ namespace MileageTraker.Web.Controllers
[Authorize(Roles = "Administrator, Developer")]
public class UserController : ControllerBase
{
public ActionResult Index()
public ActionResult Index(bool disabled = false)
{
var users =
DataService
.GetUsers()
.ToList()
.OrderBy(u => u.Username);
from u in DataService.GetUsers()
where u.IsApproved == !disabled
orderby u.Username
select u;
return View(users);
var userResultsViewModel = new UserResultsViewModel(users.ToList(), disabled);
return View(userResultsViewModel);
}
[ActionLog]
+15 -3
View File
@@ -1,12 +1,12 @@
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
using MileageTraker.Web.Models;
using MileageTraker.Web.Utility;
using MileageTraker.Web.ViewModels.Vehicle;
using MileageTraker.Web.ViewModels.VehicleService;
namespace MileageTraker.Web.Controllers
{
@@ -33,8 +33,17 @@ namespace MileageTraker.Web.Controllers
public PartialViewResult DetailsPartial(string id)
{
var vehicle = DataService.GetVehicle(id);
if (vehicle == null)
Response.StatusCode = 404;
return PartialView(new VehiclePartialDetails(vehicle));
}
public PartialViewResult DetailsQuickPartial(string id)
{
var vehicle = DataService.GetVehicle(id);
if (vehicle == null)
Response.StatusCode = 404;
return PartialView(new VehiclePartialDetailsQuick(vehicle));
}
public ActionResult Create()
{
@@ -75,9 +84,12 @@ namespace MileageTraker.Web.Controllers
}
[AllowAnonymous]
public JsonResult Exists(string vehicleId)
public JsonResult Exists(string vehicleId, string serviceVehicleId)
{
var vehicle = DataService.GetVehicle(vehicleId);
var vehicle =
vehicleId != null
? DataService.GetVehicle(vehicleId)
: DataService.GetVehicle(serviceVehicleId);
return Json(vehicle != null, JsonRequestBehavior.AllowGet);
}
+122
View File
@@ -0,0 +1,122 @@
using System.Linq;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.Models;
using MileageTraker.Web.ViewModels.VehicleRecall;
namespace MileageTraker.Web.Controllers
{
[Authorize(Roles = "Administrator, Developer")]
public class VehicleRecallController : ControllerBase
{
public ActionResult Index(bool completed = false)
{
var vehicleRecalls =
DataService.GetVehicleRecalls()
.Where(vr =>
completed
? vr.CompletedService != null
: vr.CompletedService == null).ToList();
if (vehicleRecalls.Count == 0)
return View("Empty");
var recalls = vehicleRecalls.Select(vr => new VehicleRecallViewModel(vr));
var viewModel = new VehicleRecallResultsViewModel(recalls, completed);
return View(viewModel);
}
public ViewResult Details(int id)
{
var vehicleRecall = DataService.GetVehicleRecall(id);
var viewModel = new VehicleRecallViewModel(vehicleRecall);
return View(viewModel);
}
public ActionResult Create()
{
return View();
}
[HttpGet]
[RequireRequestValue("vehicleId")]
public ActionResult Create(string vehicleId)
{
return View(new VehicleRecallViewModel{VehicleId = vehicleId});
}
[HttpPost]
[ActionLog]
public ActionResult Create(VehicleRecallViewModel viewModel)
{
if (ModelState.IsValid)
{
var vehicleRecall = viewModel.GetVehicleRecall();
var vehicle = DataService.GetVehicle(viewModel.VehicleId);
vehicleRecall.Vehicle = vehicle;
DataService.AddVehicleRecall(vehicleRecall);
var serviceReminder
= new ServiceReminder
{
Vehicle = vehicle,
TargetOdometer = vehicle.CurrentOdometer ?? 0,
Description = $"Recall: {vehicleRecall.Identifier}, {vehicleRecall.Description}"
};
DataService.AddServiceReminder(serviceReminder);
SetStatusMessage($"Vehicle Recall for vehicle {viewModel.VehicleId} created, Service Reminder also created", StatusType.Success);
return RedirectToAction("Index");
}
return View(viewModel);
}
public ActionResult Edit(int id)
{
var vehicleRecall = DataService.GetVehicleRecall(id);
var viewModel = new VehicleRecallViewModel(vehicleRecall);
return View(viewModel);
}
public ActionResult Delete(int id)
{
var vehicleRecall = DataService.GetVehicleRecall(id);
var viewModel = new VehicleRecallViewModel(vehicleRecall);
return View(viewModel);
}
[HttpPost, ActionName("Delete")]
[ActionLog]
public ActionResult DeleteConfirmed(int id)
{
var vehicleRecall = DataService.GetVehicleRecall(id);
var vehicleVehicleId = vehicleRecall.Vehicle.VehicleId;
DataService.DeleteVehicleRecall(id);
SetStatusMessage($"Vehicle Recall \"{vehicleRecall.Identifier}\" for Vehicle ID {vehicleVehicleId} deleted");
return RedirectToAction("Index");
}
[HttpPost]
[ActionLog]
public ActionResult Edit(VehicleRecallViewModel viewModel)
{
if (ModelState.IsValid)
{
var vehicleRecall = viewModel.GetVehicleRecall();
vehicleRecall.Vehicle = DataService.GetVehicle(viewModel.VehicleId);
DataService.UpdateVehicleRecall(vehicleRecall);
SetStatusMessage("Changes saved for vehicle recall " + vehicleRecall.Vehicle.VehicleId);
return RedirectToAction("Details", new { id = vehicleRecall.VehicleRecallId });
}
return View(viewModel);
}
}
}
+104 -18
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
@@ -12,9 +13,10 @@ using MileageTraker.Web.ViewModels.VehicleService;
namespace MileageTraker.Web.Controllers
{
[Authorize(Roles = "Administrator, Developer")]
[Authorize(Roles = "Administrator, Developer, Driver")]
public class VehicleServiceController : ControllerBase
{
[Authorize(Roles = "Administrator, Developer")]
public ActionResult Index(VehicleServiceQueryViewModel query)
{
var validVehicleServiceYearMonths = DataService.GetValidVehicleServiceMonths();
@@ -25,7 +27,10 @@ namespace MileageTraker.Web.Controllers
// default parameter processing
query.SetDefaultParameters(validVehicleServiceYearMonths);
var vehicleServices = DataService.FilterVehicleServices(DataService.GetVehicleServices(), query).ToList();
var vehicleServices =
DataService
.FilterVehicleServices(DataService.GetVehicleServices(), query)
.ToList();
var upcomingServiceReminders =
DataService.GetUpcomingServiceReminders().ToList()
@@ -33,7 +38,7 @@ namespace MileageTraker.Web.Controllers
upcomingServiceReminders.Sort();
var viewModel = new VehicleServiceResultsViewModel(
vehicleServices.Select(s => new VehicleServiceViewModel(s)),
vehicleServices.Select(s => HydrateViewModel(new VehicleServiceViewModel(s), s.VehicleServiceId)),
upcomingServiceReminders,
query,
CustomExtensions.YearMonthList(validVehicleServiceYearMonths));
@@ -41,6 +46,7 @@ namespace MileageTraker.Web.Controllers
return View(viewModel);
}
[Authorize(Roles = "Administrator, Developer")]
[ActionLog]
public ActionResult Export(VehicleServiceQueryViewModel query)
{
@@ -53,7 +59,7 @@ namespace MileageTraker.Web.Controllers
query.SetDefaultParameters(validVehicleServiceYearMonths);
var vehicleServices = DataService.FilterVehicleServices(DataService.GetVehicleServices(), query).ToList();
var filteredServices = vehicleServices.Select(vs => new VehicleServiceViewModel(vs));
var filteredServices = vehicleServices.Select(vs => HydrateViewModel(new VehicleServiceViewModel(vs), vs.VehicleServiceId));
var name = string.Format("VehicleServices_{0}", query);
@@ -61,23 +67,85 @@ namespace MileageTraker.Web.Controllers
return File(export, "application/ms-excel", name + ".xls");
}
[Authorize(Roles = "Administrator, Developer")]
public ViewResult Details(int id)
{
var vehicleService = DataService.GetVehicleService(id);
var viewModel = new VehicleServiceViewModel(vehicleService);
return View(viewModel);
return View(HydrateViewModel(viewModel, vehicleServiceId : vehicleService.VehicleServiceId));
}
public ActionResult Create()
[Authorize(Roles = "Administrator, Developer")]
public ActionResult SelectVehicle()
{
return View();
}
[Authorize(Roles = "Administrator, Developer")]
[HttpGet]
[RequireRequestValue("vehicleId")]
public ActionResult Create(string vehicleId)
public ActionResult Create(string vehicleId, string vehicleRecallId)
{
return View(new VehicleServiceViewModel{VehicleId = vehicleId});
var viewModel = HydrateViewModel(new VehicleServiceViewModel(), vehicleId: vehicleId);
var recall = viewModel.VehicleRecall.Available.FirstOrDefault(r => r.Value == vehicleRecallId);
if (recall != null)
{
foreach (var selectListItem in viewModel.VehicleRecall.Available)
{
selectListItem.Selected = false;
}
recall.Selected = true;
viewModel.VehicleRecall.Selected = int.Parse(recall.Value);
}
return View(viewModel);
}
[HttpPost]
[RequireRequestValue("serviceVehicleId")]
public ActionResult CreateDriver(string serviceVehicleId)
{
return View ("Create", HydrateViewModel(new VehicleServiceViewModel(), vehicleId: serviceVehicleId));
}
private VehicleServiceViewModel HydrateViewModel(VehicleServiceViewModel viewModel,
int vehicleServiceId = Int32.MinValue, string vehicleId = null)
{
if (vehicleId != null)
viewModel.VehicleId = vehicleId;
viewModel.VehicleRecall
= GetVehicleRecallSelectList(viewModel.VehicleId, vehicleServiceId);
return viewModel;
}
private SelectListViewModel GetVehicleRecallSelectList(string vehicleId = null, int vehicleServiceId = Int32.MinValue)
{
var availableRecalls =
DataService.GetOpenVehicleRecalls(vehicleId).Union(DataService.GetVehicleRecallByServiceId(vehicleServiceId))
.Select(vr =>
new SelectListItem
{
Text = vr.Identifier,
Value = vr.VehicleRecallId.ToString(),
Selected = vr.CompletedService.VehicleServiceId == vehicleServiceId
}).ToList();
var selectedValue = availableRecalls.FirstOrDefault(vr => vr.Selected)?.Value ?? "0";
var selectList = new SelectList(availableRecalls, "Value", "Text", selectedValue);
var slvm = new SelectListViewModel
{
Available = selectList,
Selected =
selectList.SelectedValue != null
? (int?)int.Parse((string)selectList.SelectedValue)
: null
};
return slvm;
}
[HttpPost]
@@ -91,12 +159,14 @@ namespace MileageTraker.Web.Controllers
vehicleService.Vehicle = DataService.GetVehicle(viewModel.VehicleId);
DataService.AddVehicleService(vehicleService);
SetStatusMessage(
string.Format("Vehicle Service for vehicle {0} created", viewModel.VehicleId), StatusType.Success);
// update any recalls
DataService.UpdateVehicleRecallService(viewModel.VehicleRecall?.Selected ?? int.MinValue, vehicleService);
SetStatusMessage($"Vehicle Service for vehicle {viewModel.VehicleId} created", StatusType.Success);
return RedirectToAction("UpdateServiceReminders", new {vehicleId = viewModel.VehicleId});
}
return View(viewModel);
return View(HydrateViewModel(viewModel));
}
[HttpGet]
@@ -134,7 +204,7 @@ namespace MileageTraker.Web.Controllers
serviceReminder.Vehicle = vehicle;
DataService.AddServiceReminder(serviceReminder);
status.Add(string.Format("Service Reminder at {0} miles created", viewModel.TargetOdometer));
status.Add($"Service Reminder at {viewModel.TargetOdometer} miles created");
}
// handle any deletion
@@ -151,19 +221,28 @@ namespace MileageTraker.Web.Controllers
{
DataService.DeleteServiceReminder(serviceReminders[selected].id);
}
status.Add(string.Format("Selected {0} service reminders deleted", viewModel.DeleteServiceReminders.Selected.Count()));
status.Add(
$"Selected {viewModel.DeleteServiceReminders.Selected.Count()} " + $"" +
$"service reminder{(viewModel.DeleteServiceReminders.Selected.Count() > 2 ? "s" : "")} deleted");
}
if (status.Count > 0)
{
SetStatusMessage(string.Join(", ", status), StatusType.Success);
}
if (User.IsInRole("Administrator") || User.IsInRole("Developer"))
{
return RedirectToAction("Index");
}
return RedirectToAction("Index", "CreateLog"); // for the drivers
}
return View(viewModel);
}
[Authorize(Roles = "Administrator, Developer")]
private void RefreshServiceReminderViewModel(
UpdateServiceRemindersViewModel viewModel, Vehicle vehicle, bool setDefaultSelectedServiceReminders = false)
{
@@ -186,20 +265,23 @@ namespace MileageTraker.Web.Controllers
}
}
[Authorize(Roles = "Administrator, Developer")]
public ActionResult Edit(int id)
{
var vehicleService = DataService.GetVehicleService(id);
var viewModel = new VehicleServiceViewModel(vehicleService);
return View(viewModel);
return View(HydrateViewModel(viewModel, vehicleServiceId: vehicleService.VehicleServiceId));
}
[Authorize(Roles = "Administrator, Developer")]
public ActionResult Delete(int id)
{
var vehicleService = DataService.GetVehicleService(id);
var viewModel = new VehicleServiceViewModel(vehicleService);
return View(viewModel);
return View(HydrateViewModel(viewModel, vehicleServiceId: vehicleService.VehicleServiceId));
}
[Authorize(Roles = "Administrator, Developer")]
[HttpPost, ActionName("Delete")]
[ActionLog]
public ActionResult DeleteConfirmed(int id)
@@ -210,20 +292,24 @@ namespace MileageTraker.Web.Controllers
return RedirectToAction("Index");
}
[Authorize(Roles = "Administrator, Developer")]
[HttpPost]
[ActionLog]
public ActionResult Edit(VehicleServiceViewModel viewModel)
{
var vehicleService = viewModel.GetVehicleService();
if (ModelState.IsValid)
{
var vehicleService = viewModel.GetVehicleService();
vehicleService.Vehicle = DataService.GetVehicle(viewModel.VehicleId);
DataService.UpdateVehicleService(vehicleService);
DataService.UpdateVehicleRecallService(viewModel.VehicleRecall?.Selected ?? int.MinValue, vehicleService);
SetStatusMessage("Changes saved for vehicle service " + vehicleService.Vehicle.VehicleId);
return RedirectToAction("Details", new { id = vehicleService.VehicleServiceId });
}
return View(viewModel);
return View(HydrateViewModel(viewModel, vehicleService.VehicleServiceId));
}
public JsonResult ServiceCenterNameAutocomplete(string term)
+77
View File
@@ -820,6 +820,11 @@ namespace MileageTraker.Web.DAL
var vehicleService = _db.VehicleServices.Find(id);
_db.VehicleServices.Remove(vehicleService);
foreach (var recall in _db.VehicleRecalls.Where(vr => vr.CompletedService.VehicleServiceId == id))
{
recall.CompletedService = null;
_db.Entry(recall).State = EntityState.Modified;
}
_db.SaveChanges();
}
@@ -992,5 +997,77 @@ namespace MileageTraker.Web.DAL
#endregion
#region Vehicle Recall
public void AddVehicleRecall(VehicleRecall vehicleRecall)
{
_db.VehicleRecalls.Add(vehicleRecall);
_db.SaveChanges();
}
public void UpdateVehicleRecall(VehicleRecall vehicleRecall)
{
_db.Entry(vehicleRecall).State = EntityState.Modified;
_db.SaveChanges();
}
public void UpdateVehicleRecallService(int vehicleRecallId, VehicleService vehicleService)
{
if (vehicleRecallId > 0)
{
var recall = GetVehicleRecall(vehicleRecallId);
recall.CompletedService = vehicleService;
UpdateVehicleRecall(recall);
}
else
{
var recall = GetVehicleRecalls().FirstOrDefault(vr => vr.CompletedService.VehicleServiceId == vehicleService.VehicleServiceId);
if (recall != null)
{
recall.CompletedService = null;
UpdateVehicleRecall(recall);
}
}
}
public IQueryable<VehicleRecall> GetVehicleRecalls(string vehicleId)
{
return GetVehicleRecalls().Where(vr => vr.Vehicle.VehicleId == vehicleId);
}
public IQueryable<VehicleRecall> GetOpenVehicleRecalls()
{
return GetVehicleRecalls().Where(vr => vr.CompletedService == null);
}
public IQueryable<VehicleRecall> GetOpenVehicleRecalls(string vehicleId)
{
return GetOpenVehicleRecalls().Where(vr => vr.Vehicle.VehicleId == vehicleId);
}
public IQueryable<VehicleRecall> GetVehicleRecallByServiceId(int vehicleServiceId)
{
return GetVehicleRecalls().Where(vr => vr.CompletedService.VehicleServiceId == vehicleServiceId);
}
public IQueryable<VehicleRecall> GetVehicleRecalls()
{
return _db.VehicleRecalls;
}
public VehicleRecall GetVehicleRecall(int id)
{
return _db.VehicleRecalls.Find(id);
}
public void DeleteVehicleRecall(int id)
{
var vehicleRecall = _db.VehicleRecalls.Find(id);
_db.VehicleRecalls.Remove(vehicleRecall);
_db.SaveChanges();
}
#endregion
}
}
+2 -1
View File
@@ -71,7 +71,8 @@ namespace MileageTraker.Web.Email
}
catch (SmtpException ex)
{
Logger.Error(ex, "Failed to send mail");
Logger.Error(ex, $"Failed to send mail. Status Code: {ex.StatusCode}. Message: {ex.Message}");
}
}
}
+7 -4
View File
@@ -68,20 +68,23 @@ namespace MileageTraker.Web
metadata.DisplayName = propertyName.Wordify();
var formatHint = attributes.OfType<FormatHintAttribute>().FirstOrDefault();
metadata.AdditionalValues.Add("FormatHint", formatHint != null ? formatHint.Text : null);
metadata.AdditionalValues.Add("FormatHint", formatHint?.Text);
var unitsAttribute = attributes.OfType<UnitsAttribute>().FirstOrDefault();
metadata.AdditionalValues.Add("Units", unitsAttribute != null ? unitsAttribute.Text : null);
metadata.AdditionalValues.Add("Units", unitsAttribute?.Text);
var currencyAttribute = attributes.OfType<CurrencyAttribute>().FirstOrDefault();
metadata.AdditionalValues.Add("Currency", currencyAttribute != null ? currencyAttribute.Symbol : null);
metadata.AdditionalValues.Add("Currency", currencyAttribute?.Symbol);
var inputSizeAttribute = attributes.OfType<InputSizeAttribute>().FirstOrDefault();
metadata.AdditionalValues.Add("InputSize", inputSizeAttribute != null ? inputSizeAttribute.ClassName : null);
metadata.AdditionalValues.Add("InputSize", inputSizeAttribute?.ClassName);
var editLabelAttribute = attributes.OfType<NoEditLabelAttribute>().FirstOrDefault();
metadata.AdditionalValues.Add("EditLabel", editLabelAttribute == null);
var optionLabelAttribute = attributes.OfType<OptionLabelAttribute>().FirstOrDefault();
metadata.AdditionalValues.Add("OptionLabel", optionLabelAttribute?.Text);
return metadata;
}
}
+29
View File
@@ -0,0 +1,29 @@
// <auto-generated />
namespace MileageTraker.Web.Migrations
{
using System.CodeDom.Compiler;
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
[GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")]
public sealed partial class VehicleRecall : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(VehicleRecall));
string IMigrationMetadata.Id
{
get { return "202008300135173_VehicleRecall"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,37 @@
namespace MileageTraker.Web.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class VehicleRecall : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.VehicleRecall",
c => new
{
VehicleRecallId = c.Int(nullable: false, identity: true),
Identifier = c.String(nullable: false, maxLength: 128),
Description = c.String(nullable: false, maxLength: 128),
CompletedService_VehicleServiceId = c.Int(),
Vehicle_VehicleId = c.String(nullable: false, maxLength: 6),
})
.PrimaryKey(t => t.VehicleRecallId)
.ForeignKey("dbo.VehicleService", t => t.CompletedService_VehicleServiceId)
.ForeignKey("dbo.Vehicle", t => t.Vehicle_VehicleId, cascadeDelete: true)
.Index(t => t.CompletedService_VehicleServiceId)
.Index(t => t.Vehicle_VehicleId);
}
public override void Down()
{
DropForeignKey("dbo.VehicleRecall", "Vehicle_VehicleId", "dbo.Vehicle");
DropForeignKey("dbo.VehicleRecall", "CompletedService_VehicleServiceId", "dbo.VehicleService");
DropIndex("dbo.VehicleRecall", new[] { "Vehicle_VehicleId" });
DropIndex("dbo.VehicleRecall", new[] { "CompletedService_VehicleServiceId" });
DropTable("dbo.VehicleRecall");
}
}
}
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -14,7 +14,7 @@ namespace MileageTraker.Web.Models
[Key]
[Required]
[StringLength(6, MinimumLength = 4, ErrorMessage = "Must be at least a 4 digit number")]
[Display(Name = "EHTRA ID")]
[Display(Name = "ETHRA ID")]
[RegularExpression(@"\d+", ErrorMessage = "Vehicle ID must be all numbers")]
[InputSize("mini")]
public string VehicleId { get; set; }
+22
View File
@@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;
namespace MileageTraker.Web.Models
{
public class VehicleRecall
{
[Key]
public int VehicleRecallId { get; set; }
[Required]
public virtual Vehicle Vehicle { get; set; }
[Required]
[StringLength(128, MinimumLength = 3)]
public string Identifier { get; set; }
[Required]
[StringLength(128, MinimumLength = 3, ErrorMessage = "Minimum 3 characters")]
public string Description { get; set; }
public virtual VehicleService CompletedService { get; set; }
}
}
+2
View File
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MileageTraker.Web.Models
{
@@ -24,6 +25,7 @@ namespace MileageTraker.Web.Models
[StringLength(32)]
public string InvoiceNumber { get; set; }
[Required]
public decimal Price { get; set; }
+1 -1
View File
@@ -7,7 +7,7 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<PropertyGroup>
<WebPublishMethod>Package</WebPublishMethod>
<SiteUrlToLaunchAfterPublish />
<DesktopBuildPackageLocation>C:\Users\poprhythm\Documents\code\PublishPackages\MileageTraker.zip</DesktopBuildPackageLocation>
<DesktopBuildPackageLocation>C:\Users\james\source\PublishPackages\MileageTraker.zip</DesktopBuildPackageLocation>
<PackageAsSingleFile>true</PackageAsSingleFile>
<DeployIisAppPath>Default Web Site</DeployIisAppPath>
<PublishDatabaseSettings>
+24
View File
@@ -213,12 +213,14 @@ function addButtonIcons () {
'Vehicle Mileage': 'car',
'Show Active': 'check-circle',
'Show Inactive': 'ban',
'Show Disabled Accts': 'ban',
'Set Inactive' : 'ban',
'Reactivate': 'check-circle',
'Config': 'cog',
'Cities': 'map',
'Purposes': 'arrow-right',
'Vehicle Service': 'wrench',
'Vehicle Recall': 'refresh',
'Vehicle': 'car',
'Cost': 'money',
'Reminder': 'clock-o',
@@ -384,5 +386,27 @@ $(function () {
});
});
function VehicleInput_ShowDetails() {
$(".control-group.vehicleId").append('<div id="VehicleDetails"</div>');
var getDetails = function () {
var vehicleId = $("#VehicleId");
var vehicleDetails = $("#VehicleDetails");
if (vehicleId.val().length >= 4 && vehicleId.valid() === true) {
$.ajax({
type: "GET",
url: "/Vehicle/DetailsQuickPartial",
data: { id: vehicleId.val() },
success: function (html) { vehicleDetails.html(html); },
error: function () { vehicleDetails.empty(); }
});
} else {
vehicleDetails.empty();
}
};
$("#VehicleId").keyup(getDetails);
}
/* End Form Validation */
+12 -7
View File
@@ -5,6 +5,7 @@ using System.Linq;
using System.Reflection;
using ExcelLibrary.SpreadSheet;
using MileageTraker.Web.Models;
using MileageTraker.Web.ViewModels;
namespace MileageTraker.Web.Utility
{
@@ -108,21 +109,25 @@ namespace MileageTraker.Web.Utility
if (p.Name == "GasPurchased") // format to the .000 place
formatString = "#,##0.000";
int intValue; // write int-looking values as numbers
if (value is string && int.TryParse((string) value, out intValue))
if (value is string valInt && int.TryParse(valInt, out var intValue))
value = intValue;
double doubleValue; // write double-looking values as numbers
if (value is string && double.TryParse((string) value, out doubleValue))
if (value is string valDbl && double.TryParse(valDbl, out var doubleValue))
value = doubleValue;
if (value is MileageLogTypeWrapper)
value = ((MileageLogTypeWrapper) value).Enum.GetDisplayName();
if (value is MileageLogTypeWrapper valMt)
value = valMt.Enum.GetDisplayName();
if (value is SelectListViewModel valSelList)
value = valSelList.ToString();
if (value == null)
value = p.GetNullDisplayText(item);
var cell = formatString != null ? new Cell(value, formatString) : new Cell(value);
var cell =
formatString != null
? new Cell(value, formatString)
: new Cell(value);
worksheet.Cells[r, c] = cell;
return (string) null;
+15 -2
View File
@@ -1,15 +1,28 @@
using System.Web.Mvc;
using System.Linq;
using System.Web.Mvc;
namespace MileageTraker.Web.ViewModels
{
public class SelectListViewModel
{
public SelectList Available { get; set; }
public int Selected { get; set; }
public int? Selected { get; set; }
public override string ToString()
{
if (Selected.HasValue && Selected.Value > 0 && Available != null)
{
var selected = Available.FirstOrDefault(i => i.Value == Selected.ToString());
if (selected != null)
{
return selected.Text;
}
}
else if (Selected.HasValue)
{
return Selected.ToString();
}
return string.Empty;
}
}
}
@@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace MileageTraker.Web.ViewModels.User
{
public class UserResultsViewModel
{
public IEnumerable<Models.User> Users { get; set; }
public bool Disabled { get; }
public UserResultsViewModel(IEnumerable<Models.User> users, bool disabled)
{
Users = users;
Disabled = disabled;
}
}
}
@@ -0,0 +1,42 @@
using System.ComponentModel.DataAnnotations;
using AutoMapper;
namespace MileageTraker.Web.ViewModels.Vehicle
{
public class VehiclePartialDetailsQuick
{
[Display(Name = "Year")]
public string ModelYear { get; set; }
public string Make { get; set; }
[Display(Name = "Model")]
public string CarModel { get; set; }
public string Color { get; set; }
public string Type { get; set; }
[Display(Name = "VIN")]
public string Vin { get; set; }
[Display(Name = "Tag#")]
public string TagNumber { get; set; }
[DisplayFormat(NullDisplayText = "Unassigned")]
public string Assigned { get; set; }
static VehiclePartialDetailsQuick()
{
Mapper.CreateMap<Models.Vehicle, VehiclePartialDetailsQuick>();
}
public VehiclePartialDetailsQuick()
{}
public VehiclePartialDetailsQuick(Models.Vehicle vehicle)
{
Mapper.Map(vehicle, this);
}
}
}
@@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace MileageTraker.Web.ViewModels.VehicleRecall
{
public class VehicleRecallResultsViewModel
{
public IEnumerable<VehicleRecallViewModel> Recalls { get; set; }
public bool Completed { get; set; }
public VehicleRecallResultsViewModel(IEnumerable<VehicleRecallViewModel> vehicles, bool completed)
{
Recalls = vehicles;
Completed = completed;
}
}
}
@@ -0,0 +1,64 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using AutoMapper;
using MileageTraker.Web.Attributes;
namespace MileageTraker.Web.ViewModels.VehicleRecall
{
public class VehicleRecallViewModel
{
[HiddenInput(DisplayValue = false)]
public int? VehicleRecallId { get; set; }
[Required]
[Remote("Exists", "Vehicle", ErrorMessage = "ID not found")]
[StringLength(6, MinimumLength = 4, ErrorMessage = "Must be at least a 4 digit number")]
[Display(Name = "Vehicle ID")]
[RegularExpression(@"\d+", ErrorMessage = "Vehicle ID must be all numbers")]
[InputSize("mini")]
public string VehicleId { get; set; }
[Required]
[Display(Name = "Recall Identifier")]
[StringLength(128, MinimumLength = 3)]
[InputSize("small")]
public string Identifier { get; set; }
[Required]
[StringLength(128, MinimumLength = 3, ErrorMessage = "Minimum 3 characters")]
public string Description { get; set; }
[ScaffoldColumn(false)]
[Display(Name = "Vehicle Service")]
[UIHint("VehicleServiceLink")]
public int CompletedService_VehicleServiceId { get; set; }
[ScaffoldColumn(false)]
[Display(Name = "Completed Date")]
public DateTime CompletedService_InvoiceDate { get; set; }
static VehicleRecallViewModel()
{
Mapper.CreateMap<VehicleRecallViewModel, Models.VehicleRecall>();
Mapper.CreateMap<Models.VehicleRecall, VehicleRecallViewModel>()
.ForMember(dest => dest.VehicleId, opt => opt.MapFrom(src => src.Vehicle.VehicleId));
}
public VehicleRecallViewModel(Models.VehicleRecall vehicleRecall)
{
Mapper.Map(vehicleRecall, this);
}
public VehicleRecallViewModel()
{
}
public Models.VehicleRecall GetVehicleRecall()
{
var vehicleRecall = new Models.VehicleRecall();
Mapper.Map(this, vehicleRecall);
return vehicleRecall;
}
}
}
@@ -4,7 +4,6 @@ using System.Web.Mvc;
using AutoMapper;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
using MileageTraker.Web.ViewModels.ServiceReminder;
namespace MileageTraker.Web.ViewModels.VehicleService
{
@@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
namespace MileageTraker.Web.ViewModels.VehicleService
{
public class VehicleSelectViewModel : IValidatableObject
{
[Required(ErrorMessage = "Required")]
[Remote("Exists", "Vehicle", ErrorMessage = "ID not found")]
[StringLength(6, MinimumLength = 4, ErrorMessage = "Must be a 4 digit number")]
[Display(Name = "Vehicle ID")]
[InputSize("mini")]
[RegularExpression(@"\d+", ErrorMessage = "Must be all numbers")]
public string ServiceVehicleId { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
using (var dataService = new DataService())
{
var inactiveDate = dataService.GetVehicle(ServiceVehicleId).InactiveDate;
if (inactiveDate.HasValue)
{
yield return new ValidationResult(
string.Format("Vehicle was set inactive on {0:MM/dd/yyyy}", inactiveDate.Value),
new[] { "VehicleId" });
}
}
}
public override string ToString()
{
return string.Format("vehicle: {0}", ServiceVehicleId);
}
}
}
@@ -1,22 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
using AutoMapper;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
namespace MileageTraker.Web.ViewModels.VehicleService
{
public class VehicleServiceViewModel
public class VehicleServiceViewModel : IValidatableObject
{
[HiddenInput(DisplayValue = false)]
public int? VehicleServiceId { get; set; }
[Required]
[Remote("Exists", "Vehicle", ErrorMessage = "ID not found")]
[StringLength(6, MinimumLength = 4, ErrorMessage = "Must be at least a 4 digit number")]
[Display(Name = "Vehicle ID")]
[RegularExpression(@"\d+", ErrorMessage = "Vehicle ID must be all numbers")]
[InputSize("mini")]
[HiddenInput(DisplayValue = true)]
public string VehicleId { get; set; }
[DataType(DataType.DateTime)]
@@ -44,6 +42,11 @@ namespace MileageTraker.Web.ViewModels.VehicleService
[StringLength(64, MinimumLength = 3, ErrorMessage = "Minimum 3 characters")]
public string Description { get; set; }
[Display(Name = "Vehicle Recall")]
[OptionLabel("Not a recall")]
[UIHint("VehicleRecallSelectListViewModel")]
public SelectListViewModel VehicleRecall { get; set; }
static VehicleServiceViewModel()
{
Mapper.CreateMap<VehicleServiceViewModel, Models.VehicleService>();
@@ -51,13 +54,15 @@ namespace MileageTraker.Web.ViewModels.VehicleService
.ForMember(dest => dest.VehicleId, opt => opt.MapFrom(src => src.Vehicle.VehicleId));
}
public VehicleServiceViewModel(Models.VehicleService vehicleService)
public VehicleServiceViewModel(Models.VehicleService vehicleService) : this()
{
Mapper.Map(vehicleService, this);
}
public VehicleServiceViewModel()
{
//var enumerable = new string[]{};
//VehicleRecallId = new SelectListViewModel { Available = new SelectList(enumerable, "VehicleRecallId", "RecallId") };
}
public Models.VehicleService GetVehicleService()
@@ -66,5 +71,19 @@ namespace MileageTraker.Web.ViewModels.VehicleService
Mapper.Map(this, vehicleService);
return vehicleService;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
using (var dataService = new DataService())
{
var recallId = VehicleRecall?.Selected ?? int.MinValue;
// if there's a recall, verify it's for this vehicle
if (recallId >= 0 && dataService.GetVehicleRecall(recallId).Vehicle.VehicleId != VehicleId)
{
yield return new ValidationResult("This recall is not for the given vehicle",
new[] {"VehicleRecall"});
}
}
}
}
}
+4 -1
View File
@@ -1,4 +1,5 @@
@model MileageTraker.Web.ViewModels.CreateLog.CreateLogViewModel
@using MileageTraker.Web.ViewModels.VehicleService
@model MileageTraker.Web.ViewModels.CreateLog.CreateLogViewModel
@{
ViewBag.Title = "Enter Mileage Log";
@@ -24,6 +25,8 @@
</div>
@Html.Partial("EditorTemplates/VehicleSelect", new VehicleSelectViewModel())
<div class="center-content" style="text-align: center">
@Html.ActionLink("Import", "ImportUpload", new {}, new { @class = "btn"})
</div>
+3
View File
@@ -17,7 +17,10 @@
</div>
<div class="btn-toolbar center-content well">
<div class="btn-group">
@Html.ActionLink("Add Reminder", "Create", new { vehicleId = Model.VehicleId }, new { @class = "btn" })
@Html.ActionLink("Add Service", "Create", "VehicleService", new { vehicleId = Model.VehicleId }, new { @class = "btn" })
@Html.ActionLink("Add Recall", "Create", "VehicleRecall", new { vehicleId = Model.VehicleId }, new { @class = "btn" })
</div>
@Html.ActionLink("Vehicle Details", "Details", "Vehicle", new { id = Model.VehicleId }, new { @class = "btn" })
</div>
@@ -0,0 +1,19 @@
@model MileageTraker.Web.ViewModels.VehicleRecall.VehicleRecallViewModel
@{
ViewBag.Title = "Vehicle Recall Details" ;
}
@Html.Partial("_StatusMessage")
<h2 class="center-content"><i class="fa fa-refresh"></i> @ViewBag.Title</h2>
<div class="center-content well">
@Html.DisplayForModel()
</div>
<div class="center-content btn-toolbar">
@Html.ActionLink("Edit", "Edit", "VehicleRecall", new { id = Model.VehicleRecallId }, new { @class = "btn" })
@Html.ActionLink("Delete", "Delete", "VehicleRecall", new { id = Model.VehicleId }, new { @class = "btn" })
@Html.ActionLink("Vehicle Details", "Details", "Vehicle", new { id = Model.VehicleId }, new{@class="btn"})
@Html.ActionLink("Add Service", "Create", "VehicleService", new { VehicleId = Model.VehicleId }, new{@class="btn"})
</div>
@@ -0,0 +1,16 @@
@model MileageTraker.Web.ViewModels.SelectListViewModel
@{
Layout = "~/Views/Shared/DisplayTemplates/_FieldLayout.cshtml";
if (Model.Selected > 0)
{
var selected = Model.Available.FirstOrDefault(i => i.Value == Model.Selected.ToString());
if (selected != null)
{
@Html.ActionLink(selected.Text, "Details", "VehicleRecall", new { id = selected.Value }, null)
}
}
else
{
<text>Not a recall</text>
}
}
@@ -0,0 +1,7 @@
@{
Layout = "~/Views/Shared/DisplayTemplates/_FieldLayout.cshtml";
}
@if (Model != null)
{
@Html.ActionLink("View Vehicle Service", "Details", "VehicleService", new { id = Model}, null)
}
@@ -1,5 +1,7 @@
@model MileageTraker.Web.ViewModels.SelectListViewModel
@{
Layout = "~/Views/Shared/EditorTemplates/_FieldLayout.cshtml";
var values = ViewData.ModelMetadata.AdditionalValues;
var optionLabel = values.ContainsKey("OptionLabel") ? (string)values["OptionLabel"] : string.Empty;
}
@Html.DropDownListFor(m => m.Selected, Model.Available, string.Empty)
@Html.DropDownListFor(m => m.Selected, Model.Available, optionLabel)
@@ -0,0 +1,25 @@
@model MileageTraker.Web.ViewModels.VehicleService.VehicleSelectViewModel
@using (Html.BeginForm("CreateDriver", "VehicleService", FormMethod.Post, new { @class = "form-horizontal well center-content" }))
{
<h5>Enter Vehicle Service</h5>
<div class="control-group serviceVehicleId">
<div class="row-fluid">
<div class="span6">
@Html.LabelFor(m => m.ServiceVehicleId, "Vehicle ID")
</div>
<div class="span4">
@Html.TextBoxFor(m => m.ServiceVehicleId, new { @class = "input-mini" })
</div>
<div class="span2">
<input type="submit" value="Enter" class="btn btn-small" />
</div>
</div>
<div class="row-fluid">
<div class="offset6">
<span class="help-block">@Html.ValidationMessage("ServiceVehicleId")</span>
</div>
</div>
</div>
}
+1
View File
@@ -41,6 +41,7 @@
<ul class="dropdown-menu">
<li>@Html.ActionLink("Vehicles", "Index", "Vehicle")</li>
<li>@Html.ActionLink("Vehicle Service", "Index", "VehicleService")</li>
<li>@Html.ActionLink("Vehicle Recalls", "Index", "VehicleRecall")</li>
<li>@Html.ActionLink("Fuel Logs", "Index", "FuelLog")</li>
<li>@Html.ActionLink("Cost Report", "VehicleCostIndex", "Vehicle")</li>
@if (User.IsInRole("Developer"))
+4 -2
View File
@@ -1,9 +1,9 @@
@using MileageTraker.Web.Models
@model IEnumerable<User>
@model MileageTraker.Web.ViewModels.User.UserResultsViewModel
@{
ViewBag.Title = "Users";
var grid = new WebGrid(Model, rowsPerPage: 45);
var grid = new WebGrid(Model.Users, rowsPerPage: 45);
}
@Html.Partial("_StatusMessage")
@@ -20,6 +20,8 @@
<div class="btn-toolbar pull-left">
@Html.ActionLink("Add new User", "Create", null, new{@class="btn"})
@Html.ActionLink("Export", "Export", null, new{@class="btn"})
@Html.ActionLink(Model.Disabled ? "Show Active" : "Show Disabled Accts", "Index", new {disabled = !Model.Disabled}, new { @class = "btn" })
@if (User.IsInRole("Developer"))
{
@Html.ActionLink("Invite Uninintialized", "InviteUninitialized", null, new{@class="btn"})
+3
View File
@@ -38,6 +38,9 @@
</li>
<li>
@Html.ActionLink("Add Service", "Create", "VehicleService", new { VehicleId = Model.VehicleId }, null)
</li>
<li>
@Html.ActionLink("Add Recall", "Create", "VehicleRecall", new { VehicleId = Model.VehicleId }, null)
</li>
</ul>
</div>
@@ -0,0 +1,5 @@
@model MileageTraker.Web.ViewModels.Vehicle.VehiclePartialDetailsQuick
@{
Layout = null;
}
@Html.DisplayForModel()
+28
View File
@@ -0,0 +1,28 @@
@model MileageTraker.Web.ViewModels.VehicleRecall.VehicleRecallViewModel
@{
ViewBag.Title = "Enter Vehicle Recall";
}
@section Scripts {
<script type="text/javascript">
VehicleInput_ShowDetails();
</script>
}
@Html.Partial("_StatusMessage")
<h2 class="center-content"><i class="fa fa-refresh"></i> @ViewBag.Title</h2>
<h4 class="center-content">Enter an available recall for vehicle</h4>
@using (Html.BeginForm("Create", "VehicleRecall", FormMethod.Post, new { @class = "form-horizontal well center-content" }))
{
@Html.Partial("_ValidationSummary")
<fieldset>
<legend></legend>
@Html.EditorForModel()
<div class="form-actions">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</fieldset>
}
+24
View File
@@ -0,0 +1,24 @@
@model MileageTraker.Web.ViewModels.VehicleRecall.VehicleRecallViewModel
@{
ViewBag.Title = "Delete Vehicle Recall";
}
@Html.Partial("_StatusMessage")
<h2 class="center-content"><i class="fa fa-refresh"></i> @ViewBag.Title</h2>
<div class="center-content label label-warning">Are you sure you wish to delete this recall?</div>
<div class="center-content well">
@Html.DisplayForModel()
@using (Html.BeginForm("Delete", "VehicleRecall", FormMethod.Post, new { @class = "form-horizontal" }))
{
<div class="form-actions">
<input type="submit" value="Delete" class="btn btn-warning" />
@Html.ActionLink("Cancel", "Details", new { id = Model.VehicleRecallId }, new { @class = "btn" })
</div>
}
</div>
+28
View File
@@ -0,0 +1,28 @@
@using System.Activities.Expressions
@model MileageTraker.Web.ViewModels.VehicleRecall.VehicleRecallViewModel
@{
ViewBag.Title = "Vehicle Recall Details" ;
var completed = Model.CompletedService_VehicleServiceId > 0;
}
@Html.Partial("_StatusMessage")
<h2 class="center-content"><i class="fa fa-refresh"></i> @ViewBag.Title</h2>
<div class="center-content well">
@Html.DisplayForModel()
@if (completed)
{
@Html.DisplayFor(v => v.CompletedService_VehicleServiceId)
}
</div>
@if (!completed)
{
<div class="center-content">Completed? @Html.ActionLink("Add Service", "Create", "VehicleService", new { VehicleId = Model.VehicleId, VehicleRecallId = Model.VehicleRecallId}, new { @class = "btn" })</div>
}
<div class="center-content btn-toolbar">
@Html.ActionLink("Edit", "Edit", new { id = Model.VehicleRecallId }, new { @class = "btn" })
@Html.ActionLink("Delete", "Delete", new { id = Model.VehicleRecallId }, new { @class = "btn" })
@Html.ActionLink("Vehicle Details", "Details", "Vehicle", new { id = Model.VehicleId }, new{@class="btn"})
</div>
+27
View File
@@ -0,0 +1,27 @@
@model MileageTraker.Web.ViewModels.VehicleRecall.VehicleRecallViewModel
@{
ViewBag.Title = "Edit Vehicle Recall";
}
@section Scripts {
<script type="text/javascript">
VehicleInput_ShowDetails();
</script>
}
@Html.Partial("_StatusMessage")
<h2 class="center-content"><i class="fa fa-refresh"></i> @ViewBag.Title</h2>
@using (Html.BeginForm("Edit", "VehicleRecall", FormMethod.Post, new { @class = "form-horizontal well center-content" }))
{
@Html.Partial("_ValidationSummary")
<fieldset>
<legend></legend>
@Html.EditorForModel()
<div class="form-actions">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</fieldset>
}
+9
View File
@@ -0,0 +1,9 @@
@{
ViewBag.Title = "No Open Vehicle Recalls";
}
<h2 class="center-content"><i class="fa fa-refresh"></i> @ViewBag.Title</h2>
<div class="center-content well">
No open Vehicle Recalls. @Html.ActionLink("Add Recall", "Create", null, new { @class = "btn" })
</div>
+34
View File
@@ -0,0 +1,34 @@
@model MileageTraker.Web.ViewModels.VehicleRecall.VehicleRecallResultsViewModel
@{
ViewBag.Title = string.Format("Vehicle Recalls ({0})", Model.Completed ? "Completed" : "Open");
var grid = new WebGrid(Model.Recalls, rowsPerPage: 45);
var columns = grid.Columns(
grid.Column("VehicleId", "Vehicle ID", item => Html.ActionLink((string) item.VehicleId, "DetailsPartial", "Vehicle", new {id = item.VehicleId}, new {@class = "qtip-modal"})),
grid.Column("Identifier", "Identifier", item => item.Identifier),
grid.Column("Description", "Description"),
grid.Column(format:
@<div class='btn-group'>
@Html.ActionLink("Details", "Details", new {id = item.VehicleRecallId}, new {@class = "btn btn-mini"})
@Html.ActionLink("Delete", "Delete", new {id = item.VehicleRecallId}, new {@class = "btn btn-mini"})
</div>)
).ToList();
if (Model.Completed)
{
columns.Insert(3, grid.Column("CompletedService_InvoiceDate", "Completed Date", item => ((DateTime)item.CompletedService_InvoiceDate).ToShortDateString()));
}
}
@Html.Partial("_StatusMessage")
<h2 id="vehicle-title"><i class="fa fa-refresh"></i> @ViewBag.Title</h2>
<div class="btn-toolbar pull-left">
@Html.ActionLink("Add Recall", "Create", null, new { @class = "btn" })
@Html.ActionLink(Model.Completed ? "Show Open" : "Show Completed", "Index", new { completed = !Model.Completed }, new { @class = "btn" })
</div>
@grid.GetHtml(columns: columns,
htmlAttributes: new { @class = "table table-striped table-bordered table-hover table-condensed"},
numericLinksCount: 20
)
+9 -2
View File
@@ -1,7 +1,6 @@
@model MileageTraker.Web.ViewModels.VehicleService.VehicleServiceViewModel
@{
ViewBag.Title = "Create Vehicle Service";
ViewBag.Title = "Record Vehicle Service";
}
<h2 class="center-content"><i class="fa fa-wrench"></i> @ViewBag.Title</h2>
@@ -12,6 +11,14 @@
@Html.Partial("_ValidationSummary")
<fieldset>
<legend></legend>
<div class="control-group">
<div class="control-label">
<label>Vehicle ID</label>
</div>
<div class="controls">
<b>@Model.VehicleId</b>
</div>
</div>
@Html.EditorForModel()
<div class="form-actions">
<input type="submit" value="Create" class="btn btn-primary" />
+23 -3
View File
@@ -1,4 +1,5 @@
@model MileageTraker.Web.ViewModels.VehicleService.VehicleServiceResultsViewModel
@using MileageTraker.Web.ViewModels
@model MileageTraker.Web.ViewModels.VehicleService.VehicleServiceResultsViewModel
@{
ViewBag.Title = "Vehicle Service";
@@ -30,7 +31,7 @@
<h2 id="vehicle-title"><i class="fa fa-wrench"></i> @ViewBag.Title</h2>
<div class="btn-toolbar pull-left">
@Html.ActionLink("Add Service", "Create", null, new { @class = "btn" })
@Html.ActionLink("Add Service", "SelectVehicle", null, new { @class = "btn" })
@Html.ActionLink("Export", "Export", queryParams, new { @class = "btn" })
<a class="qtip-show-next-div btn">Upcoming Services <span class="badge @serviceOverdueBadge">@Model.UpcomingServiceReminders.Count</span></a>
<div class="hidden">
@@ -38,7 +39,8 @@
{
@Html.Partial("UpcomingServiceReminders", Model.UpcomingServiceReminders)
}
else {
else
{
<h5>No upcoming services currently scheduled</h5>
}
</div>
@@ -51,6 +53,7 @@
grid.Column("ServiceCenterName", "Service Center Name"),
grid.Column("Price", "Price", @<text>@String.Format("{0:C}", item.Price)</text>),
grid.Column("Description", "Description"),
grid.Column("VehicleRecall", "Vehicle Recall", item => Recall(item.VehicleRecall)),
grid.Column(format:
@<div class='btn-group'>
@Html.ActionLink("Details", "Details", new { id = item.VehicleServiceId }, new { @class = "btn btn-mini" })
@@ -60,3 +63,20 @@
htmlAttributes: new { @class = "table table-striped table-bordered table-hover table-condensed" },
numericLinksCount: 20
)
@helper Recall(SelectListViewModel selectList)
{
if (selectList != null && selectList.Selected > 0)
{
var selected = selectList.Available.FirstOrDefault(i => i.Value == selectList.Selected.ToString());
if (selected != null)
{
@Html.ActionLink(selected.Text, "Details", "VehicleRecall", new { id = selected.Value }, null)
}
}
else
{
<span class="muted">(Not a recall)</span>
}
}
@@ -0,0 +1,11 @@
@using MileageTraker.Web.ViewModels.VehicleService
@model MileageTraker.Web.ViewModels.VehicleService.VehicleServiceViewModel
@{
ViewBag.Title = "Record Vehicle Service";
}
<h2 class="center-content"><i class="fa fa-wrench"></i> @ViewBag.Title</h2>
<h4 class="center-content">Track completed service for a vehicle</h4>
@Html.Partial("EditorTemplates/VehicleSelect", new VehicleSelectViewModel())
@@ -0,0 +1,2 @@
@model MileageTraker.Web.ViewModels.SelectListViewModel
@Html.EditorForModel()
+1 -1
View File
@@ -34,7 +34,7 @@
<system.net>
<mailSettings>
<smtp>
<network xdt:Transform="SetAttributes" host="Exchange2010.ethra.org" />
<network xdt:Transform="SetAttributes" enableSsl="true" host="smtp.office365.com" port="587" userName="donotreply@ethra.org" password="**ENTER PASSWORD***" />
</smtp>
</mailSettings>
</system.net>
+5 -5
View File
@@ -2,8 +2,8 @@
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
<connectionStrings>
<add name="MileageTrakerContext" connectionString="Data Source=LOCALHOST\SQLEXPRESS;Initial Catalog=MileageTraker;Integrated Security=True;Connect Timeout=60" providerName="System.Data.SqlClient" />
</connectionStrings>
@@ -14,17 +14,17 @@
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="enableSimpleMembership" value="false" />
<add key="AgencyName" value="" />
<add key="EmailFromAddress" value="Mileage Traker &lt;noreply@ethra.org&gt;" />
<add key="EmailFromAddress" value="Mileage Traker &lt;donotreply@ethra.org&gt;" />
<add key="ResetPasswordSubject" value="New Mileage Traker Password Request" />
<add key="ResetPasswordBody" value="Hello {1}, please open this link to set a new password for your Mileage Traker account: {0}" />
<add key="InitializePasswordSubject" value="Initialize Mileage Traker Account" />
<add key="InitializetPasswordBody" value="Hello {1}, welcome to Mileage Traker. Your username is {2}. Please open this link to initialize your password: {0}" />
<add key="ServiceReminderSubject" value="Vehicle Serivce Reminder for {0}" />
<add key="ServiceReminderSubject" value="Vehicle Service Reminder for {0}" />
<add key="ServiceReminderBody" value="Hello {0}, please note the following vehicles due for service: {1}" />
</appSettings>
<system.net>
<mailSettings>
<smtp deliveryMethod="Network" from="Mileage Traker &lt;roreply@ethra.org&gt;">
<smtp deliveryMethod="Network" from="Mileage Traker &lt;donotreply@ethra.org&gt;">
<network host="localhost" />
</smtp>
</mailSettings>
+34 -10
View File
@@ -63,23 +63,19 @@
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll</HintPath>
<Private>True</Private>
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
</Reference>
<Reference Include="ExcelLibrary, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ExcelLibrary.1.2011.7.30\lib\ExcelLibrary.dll</HintPath>
</Reference>
<Reference Include="Hangfire.Core, Version=1.5.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Hangfire.Core.1.5.2\lib\net45\Hangfire.Core.dll</HintPath>
<Private>True</Private>
<Reference Include="Hangfire.Core, Version=1.6.20.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Hangfire.Core.1.6.20\lib\net45\Hangfire.Core.dll</HintPath>
</Reference>
<Reference Include="Hangfire.SqlServer, Version=1.5.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Hangfire.SqlServer.1.5.2\lib\net45\Hangfire.SqlServer.dll</HintPath>
<Private>True</Private>
<Reference Include="Hangfire.SqlServer, Version=1.6.20.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Hangfire.SqlServer.1.6.20\lib\net45\Hangfire.SqlServer.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Owin, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -160,16 +156,27 @@
<Compile Include="Attributes\MileageLogTypeValid.cs" />
<Compile Include="Attributes\LogOwnerAuthorizeAttribute.cs" />
<Compile Include="Attributes\NoEditLabelAttribute.cs" />
<Compile Include="Attributes\OptionLabelAttribute.cs" />
<Compile Include="Attributes\UnitsAttribute.cs" />
<Compile Include="Attributes\UserActivityAttribute.cs" />
<Compile Include="Context\MileageTrakerContext.cs" />
<Compile Include="Controllers\AccountController.cs" />
<Compile Include="Controllers\CityController.cs" />
<Compile Include="Controllers\ControllerBase.cs" />
<Compile Include="Controllers\VehicleRecallController.cs" />
<Compile Include="Email\ServiceReminderEmail.cs" />
<Compile Include="Email\ServiceReminderEmailService.cs" />
<Compile Include="Migrations\202008300135173_VehicleRecall.cs" />
<Compile Include="Migrations\202008300135173_VehicleRecall.Designer.cs">
<DependentUpon>202008300135173_VehicleRecall.cs</DependentUpon>
</Compile>
<Compile Include="Models\VehicleRecall.cs" />
<Compile Include="Startup.cs" />
<Compile Include="ViewModels\DriverMileageFlattenedViewModel.cs" />
<Compile Include="ViewModels\User\UserResultsViewModel.cs" />
<Compile Include="ViewModels\VehicleRecall\VehicleRecallViewModel.cs" />
<Compile Include="ViewModels\VehicleRecall\VehicleRecallResultsViewModel.cs" />
<Compile Include="ViewModels\VehicleService\VehicleSelectViewModel.cs" />
<Compile Include="ViewModels\VehicleService\UpdateServiceRemindersViewModel.cs" />
<Compile Include="Controllers\FuelLogController.cs" />
<Compile Include="Controllers\ServiceReminderController.cs" />
@@ -295,6 +302,7 @@
<Compile Include="ViewModels\VehicleService\VehicleServiceViewModel.cs" />
<Compile Include="ViewModels\Vehicle\VehicleCostItem.cs" />
<Compile Include="ViewModels\Vehicle\VehicleCostReport.cs" />
<Compile Include="ViewModels\Vehicle\VehiclePartialDetailsQuick.cs" />
<Compile Include="ViewModels\Vehicle\VehicleViewModel.cs" />
<Compile Include="ViewModels\Vehicle\VehicleResultsViewModel.cs" />
<Compile Include="ViewModels\SelectListViewModel.cs" />
@@ -391,6 +399,19 @@
<Content Include="Views\Shared\PageTitle.cshtml" />
<Content Include="Views\VehicleService\Delete.cshtml" />
<Content Include="Views\ServiceReminder\Delete.cshtml" />
<Content Include="Views\Shared\EditorTemplates\VehicleSelect.cshtml" />
<Content Include="Views\VehicleRecall\Index.cshtml" />
<Content Include="Views\VehicleRecall\Empty.cshtml" />
<Content Include="Views\VehicleRecall\Create.cshtml" />
<Content Include="Views\VehicleRecall\Details.cshtml" />
<Content Include="Views\VehicleRecall\Delete.cshtml" />
<Content Include="Views\Vehicle\DetailsQuickPartial.cshtml" />
<Content Include="Views\VehicleRecall\Edit.cshtml" />
<Content Include="Views\Shared\DisplayTemplates\Details.cshtml" />
<Content Include="Views\Shared\DisplayTemplates\VehicleRecallSelectListViewModel.cshtml" />
<Content Include="Views\Shared\DisplayTemplates\VehicleServiceLink.cshtml" />
<Content Include="Views\VehicleService\VehicleRecallSelect.cshtml" />
<Content Include="Views\VehicleService\SelectVehicle.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\Account.Login.css" />
@@ -629,6 +650,9 @@
<EmbeddedResource Include="Migrations\201510150220550_ServiceReminder.resx">
<DependentUpon>201510150220550_ServiceReminder.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\202008300135173_VehicleRecall.resx">
<DependentUpon>202008300135173_VehicleRecall.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
+4 -4
View File
@@ -2,12 +2,12 @@
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="CsvHelper" version="2.13.2.0" targetFramework="net45" />
<package id="EntityFramework" version="6.1.3" targetFramework="net45" />
<package id="EntityFramework" version="6.2.0" targetFramework="net45" />
<package id="ExcelLibrary" version="1.2011.7.30" />
<package id="FontAwesome" version="4.4.0" targetFramework="net45" />
<package id="Hangfire" version="1.5.2" targetFramework="net45" />
<package id="Hangfire.Core" version="1.5.2" targetFramework="net45" />
<package id="Hangfire.SqlServer" version="1.5.2" targetFramework="net45" />
<package id="Hangfire" version="1.6.20" targetFramework="net45" />
<package id="Hangfire.Core" version="1.6.20" targetFramework="net45" />
<package id="Hangfire.SqlServer" version="1.6.20" targetFramework="net45" />
<package id="JonSkeet.MiscUtil" version="0.1" targetFramework="net40" />
<package id="jQuery" version="2.1.4" targetFramework="net45" />
<package id="jQuery.Migrate" version="1.2.1" targetFramework="net40" />