Fuel Log Import basic functionality

This commit is contained in:
2015-09-18 13:02:15 -04:00
parent 4987215f0b
commit e3590b29e5
18 changed files with 438 additions and 59 deletions
@@ -0,0 +1,46 @@
using System;
using MileageTraker.Web.ViewModels.FuelLog;
using NUnit.Framework;
namespace Web.Tests.ViewModels.FuelLog
{
[TestFixture]
public class ImportFuelLogViewModelTests
{
private static readonly ImportFuelLogViewModel Iflvm = new ImportFuelLogViewModel
{
Date = new DateTime(2015, 10, 1, 3, 2, 1),
DriverFullName = "Bob Dobalina",
TagNumber = "TG2832",
Odometer = 98323,
CityName = "Knoxville",
MPG = 23.1,
GasPurchased = 2.123,
TotalPrice = 4.32M
};
[Test]
public void Converts_To_FuelLog()
{
var fuelLog = Iflvm.GetFuelLog();
Assert.That(fuelLog.Date, Is.EqualTo(Iflvm.Date));
}
[Test]
public void Converts_To_FuelLog_And_Back()
{
var fuelLog = Iflvm.GetFuelLog();
var importFuelLogViewModel = new ImportFuelLogViewModel(fuelLog);
Assert.That(importFuelLogViewModel.TotalPrice, Is.EqualTo(Iflvm.TotalPrice));
}
[Test]
public void Converts_FuelLogLogId()
{
var fuelLog = Iflvm.GetFuelLog();
fuelLog.Log = new MileageTraker.Web.Models.Log {LogId = 123};
var importFuelLogViewModel = new ImportFuelLogViewModel(fuelLog);
Assert.That(importFuelLogViewModel.TotalPrice, Is.EqualTo(Iflvm.TotalPrice));
}
}
}
+1
View File
@@ -108,6 +108,7 @@
<Compile Include="Utility\NameNormalizerTests.cs" />
<Compile Include="ViewModels\CreateLog\CreateLogViewModelTests.cs" />
<Compile Include="ViewModels\CreateLog\LogImportViewModelTests.cs" />
<Compile Include="ViewModels\FuelLog\ImportFuelLogViewModelTests.cs" />
<Compile Include="ViewModels\Log\LogQueryViewModelTests.cs" />
<Compile Include="ViewModels\Log\LogViewModelTests.cs" />
<Compile Include="ViewModels\User\CreateUserViewModelTests.cs" />
+69 -13
View File
@@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
using MileageTraker.Web.Models;
using MileageTraker.Web.Utility;
using MileageTraker.Web.ViewModels.FuelLog;
@@ -40,7 +39,7 @@ namespace MileageTraker.Web.Controllers
// orderby log. descending
// select log).ToList();
var viewModel = new FuelLogResultsViewModel(fuelLogs, query, CustomExtensions.YearMonthList(validLogYearMonths));
var viewModel = new ResultsViewModel(fuelLogs, query, CustomExtensions.YearMonthList(validLogYearMonths));
//Session.Add("FuelLogPage", Request.Url.PathAndQuery);
@@ -55,7 +54,8 @@ namespace MileageTraker.Web.Controllers
}
[HttpPost]
public ActionResult Import(FuelLogImportUploadViewModel viewModel)
[ActionLog]
public ActionResult Import(ImportUploadViewModel viewModel)
{
if (ModelState.IsValid && viewModel.File != null && viewModel.File.ContentLength > 0)
{
@@ -66,17 +66,23 @@ namespace MileageTraker.Web.Controllers
try
{
var logImports = FuelmanCsvImporter.Import(fileInfo);
// todo: add to the database
DataService.AddFuelLogs(logImports);
var fuelLogs = FuelmanCsvImporter.Import(fileInfo);
// todo: delete file?
return View(logImports.ToList());
var fls = (from fuelLog in fuelLogs
let prevAdds = DataService.GetDuplicateFuelLogs(fuelLog)
select new {ImportedFuelLog = fuelLog, PrevAdded = prevAdds.FirstOrDefault()}).ToList();
// add new logs to the database
DataService.AddFuelLogs(fls.Where(fl => fl.PrevAdded == null).Select(fl => fl.ImportedFuelLog));
var vms = from fl in fls
let vm = fl.PrevAdded == null
? new ImportFuelLogViewModel(fl.ImportedFuelLog)
: new ImportFuelLogViewModel(fl.PrevAdded) {PreviouslyAdded = true}
select vm;
return View(vms.ToList());
}
//catch (OutOfMemoryException)
//{
// TempData["StatusMessage"] = "Problem reading excel document - please verify that the document is in Excel 97-2003 Workbook (.xls) format";
// TempData["StatusMessage-Type"] = "alert-error";
//}
catch (Exception ex)
{
TempData["StatusMessage"] = "Problem reading document: " + ex.Message;
@@ -90,6 +96,56 @@ namespace MileageTraker.Web.Controllers
}
return RedirectToAction("ImportUpload");
}
enum MatchStatus
{
Match,
NoMatch,
Error
}
[HttpPost]
public ActionResult Match(int fuelLogId)
{
var fuelLog = DataService.GetFuelLog(fuelLogId);
if (fuelLog == null)
{
return Json(new
{
Status = MatchStatus.Error.ToString(),
Message = "Fuel Log not found with given ID: " + fuelLogId
}, JsonRequestBehavior.AllowGet);
}
if (fuelLog.Log != null)
{
return Json(new
{
Status = MatchStatus.NoMatch.ToString(),
Message = "Already matched to log",
Action = RenderRazorViewToString("ImportMatchLogView", fuelLog.Log.LogId)
}, JsonRequestBehavior.AllowGet);
}
// run the match
var matchingLog = DataService.GetMatchingLog(fuelLog);
if (matchingLog == null)
{
return Json(new
{
Status = MatchStatus.NoMatch.ToString(),
Message = "Unable to find match"
}, JsonRequestBehavior.AllowGet);
}
fuelLog.Log = matchingLog;
DataService.UpdateFuelLog(fuelLog);
return Json(new
{
Status = MatchStatus.Match.ToString(),
Action = RenderRazorViewToString("ImportMatchedLog", new ImportMatchedLogViewModel { LogId = fuelLog.Log.LogId })
}, JsonRequestBehavior.AllowGet);
}
#endregion
}
}
+1 -2
View File
@@ -259,10 +259,9 @@ namespace MileageTraker.Web.Controllers
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
viewModel.File.SaveAs(path);
IEnumerable<ImportLogViewModel> logImports;
try
{
logImports = LogImporter.Import(path);
var logImports = LogImporter.Import(path);
// todo: delete file?
return View(logImports.ToList());
}
+49 -1
View File
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Text.RegularExpressions;
using MileageTraker.Web.Context;
using MileageTraker.Web.Models;
using MileageTraker.Web.Utility;
@@ -409,6 +409,20 @@ namespace MileageTraker.Web.DAL
return _db.Vehicles.Find(id);
}
public Vehicle GetVehicleByTag(string tagNumber)
{
var vehicle = GetVehicles().FirstOrDefault(v => v.TagNumber == tagNumber);
if (vehicle != null)
return vehicle; // exact match, this is optimal for the DB query
// no match, normalize the tags, have to get all the vehicles for regex
var vehicles = GetVehicles().ToList();
Func<string, string> b = s => Regex.Replace(s.ToLower(), @"-|\s", "");
vehicle = vehicles.FirstOrDefault(v => b(v.TagNumber) == b(tagNumber));
return vehicle;
}
public void UpdateCurrentOdometer(string vehicleId)
{
var mostRecentOdometerQuery =
@@ -630,6 +644,40 @@ namespace MileageTraker.Web.DAL
return _db.FuelLogs.Find(id);
}
public IEnumerable<FuelLog> GetDuplicateFuelLogs(FuelLog log)
{
return
from dbLog in GetFuelLogs()
where
dbLog.Date == log.Date &&
dbLog.GasPurchased == log.GasPurchased &&
dbLog.TagNumber == log.TagNumber
select dbLog;
}
public Log GetMatchingLog(FuelLog fuelLog)
{
var logs = GetLogs();
// matching by Date, Gas Purchased (gallons), and Vehicle
var vehicle = GetVehicleByTag(fuelLog.TagNumber);
if (vehicle != null)
logs = logs.Where(log => log.VehicleId == vehicle.VehicleId);
else return null;
logs = logs.Where(log =>
log.Date.Year == fuelLog.Date.Year &&
log.Date.Month == fuelLog.Date.Month &&
log.Date.Day == fuelLog.Date.Day
);
logs = logs.Where(log => log.GasPurchased == fuelLog.GasPurchased);
//logs = logs.Where(log => log.User.FullName == fuelLog.DriverFullName);
//logs = logs.Where(log => log.EndOdometer == fuelLog.Odometer);
return logs.FirstOrDefault();
}
public IList<DateTime> GetValidFuelLogMonths()
{
+1
View File
@@ -10,6 +10,7 @@ namespace MileageTraker.Web.Models
[Required]
[DataType(DataType.Date)]
[DisplayFormatAttribute(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
public DateTime Date { get; set; }
[Required]
+61
View File
@@ -0,0 +1,61 @@
function importFuelLogs() {
$('.breadcrumb').hide();
$('tr:not(.complete) .match-status').append('<span class="label">Pending</span');
var total = $("#fuellogs > tbody > tr:not(.complete)").length;
$('#page-match-status').html('<span class="label label-warning"><i class="fa fa-spinner fa-spin"></i> Matching In Progress</span> <strong>Keep page open until complete.</strong>');
$('#page-match-status').after('<div class="progress progress-striped active"><div class="bar" style="width:0%"></div><div>');
submitNext();
var failureCount = 0;
function submitNext() {
var $fuelLogs = $("#fuellogs > tbody > tr:not(.complete)");
var percentComplete = Math.round( (1 - ($fuelLogs.length / total)) * 100 );
$('.progress .bar').attr('style', 'width:' + percentComplete + '%');
if ($fuelLogs.length > 0) {
var $row = $($fuelLogs[0]);
var data = $('form', $row).serialize();
var url = $('form', $row).attr('action');
$('.match-status', $row).html('<span class="label label-info"><i class="fa fa-spinner fa-spin"></i> Submitting</span>');
$.ajax({
url: url,
type: 'post',
data: data,
success: function (result) {
$row.addClass("complete");
if (result.Status == "Match") {
$('.match-status', $row).html('<span class="label label-success">Match found</span>');
}
else if (result.Status == "NoMatch" || result.Status == "Error") {
if (result.Status == "NoMatch") {
$('.match-status', $row).html('<span class="label label-warning">No Match</span>');
} else {
$('.match-status', $row).html('<span class="label label-important">Error</span>');
}
$('.match-message', $row).text(result.Message);
failureCount++;
$('.progress .bar').addClass('bar-warning');
}
if (result.Action != undefined && result.Action != null) {
$('.match-status', $row).append(" " + result.Action);
}
submitNext();
}
});
} else {
$('.breadcrumb').show();
$('.progress').removeClass('progress-striped');
$('.progress').removeClass('active');
if (failureCount == 0) {
$('#page-match-status').html('<span class="label">Complete</span> with all matches.');
$('.progress .bar').addClass('bar-success');
} else {
$('#page-match-status').html('<span class="label label-warning">Complete</span> but with errors. See details below.');
}
}
}
}
@@ -0,0 +1,68 @@
using System;
using System.ComponentModel.DataAnnotations;
using AutoMapper;
namespace MileageTraker.Web.ViewModels.FuelLog
{
public class ImportFuelLogViewModel
{
public int FuelLogId { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
public DateTime Date { get; set; }
[Required]
[StringLength(128)]
public string DriverFullName { get; set; }
[Required]
[Display(Name = "Tag#")]
public string TagNumber { get; set; }
[Required]
public int Odometer { get; set; }
[StringLength(64)]
public string CityName { get; set; }
public double MPG { get; set; }
[Required]
public double GasPurchased { get; set; }
[Required]
public decimal TotalPrice { get; set; }
public bool PreviouslyAdded { get; set; }
public int? LogId { get; set; }
static ImportFuelLogViewModel()
{
Mapper.CreateMap<ImportFuelLogViewModel, Models.FuelLog>();
Mapper.CreateMap<Models.FuelLog, ImportFuelLogViewModel>()
.ForMember(dest => dest.LogId,
opt => opt.ResolveUsing(
fl => fl.Log != null ? (int?)fl.Log.LogId : null
));
}
public ImportFuelLogViewModel(Models.FuelLog fuelLog)
{
Mapper.Map(fuelLog, this);
}
public ImportFuelLogViewModel()
{
}
public Models.FuelLog GetFuelLog()
{
var log = new Models.FuelLog();
Mapper.Map(this, log);
return log;
}
}
}
@@ -0,0 +1,7 @@
namespace MileageTraker.Web.ViewModels.FuelLog
{
public class ImportMatchedLogViewModel
{
public int LogId { get; set; }
}
}
@@ -3,10 +3,10 @@ using System.Web;
namespace MileageTraker.Web.ViewModels.FuelLog
{
public class FuelLogImportUploadViewModel
public class ImportUploadViewModel
{
[Required]
[Display(Name = "FuelMan CSV File")]
[Display(Name = @"FuelMan CSV/Text Data File")]
public HttpPostedFileBase File { get; set; }
}
}
@@ -1,10 +1,9 @@
using System.Collections.Generic;
using MileageTraker.Web.Models;
using MileageTraker.Web.ViewModels.Log;
using System.Globalization;
namespace MileageTraker.Web.ViewModels.FuelLog
{
public class FuelLogResultsViewModel
public class ResultsViewModel
{
public IEnumerable<Models.FuelLog> Logs { get; set; }
public Dictionary<string, List<string>> AvailableYearMonths { get; set; }
@@ -19,12 +18,12 @@ namespace MileageTraker.Web.ViewModels.FuelLog
public string Year { get; set; }
public string Month { get; set; }
public FuelLogResultsViewModel(IEnumerable<Models.FuelLog> logs, FuelLogQueryViewModel query, Dictionary<string, List<string>> availableYearMonths)
public ResultsViewModel(IEnumerable<Models.FuelLog> logs, FuelLogQueryViewModel query, Dictionary<string, List<string>> availableYearMonths)
{
Logs = logs;
AvailableYearMonths = availableYearMonths;
Year = query.Year.HasValue ? query.Year.Value.ToString() : string.Empty;
Month = query.Month.HasValue ? query.Month.Value.ToString() : string.Empty;
Year = query.Year.HasValue ? query.Year.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;
Month = query.Month.HasValue ? query.Month.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;
}
}
}
+9
View File
@@ -0,0 +1,9 @@
@{
ViewBag.Title = "No Fuel Logs";
}
<h2 class="center-content">@ViewBag.Title</h2>
<div class="center-content well">
No Fuel logs have been added yet. @Html.ActionLink("Import", "ImportUpload", null, new { @class = "btn" })
</div>
+36 -30
View File
@@ -1,4 +1,5 @@
@model IList<MileageTraker.Web.Models.FuelLog>
@using MileageTraker.Web.ViewModels.FuelLog
@model IList<ImportFuelLogViewModel>
@{
ViewBag.Title = "Import Fuel Logs";
@@ -8,58 +9,63 @@
<link href="@Url.Content("~/Content/font-awesome.min.css")" rel="stylesheet" type="text/css" />
}
@{ Html.RenderPartial("BackToLogs"); }
@Html.Partial("_StatusMessage")
<h2>@ViewBag.Title</h2>
<p>Driver: <strong>@ViewData["UserFullName"]</strong></p>
<h5>Matching Mileage Logs based on Date, Vehicle, and Gas Purchased</h5>
<p id="page-import-status"></p>
<p id="page-match-status"></p>
<table id="logs" class="table table-striped table-bordered table-hover table-condensed">
<table id="fuellogs" class="table table-striped table-bordered table-hover table-condensed">
<thead>
<tr>
<th>Import Status</th>
<th style="width:20%"></th>
<th>Vehicle ID</th>
<th>End Odometer</th>
<th>Type</th>
<th>Destination City</th>
<th>Purpose</th>
<th>Notes</th>
<th>Gas Purchased</th>
<th>Match Status</th>
<th style="width:15%"></th>
<th>Date</th>
<th>Driver</th>
<th>Tag Number</th>
<th>Odometer</th>
<th>MPG</th>
<th>Gas Purchased</th>
<th>Total Price</th>
</tr>
</thead>
@for (var i = 0; i < Model.Count; i++)
{
var viewModel = Model[i];
<tr id="log-@i">
@using (Html.BeginForm("ImportCreate", "Log", FormMethod.Post))
<tr id="fuellog-@i" @if (viewModel.PreviouslyAdded && viewModel.LogId != null) { <text>class="complete"</text>}>
@using (Html.BeginForm("Match", "FuelLog", FormMethod.Post))
{
@Html.EditorFor(x => viewModel)
<input type="hidden" name="fuelLogId" value="@viewModel.FuelLogId"/>
}
<td class="import-status"></td>
<td class="import-message"></td>
<td>@Html.ValueFor(x => viewModel.VehicleId)</td>
<td>@Html.ValueFor(x => viewModel.EndOdometer)</td>
<td>@Html.ValueFor(x => viewModel.LogType)</td>
<td>@Html.ValueFor(x => viewModel.CityName)</td>
<td>@Html.ValueFor(x => viewModel.Purpose)</td>
<td>@Html.ValueFor(x => viewModel.Notes)</td>
<td>@Html.ValueFor(x => viewModel.GasPurchased)</td>
<td>@Html.ValueFor(x => viewModel.Date)</td>
<td class="match-status">
@if (viewModel.PreviouslyAdded)
{
<span class="label label-info">Previously Imported</span>
}
@if (viewModel.LogId != null)
{
@Html.Partial("ImportMatchedLog", new ImportMatchedLogViewModel { LogId = viewModel.LogId.Value })
}
</td>
<td class="match-message"></td>
<td>@Html.ValueFor(x => viewModel.Date, "{0:d}")</td>
<td>@Html.ValueFor(x => viewModel.DriverFullName)</td>
<td>@Html.ValueFor(x => viewModel.TagNumber)</td>
<td>@Html.ValueFor(x => viewModel.Odometer)</td>
<td>@Html.ValueFor(x => viewModel.MPG)</td>
<td>@Html.ValueFor(x => viewModel.GasPurchased, "{0:0.000}")</td>
<td>@Html.ValueFor(x => viewModel.TotalPrice, "{0:C}")</td>
</tr>
}
</table>
@section Scripts
{
<script src="@Url.Content("~/Scripts/Shared/ImportCreate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/Shared/FuelLogImport.js")" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
importLogs("@ViewData["UserFullName"]");
importFuelLogs();
});
</script>
}
@@ -0,0 +1,5 @@
@model MileageTraker.Web.ViewModels.FuelLog.ImportMatchedLogViewModel
@{
Layout = null;
}
@Html.ActionLink("View Log", "Details", "Log", new{id=Model.LogId}, new{@class="btn btn-mini", target="_blank"})
+1 -1
View File
@@ -1,4 +1,4 @@
@model MileageTraker.Web.ViewModels.FuelLog.FuelLogImportUploadViewModel
@model MileageTraker.Web.ViewModels.FuelLog.ImportUploadViewModel
@{
ViewBag.Title = "Import Fuel Logs";
}
+67
View File
@@ -0,0 +1,67 @@
@using MileageTraker.Web.Utility
@model MileageTraker.Web.ViewModels.FuelLog.ResultsViewModel
@{
ViewBag.Title = "Fuel Logs";
var grid = new WebGrid(Model.Logs, rowsPerPage: 45);
var parameters = new {Model.Year, Model.Month};
}
@section Styles {
<link href="@Url.Content("~/Content/VehicleColors.css")" rel="stylesheet" type="text/css" />
}
@section Scripts {
<script type="text/javascript">
var availableLogYearMonths = @Html.Raw(Json.Encode(Model.AvailableYearMonths));
@if (Model.Year != null)
{
<text>var selectedYear = "@Model.Year";</text>
<text>var selectedMonth = "@Model.Month";</text>
}
</script>
}
@Html.Partial("_StatusMessage")
<div class="btn-toolbar pull-right">
@using (Html.BeginForm("Index", "Log", FormMethod.Get, new { id = "filter", @class = "form" }))
{
<div class="">
@*@Html.EditorForModel()*@
</div>
}
</div>
<h2 id="log-title">@ViewBag.Title</h2>
<div class="btn-toolbar clearfix">
@Html.ActionLink("Import", "ImportUpload", null, new { @class = "btn" })
@Html.ActionLink("Export", "Export", parameters, new { @class = "btn" })
</div>
<div>
@grid.GetHtml(columns:
grid.Columns(
grid.Column("Date", format: item => item.Date.ToString("d")),
grid.Column("DriverFullName", "Driver Name"),
grid.Column("TagNumber"),
grid.Column("Odometer"),
grid.Column("MPG"),
grid.Column("GasPurchased", "Gas Purchased", @<text>@String.Format("{0:0.000}", item.GasPurchased)</text>),
grid.Column("TotalPrice", "Total Price", @<text>@String.Format("{0:C}", item.TotalPrice)</text>),
grid.Column("Log", "Matched Log", @<text>
@(item.Log != null
? Html.ActionLink("View Log", "Details", "Log", new {id = item.Log.LogId}, new {@class = "btn btn-mini", target="_blank"})
: Html.ActionLink("Match", "Match", new {id = item.FuelLogId}, new {@class = "btn btn-warning btn-mini", target="_blank"}))
</text>),
grid.Column("Total Results: " + Model.Logs.Count(), canSort:false, format:
@<div class='btn-group'> @Html.ActionLink("Details", "Details", new { id = item.FuelLogId }, new { @class = "btn btn-mini" }) </div>)),
htmlAttributes: new { @class = "table table-striped table-bordered table-hover table-condensed"},
numericLinksCount: 20
)
</div>
@if (!Model.Logs.Any())
{
<div>
No results.
</div>
}
+10 -4
View File
@@ -8,7 +8,7 @@
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{36D4C321-E918-460F-B348-16A805F88884}</ProjectGuid>
<ProjectTypeGuids>{E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MileageTraker.Web</RootNamespace>
@@ -230,9 +230,11 @@
<Compile Include="ViewModels\CreateLog\ImportUploadViewModel.cs" />
<Compile Include="ViewModels\DriverMileageItem.cs" />
<Compile Include="ViewModels\DriverMileageViewModel.cs" />
<Compile Include="ViewModels\FuelLog\FuelLogImportUploadViewModel.cs" />
<Compile Include="ViewModels\FuelLog\LogQueryViewModel.cs" />
<Compile Include="ViewModels\FuelLog\FuelLogResultsViewModel.cs" />
<Compile Include="ViewModels\FuelLog\ImportFuelLogViewModel.cs" />
<Compile Include="ViewModels\FuelLog\ImportMatchedLogViewModel.cs" />
<Compile Include="ViewModels\FuelLog\ImportUploadViewModel.cs" />
<Compile Include="ViewModels\FuelLog\FuelLogQueryViewModel.cs" />
<Compile Include="ViewModels\FuelLog\ResultsViewModel.cs" />
<Compile Include="ViewModels\Log\ImportLogViewModel.cs" />
<Compile Include="ViewModels\Log\ImportUploadViewModel.cs" />
<Compile Include="ViewModels\Log\LogViewModel.cs" />
@@ -292,6 +294,7 @@
<Content Include="Scripts\jquery.validate.min.js" />
<Content Include="Scripts\jquery.validate.unobtrusive.js" />
<Content Include="Scripts\jquery.validate.unobtrusive.min.js" />
<Content Include="Scripts\Shared\FuelLogImport.js" />
<Content Include="Views\Log\ImportFix.cshtml" />
<Content Include="Views\Shared\EditorTemplates\HttpPostedFileBase.cshtml" />
<Content Include="Views\City\Index.cshtml" />
@@ -299,6 +302,9 @@
<Content Include="Views\Shared\DisplayTemplates\LogQueryViewModel.cshtml" />
<Content Include="Views\FuelLog\ImportUpload.cshtml" />
<Content Include="Views\FuelLog\Import.cshtml" />
<Content Include="Views\FuelLog\Index.cshtml" />
<Content Include="Views\FuelLog\ImportMatchedLog.cshtml" />
<Content Include="Views\FuelLog\Empty.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\Account.Login.css" />