Add vehicle recall

This commit is contained in:
2020-09-20 22:07:13 -04:00
parent b5589103ec
commit 6f031c5cb6
34 changed files with 890 additions and 45 deletions
+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; }
+11 -1
View File
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
@@ -32,7 +33,16 @@ namespace MileageTraker.Web.Controllers
public PartialViewResult DetailsPartial(string id)
{
var vehicle = DataService.GetVehicle(id);
return PartialView(new VehiclePartialDetails(vehicle));
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()
+104
View File
@@ -0,0 +1,104 @@
using System.Linq;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
using MileageTraker.Web.Utility;
using MileageTraker.Web.ViewModels.ServiceReminder;
using MileageTraker.Web.ViewModels.VehicleRecall;
namespace MileageTraker.Web.Controllers
{
[Authorize(Roles = "Administrator, Developer")]
public class VehicleRecallController : ControllerBase
{
public ActionResult Index()
{
var vehicleRecalls = DataService.GetOpenVehicleRecalls().ToList();
if (vehicleRecalls.Count == 0)
return View("Empty");
var viewModel = vehicleRecalls.Select(vr => new VehicleRecallViewModel(vr));
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();
vehicleRecall.Vehicle = DataService.GetVehicle(viewModel.VehicleId);
DataService.AddVehicleRecall(vehicleRecall);
SetStatusMessage(
string.Format("Vehicle Recall for vehicle {0} created", viewModel.VehicleId), 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)
{
DataService.DeleteVehicleRecall(id);
SetStatusMessage("Vehicle Recall 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);
}
}
}
+67 -21
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;
@@ -68,55 +69,97 @@ namespace MileageTraker.Web.Controllers
{
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 Create()
{
return View();
return View(HydrateViewModel(new VehicleServiceViewModel()));
}
[Authorize(Roles = "Administrator, Developer")]
[HttpGet]
[RequireRequestValue("vehicleId")]
public ActionResult Create(string vehicleId)
{
return View(new VehicleServiceViewModel{VehicleId = vehicleId});
{
return View(HydrateViewModel(new VehicleServiceViewModel(), vehicleId: vehicleId));
}
[HttpPost]
[RequireRequestValue("serviceVehicleId")]
public ActionResult CreateDriver(string serviceVehicleId)
{
return View ("Create", new VehicleServiceViewModel{VehicleId = serviceVehicleId });
return View ("Create", HydrateViewModel(new VehicleServiceViewModel(), vehicleId: serviceVehicleId));
}
[HttpPost]
private VehicleServiceViewModel HydrateViewModel(VehicleServiceViewModel viewModel,
int vehicleServiceId = Int32.MinValue, string vehicleId = null)
{
if (vehicleId != null)
{
viewModel.VehicleId = vehicleId;
}
viewModel.VehicleRecall
= new SelectListViewModel
{
Available = GetVehicleRecallSelectList(
viewModel.VehicleId,
vehicleServiceId)
};
viewModel.VehicleRecall.Selected =
viewModel.VehicleRecall.Available.SelectedValue != null
? (int?) int.Parse((string)viewModel.VehicleRecall.Available.SelectedValue)
: null;
return viewModel;
}
private SelectList 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);
return selectList;
}
[HttpPost]
[ActionLog]
public ActionResult Create(VehicleServiceViewModel viewModel)
{
if (ModelState.IsValid)
{
if (ModelState.IsValid)
{
var vehicleService = viewModel.GetVehicleService();
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]
[HttpGet]
public ActionResult UpdateServiceReminders(string vehicleId)
{
var vehicle = DataService.GetVehicle(vehicleId);
var viewModel = new UpdateServiceRemindersViewModel { VehicleId = vehicleId };
var viewModel = new UpdateServiceRemindersViewModel { VehicleId = vehicleId};
RefreshServiceReminderViewModel(viewModel, vehicle, true);
@@ -208,9 +251,9 @@ namespace MileageTraker.Web.Controllers
[Authorize(Roles = "Administrator, Developer")]
public ActionResult Edit(int id)
{
var vehicleService = DataService.GetVehicleService(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")]
@@ -218,7 +261,7 @@ namespace MileageTraker.Web.Controllers
{
var vehicleService = DataService.GetVehicleService(id);
var viewModel = new VehicleServiceViewModel(vehicleService);
return View(viewModel);
return View(HydrateViewModel(viewModel, vehicleServiceId: vehicleService.VehicleServiceId));
}
[Authorize(Roles = "Administrator, Developer")]
@@ -237,16 +280,19 @@ namespace MileageTraker.Web.Controllers
[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);
SetStatusMessage("Changes saved for vehicle service " + vehicleService.Vehicle.VehicleId);
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)
+79 -2
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();
}
@@ -990,7 +995,79 @@ namespace MileageTraker.Web.DAL
public const int ServiceReminderDefaultMileageDelta = 5000;
public const int ServiceReminderUpcomingMileageThreshold = 300;
#endregion
#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
}
}
+7 -4
View File
@@ -68,19 +68,22 @@ 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
+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; }
}
}
+4 -2
View File
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MileageTraker.Web.Models
{
@@ -8,7 +9,7 @@ namespace MileageTraker.Web.Models
[Key]
public int VehicleServiceId { get; set; }
[Required]
[Required]
public virtual Vehicle Vehicle { get; set; }
[Required]
@@ -24,10 +25,11 @@ namespace MileageTraker.Web.Models
[StringLength(32)]
public string InvoiceNumber { get; set; }
[Required]
public decimal Price { get; set; }
[StringLength(64, MinimumLength = 3, ErrorMessage = "Minimum 3 characters")]
public string Description { get; set; }
}
}
}
+23
View File
@@ -220,6 +220,7 @@ function addButtonIcons () {
'Cities': 'map',
'Purposes': 'arrow-right',
'Vehicle Service': 'wrench',
'Vehicle Recall': 'refresh',
'Vehicle': 'car',
'Cost': 'money',
'Reminder': 'clock-o',
@@ -385,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 */
+1 -1
View File
@@ -5,7 +5,7 @@ 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()
{
@@ -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,60 @@
using System.Collections.Generic;
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; }
[HiddenInput(DisplayValue = false)]
[Display(Name = "Vehicle Service")]
[UIHint("VehicleServiceLink")]
public int CompletedService_VehicleServiceId { 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
{
@@ -1,13 +1,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
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; }
@@ -41,6 +43,11 @@ namespace MileageTraker.Web.ViewModels.VehicleService
[Currency]
public decimal Price { get; set; }
[Display(Name = "Vehicle Recall")]
[OptionLabel("Not a recall")]
[UIHint("VehicleRecallSelectListViewModel")]
public SelectListViewModel VehicleRecall { get; set; }
[StringLength(64, MinimumLength = 3, ErrorMessage = "Minimum 3 characters")]
public string Description { get; set; }
@@ -51,14 +58,16 @@ 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 +75,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"});
}
}
}
}
}
+6 -3
View File
@@ -17,7 +17,10 @@
</div>
<div class="btn-toolbar center-content well">
@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("Vehicle Details", "Details", "Vehicle", new { id = Model.VehicleId }, new{@class="btn"})
<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", new { id = Model.VehicleRecallId }, new { @class = "btn" })
@Html.ActionLink("Delete", "Delete", 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,12 @@
@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)
}
}
}
@@ -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,5 @@
@model MileageTraker.Web.ViewModels.SelectListViewModel
@{
Layout = "~/Views/Shared/EditorTemplates/_FieldLayout.cshtml";
}
@Html.DropDownList("", new List<SelectListItem>(new List<SelectListItem>{new SelectListItem{Text = "Not a recall", Value = "None"}}))
+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"))
+6 -3
View File
@@ -36,9 +36,12 @@
<li>
@Html.ActionLink("View Reminders", "Index", "ServiceReminder", new { VehicleId = Model.VehicleId }, null)
</li>
<li>
@Html.ActionLink("Add Service", "Create", "VehicleService", new { VehicleId = Model.VehicleId }, null)
</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>
@Html.ActionLink("Logs", "Index", "Log", new { Model.VehicleId}, new { @class = "btn" })
@@ -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 }, 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.VehicleId }, 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>
+30
View File
@@ -0,0 +1,30 @@
@model IEnumerable<MileageTraker.Web.ViewModels.VehicleRecall.VehicleRecallViewModel>
@{
ViewBag.Title = "Vehicle Recalls";
var grid = new WebGrid(Model, rowsPerPage: 45);
}
@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" })
<a class="qtip-show-next-div btn">Open Recalls @Model.Count()</a>
</div>
@grid.GetHtml(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>)
),
htmlAttributes: new { @class = "table table-striped table-bordered table-hover table-condensed"},
numericLinksCount: 20
)
+23
View File
@@ -156,17 +156,25 @@
<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\VehicleService\VehicleSelectViewModel.cs" />
<Compile Include="ViewModels\VehicleService\UpdateServiceRemindersViewModel.cs" />
<Compile Include="Controllers\FuelLogController.cs" />
@@ -293,6 +301,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" />
@@ -390,6 +399,17 @@
<Content Include="Views\VehicleService\Delete.cshtml" />
<Content Include="Views\ServiceReminder\Delete.cshtml" />
<Content Include="Views\CreateLog\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\EditorTemplates\VehicleRecallIdSelect.cshtml" />
<Content Include="Views\Shared\DisplayTemplates\Details.cshtml" />
<Content Include="Views\Shared\DisplayTemplates\VehicleRecallSelectListViewModel.cshtml" />
<Content Include="Views\Shared\DisplayTemplates\VehicleServiceLink.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\Account.Login.css" />
@@ -628,6 +648,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>