Feature: Device Importing - Initial

This commit is contained in:
Gary Sharp
2013-07-22 21:16:31 +10:00
parent ab3ad25944
commit a3aaed1d13
25 changed files with 748 additions and 20 deletions
+227
View File
@@ -0,0 +1,227 @@
using Disco.BI.Extensions;
using Disco.Data.Repository;
using Disco.Models.BI.Device;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PopulateRecordReferences = System.Tuple<System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceModel>, System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceProfile>, System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceBatch>>;
namespace Disco.BI.DeviceBI.Importing
{
internal static class Import
{
internal static void ImportRecord(this ImportDevice device, DiscoDataContext dbContext, PopulateRecordReferences references)
{
// Skips If Errors
if (device.Errors == null || device.Errors.Count == 0)
{
// Re-Populate & Skip If Errors
device.PopulateRecord(dbContext, references);
if (device.Errors == null || device.Errors.Count == 0)
{
Device discoDevice = device.Device;
if (discoDevice == null)
{
// New Device
discoDevice = new Device()
{
SerialNumber = device.SerialNumber.ToUpper(),
CreatedDate = DateTime.Now,
AllowUnauthenticatedEnrol = true,
};
dbContext.Devices.Add(discoDevice);
}
discoDevice.DeviceModelId = device.DeviceModelId;
discoDevice.DeviceProfileId = device.DeviceProfileId;
discoDevice.DeviceBatchId = device.DeviceBatchId;
discoDevice.Location = device.Location;
discoDevice.AssetNumber = device.AssetNumber;
if (discoDevice.AssignedUserId != device.AssignedUserId)
{
discoDevice.AssignDevice(dbContext, device.AssignedUser);
}
dbContext.SaveChanges();
}
}
}
internal static PopulateRecordReferences GetPopulateRecordReferences(DiscoDataContext dbContext)
{
return new PopulateRecordReferences(
dbContext.DeviceModels.ToDictionary(dm => dm.Id),
dbContext.DeviceProfiles.ToDictionary(dp => dp.Id),
dbContext.DeviceBatches.ToDictionary(db => db.Id)
);
}
internal static void PopulateRecord(this ImportDevice device, DiscoDataContext dbContext, PopulateRecordReferences references)
{
var deviceModels = references.Item1;
var deviceProfiles = references.Item2;
var deviceBatches = references.Item3;
// SERIAL NUMBER - Existing Device
if (!device.Errors.ContainsKey("SerialNumber"))
device.Device = dbContext.Devices.Find(device.SerialNumber);
// DEVICE MODEL
if (!device.Errors.ContainsKey("DeviceModelId"))
{
DeviceModel deviceModel;
if (!device.DeviceModelId.HasValue)
device.DeviceModelId = 1; // Default 'Unknown Device Model'
if (!deviceModels.TryGetValue(device.DeviceModelId.Value, out deviceModel))
device.Errors.Add("DeviceModelId", string.Format("Unknown device model id: {0}", device.DeviceModelId));
else
device.DeviceModel = deviceModel;
}
// DEVICE PROFILE
if (!device.Errors.ContainsKey("DeviceProfileId"))
{
DeviceProfile deviceProfile;
if (!deviceProfiles.TryGetValue(device.DeviceProfileId, out deviceProfile))
device.Errors.Add("DeviceProfileId", string.Format("Unknown device profile id: {0}", device.DeviceProfileId));
else
device.DeviceProfile = deviceProfile;
}
// DEVICE BATCH
if (!device.Errors.ContainsKey("DeviceBatchId") && device.DeviceBatchId.HasValue)
{
DeviceBatch deviceBatch;
if (!deviceBatches.TryGetValue(device.DeviceBatchId.Value, out deviceBatch))
device.Errors.Add("DeviceBatchId", string.Format("Unknown device Batch id: {0}", device.DeviceBatchId));
else
device.DeviceBatch = deviceBatch;
}
// ASSIGNED USER
if (!device.Errors.ContainsKey("AssignedUserId") && device.AssignedUserId != null)
{
try
{
device.AssignedUser = UserBI.UserCache.GetUser(device.AssignedUserId, dbContext, true);
}
catch (ArgumentException)
{
device.Errors.Add("AssignedUserId", string.Format("Unknown user id: {0}", device.AssignedUserId));
}
}
}
internal static ImportDevice ParseRecord(this string[] record)
{
int csvFieldCount = record.Length;
if (csvFieldCount < 1)
throw new ArgumentException("At least one CSV field is required (Serial Number)");
string csvSerialNumber;
string csvDeviceModelId;
int deviceModelId = 1; // Default 'Unknown Device Model'
string csvDeviceProfileId;
int deviceProfileId = 1; // 'Default' Profile
string csvDeviceBatchId;
int deviceBatchId = 0; // No Batch
string csvAssignedUserId = null;
string csvLocation = null;
string csvAssetNumber = null;
Dictionary<string, string> errors = new Dictionary<string, string>();
// SERIAL NUMBER
csvSerialNumber = record[0];
if (string.IsNullOrWhiteSpace(csvSerialNumber))
errors.Add("SerialNumber", "The serial number is required");
else if (csvSerialNumber.Trim().Length > 60)
errors.Add("SerialNumber", "The serial number must be less than or equal to 60 characters");
if (csvFieldCount > 1)
{
// DEVICE MODEL
csvDeviceModelId = record[1];
if (!string.IsNullOrWhiteSpace(csvDeviceModelId))
if (!int.TryParse(csvDeviceModelId, out deviceModelId))
errors.Add("DeviceModelId", "The device model is optional, but when supplied must be a number");
else if (deviceModelId < 1)
errors.Add("DeviceModelId", "The device model is optional, but when supplied must be greater than 0");
if (csvFieldCount > 2)
{
// DEVICE PROFILE
csvDeviceProfileId = record[2];
if (!string.IsNullOrWhiteSpace(csvDeviceProfileId))
if (!int.TryParse(csvDeviceProfileId, out deviceProfileId))
errors.Add("DeviceProfileId", "The device profile is optional, but when supplied must be a number");
else if (deviceProfileId < 1)
errors.Add("DeviceProfileId", "The device profile is optional, but when supplied must be greater than 0");
if (csvFieldCount > 3)
{
// DEVICE BATCH
csvDeviceBatchId = record[3];
if (!string.IsNullOrWhiteSpace(csvDeviceBatchId))
if (!int.TryParse(csvDeviceBatchId, out deviceBatchId))
errors.Add("DeviceBatchId", "The device batch is optional, but when supplied must be a number");
else if (deviceBatchId < 1)
errors.Add("DeviceBatchId", "The device batch is optional, but when supplied must be greater than 0");
if (csvFieldCount > 4)
{
// ASSIGNED USER
csvAssignedUserId = record[4];
if (string.IsNullOrWhiteSpace(csvAssignedUserId))
csvAssignedUserId = null; // Not Assigned
else if (csvAssignedUserId.Length > 50)
errors.Add("AssignedUserId", "The assigned user must be less than or equal to 50 characters");
if (csvFieldCount > 5)
{
// LOCATION
csvLocation = record[5];
if (string.IsNullOrWhiteSpace(csvLocation))
csvLocation = null; // No Location Specified
else if (csvLocation.Length > 250)
errors.Add("Location", "The location must be less than or equal to 250 characters");
if (csvFieldCount > 6)
{
// ASSET NUMBER
csvAssetNumber = record[6];
if (string.IsNullOrWhiteSpace(csvAssetNumber))
csvAssetNumber = null; // No Location Specified
else if (csvAssetNumber.Length > 40)
errors.Add("AssetNumber", "The asset number must be less than or equal to 40 characters");
}
}
}
}
}
}
return new ImportDevice()
{
SerialNumber = csvSerialNumber.Trim(),
DeviceModelId = deviceModelId,
DeviceProfileId = deviceProfileId,
DeviceBatchId = deviceBatchId == 0 ? (int?)null : deviceBatchId,
AssignedUserId = csvAssignedUserId,
Location = csvLocation,
AssetNumber = csvAssetNumber,
Errors = errors
};
}
}
}
@@ -0,0 +1,84 @@
using Disco.Data.Repository;
using Disco.Models.BI.Device;
using Disco.Models.Repository;
using Disco.Services.Tasks;
using LumenWorks.Framework.IO.Csv;
using Quartz;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Caching;
namespace Disco.BI.DeviceBI.Importing
{
public class ImportParseTask : ScheduledTask
{
public override string TaskName { get { return "Import Devices - Parsing"; } }
public override bool SingleInstanceTask { get { return false; } }
public override bool CancelInitiallySupported { get { return false; } }
internal const string ImportParseCacheKey = "ImportParseResults_{0}";
protected override void ExecuteTask()
{
MemoryStream csvStream = (MemoryStream)this.ExecutionContext.JobDetail.JobDataMap["CsvImport"];
this.Status.UpdateStatus(0, "Parsing CSV File", "Loading Records");
List<ImportDevice> records;
using (TextReader csvTextReader = new StreamReader(csvStream))
{
using (CsvReader csvReader = new CsvReader(csvTextReader, true))
{
csvReader.DefaultParseErrorAction = ParseErrorAction.ThrowException;
csvReader.MissingFieldAction = MissingFieldAction.ReplaceByNull;
records = csvReader.Select(record => record.ParseRecord()).ToList();
}
}
csvStream.Dispose();
this.Status.UpdateStatus(20, "Parsing CSV File", string.Format("Linking {0} Records", records.Count));
using (DiscoDataContext dbContext = new DiscoDataContext())
{
var populateReferences = Import.GetPopulateRecordReferences(dbContext);
DateTime lastUpdate = DateTime.Now;
foreach (var record in records)
{
record.PopulateRecord(dbContext, populateReferences);
if (DateTime.Now.Subtract(lastUpdate).TotalSeconds > 1)
{
// Update every second
this.Status.UpdateStatus((int)Math.Floor((((double)(records.IndexOf(record) + 1) / records.Count) * 80)));
lastUpdate = DateTime.Now;
}
}
}
// Set Results to Cache
string key = string.Format(ImportParseCacheKey, this.Status.SessionId);
HttpRuntime.Cache.Insert(key, records, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(60), CacheItemPriority.NotRemovable, null);
}
public static ScheduledTaskStatus Run(Stream CsvImport)
{
MemoryStream csvStream = new MemoryStream();
CsvImport.CopyTo(csvStream);
csvStream.Position = 0;
var task = new ImportParseTask();
JobDataMap taskData = new JobDataMap() { { "CsvImport", csvStream } };
return task.ScheduleTask(taskData);
}
}
}
@@ -0,0 +1,67 @@
using Disco.Data.Repository;
using Disco.Models.BI.Device;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Disco.BI.DeviceBI.Importing
{
public class ImportProcessTask : ScheduledTask
{
public override string TaskName { get { return "Import Devices - Processing Changes"; } }
public override bool SingleInstanceTask { get { return false; } }
public override bool CancelInitiallySupported { get { return false; } }
protected override void ExecuteTask()
{
string parseKey = (string)this.ExecutionContext.JobDetail.JobDataMap["ParseKey"];
if (string.IsNullOrWhiteSpace(parseKey))
throw new ArgumentNullException("ParseKey");
parseKey = string.Format(ImportParseTask.ImportParseCacheKey, parseKey);
List<ImportDevice> records = (List<ImportDevice>)HttpRuntime.Cache.Get(parseKey);
if (records == null)
throw new InvalidOperationException("The session timed out (60 minutes), try importing again");
this.Status.UpdateStatus(0, "Processing Device Import", "Importing Devices");
using (DiscoDataContext dbContext = new DiscoDataContext())
{
var populateReferences = Import.GetPopulateRecordReferences(dbContext);
DateTime lastUpdate = DateTime.Now;
foreach (var record in records)
{
record.ImportRecord(dbContext, populateReferences);
if (DateTime.Now.Subtract(lastUpdate).TotalSeconds > 1)
{
// Update every second
this.Status.UpdateStatus((int)Math.Floor((((double)(records.IndexOf(record) + 1) / records.Count) * 100)), string.Format("Importing: {0} ({1} of {2})", record.SerialNumber, records.IndexOf(record) + 1, records.Count));
lastUpdate = DateTime.Now;
}
}
}
}
public static ScheduledTaskStatus Run(string ParseTaskSessionKey)
{
if (string.IsNullOrWhiteSpace(ParseTaskSessionKey))
throw new ArgumentNullException("ParseTaskSessionKey");
var task = new ImportProcessTask();
JobDataMap taskData = new JobDataMap() { { "ParseKey", ParseTaskSessionKey } };
return task.ScheduleTask(taskData);
}
}
}
+6
View File
@@ -46,6 +46,9 @@
<Reference Include="itextsharp">
<HintPath>..\Resources\Libraries\iTextSharp\itextsharp.dll</HintPath>
</Reference>
<Reference Include="LumenWorks.Framework.IO">
<HintPath>..\..\..\Resources\Libraries\LumenWorks.Framework.IO\LumenWorks.Framework.IO.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.1.2\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
@@ -120,6 +123,9 @@
<Compile Include="BI\AttachmentBI\Utilities.cs" />
<Compile Include="BI\DeviceBI\BatchUtilities.cs" />
<Compile Include="BI\DeviceBI\DeviceModelBI.cs" />
<Compile Include="BI\DeviceBI\Importing\Import.cs" />
<Compile Include="BI\DeviceBI\Importing\ImportParseTask.cs" />
<Compile Include="BI\DeviceBI\Importing\ImportProcessTask.cs" />
<Compile Include="BI\DeviceBI\Searching.cs" />
<Compile Include="BI\DisposableImageCollection.cs" />
<Compile Include="BI\DocumentTemplateBI\DocumentTemplateQRCodeLocationCache.cs" />
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0722.1715")]
[assembly: AssemblyFileVersion("1.2.0722.1715")]
[assembly: AssemblyVersion("1.2.0722.2112")]
[assembly: AssemblyFileVersion("1.2.0722.2112")]
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0722.1715")]
[assembly: AssemblyFileVersion("1.2.0722.1715")]
[assembly: AssemblyVersion("1.2.0722.2115")]
[assembly: AssemblyFileVersion("1.2.0722.2115")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0722.1715")]
[assembly: AssemblyFileVersion("1.2.0722.1715")]
[assembly: AssemblyVersion("1.2.0722.2047")]
[assembly: AssemblyFileVersion("1.2.0722.2047")]
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0722.1715")]
[assembly: AssemblyFileVersion("1.2.0722.1715")]
[assembly: AssemblyVersion("1.2.0722.2112")]
[assembly: AssemblyFileVersion("1.2.0722.2112")]
+40
View File
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.BI.Device
{
public class ImportDevice
{
[Required, StringLength(60)]
public string SerialNumber { get; set; }
public int? DeviceModelId { get; set; }
[Range(1, int.MaxValue, ErrorMessage = "A valid Device Profile is Required")]
public int DeviceProfileId { get; set; }
public int? DeviceBatchId { get; set; }
[StringLength(50)]
public string AssignedUserId { get; set; }
[StringLength(250)]
public string Location { get; set; }
[StringLength(40)]
public string AssetNumber { get; set; }
public Repository.Device Device { get; set; }
public Repository.DeviceModel DeviceModel { get; set; }
public Repository.DeviceProfile DeviceProfile { get; set; }
public Repository.DeviceBatch DeviceBatch { get; set; }
public Repository.User AssignedUser { get; set; }
public Dictionary<string, string> Errors { get; set; }
}
}
+2
View File
@@ -46,6 +46,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="BI\Config\OrganisationAddress.cs" />
<Compile Include="BI\Device\ImportDevice.cs" />
<Compile Include="BI\DocumentTemplate\DocumentState.cs" />
<Compile Include="BI\Expressions\IImageExpressionResult.cs" />
<Compile Include="BI\Interop\Community\PluginLibraryCompatibilityItem.cs" />
@@ -123,6 +124,7 @@
<Compile Include="UI\Config\Logging\ConfigLoggingTaskStatusModel.cs" />
<Compile Include="UI\Config\Organisation\ConfigOrganisationIndexModel.cs" />
<Compile Include="UI\Device\DeviceAddOfflineModel.cs" />
<Compile Include="UI\Device\DeviceImportModel.cs" />
<Compile Include="UI\Device\DeviceIndexModel.cs" />
<Compile Include="UI\Device\DeviceShowModel.cs" />
<Compile Include="UI\Job\JobCreateModel.cs" />
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0722.1715")]
[assembly: AssemblyFileVersion("1.2.0722.1715")]
[assembly: AssemblyVersion("1.2.0722.2112")]
[assembly: AssemblyFileVersion("1.2.0722.2112")]
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Models.UI.Device
{
public interface DeviceImportModel : BaseUIModel
{
}
}
+1
View File
@@ -143,6 +143,7 @@ namespace Disco.Services.Plugins
"DotNet.Highcharts",
"EntityFramework",
"itextsharp",
"LumenWorks.Framework.IO",
"Microsoft.AspNet.SignalR.Core",
"Microsoft.AspNet.SignalR.Owin",
"Microsoft.AspNet.SignalR.SystemWeb",
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0722.1715")]
[assembly: AssemblyFileVersion("1.2.0722.1715")]
[assembly: AssemblyVersion("1.2.0722.2112")]
[assembly: AssemblyFileVersion("1.2.0722.2112")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0722.1715")]
[assembly: AssemblyFileVersion("1.2.0722.1715")]
[assembly: AssemblyVersion("1.2.0722.2112")]
[assembly: AssemblyFileVersion("1.2.0722.2112")]
@@ -464,5 +464,27 @@ namespace Disco.Web.Areas.API.Controllers
#endregion
public virtual ActionResult ImportParse(HttpPostedFileBase ImportFile)
{
if (ImportFile == null || ImportFile.ContentLength == 0)
throw new ArgumentNullException("ImportFile");
var status = Disco.BI.DeviceBI.Importing.ImportParseTask.Run(ImportFile.InputStream);
status.SetFinishedUrl(Url.Action(MVC.API.Device.ImportProcess(status.SessionId)));
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
}
public virtual ActionResult ImportProcess(string ParseTaskSessionKey)
{
if (string.IsNullOrWhiteSpace(ParseTaskSessionKey))
throw new ArgumentNullException("ParseTaskSessionKey");
var status = Disco.BI.DeviceBI.Importing.ImportProcessTask.Run(ParseTaskSessionKey);
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
}
}
}
+13
View File
@@ -76,6 +76,19 @@ namespace Disco.Web.Controllers
}
#endregion
#region Import
[HttpGet]
public virtual ActionResult Import()
{
Models.Device.ImportModel m = new Models.Device.ImportModel();
// UI Extensions
UIExtensions.ExecuteExtensions<DeviceImportModel>(this.ControllerContext, m);
return View();
}
#endregion
#region Show
public virtual ActionResult Show(string id)
{
+11 -1
View File
@@ -513,6 +513,7 @@
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Models\Device\AddOfflineModel.cs" />
<Compile Include="Models\Device\ImportModel.cs" />
<Compile Include="Models\Device\IndexModel.cs" />
<Compile Include="Models\Device\ShowModel.cs" />
<Compile Include="Models\InitialConfig\CompleteModel.cs" />
@@ -566,6 +567,11 @@
<DesignTime>True</DesignTime>
<DependentUpon>_Subject.cshtml</DependentUpon>
</Compile>
<Compile Include="Views\Device\Import.generated.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Import.cshtml</DependentUpon>
</Compile>
<Compile Include="Views\Device\Index.generated.cs">
<DependentUpon>Index.cshtml</DependentUpon>
<AutoGen>True</AutoGen>
@@ -1444,6 +1450,10 @@
<Generator>RazorGenerator</Generator>
<LastGenOutput>_Subject.generated.cs</LastGenOutput>
</None>
<None Include="Views\Device\Import.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>Import.generated.cs</LastGenOutput>
</None>
<None Include="Views\Device\Index.cshtml">
<Generator>RazorGenerator</Generator>
<LastGenOutput>Index.generated.cs</LastGenOutput>
@@ -1911,7 +1921,7 @@
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
<UserProperties BuildVersion_StartDate="2011/7/1" BuildVersion_BuildAction="Both" BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" BuildVersion_StartDate="2011/7/1" />
</VisualStudio>
</ProjectExtensions>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
+15
View File
@@ -0,0 +1,15 @@
using Disco.Models.UI.Device;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace Disco.Web.Models.Device
{
public class ImportModel : DeviceImportModel
{
[Required, Display(Name="Import File")]
public HttpPostedFileBase ImportFile { get; set; }
}
}
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.2.0722.1715")]
[assembly: AssemblyFileVersion("1.2.0722.1715")]
[assembly: AssemblyVersion("1.2.0722.2112")]
[assembly: AssemblyFileVersion("1.2.0722.2112")]
+65
View File
@@ -1107,6 +1107,7 @@ namespace Disco.Web.Controllers
{
public readonly string Index = "Index";
public readonly string AddOffline = "AddOffline";
public readonly string Import = "Import";
public readonly string Show = "Show";
}
@@ -1115,6 +1116,7 @@ namespace Disco.Web.Controllers
{
public const string Index = "Index";
public const string AddOffline = "AddOffline";
public const string Import = "Import";
public const string Show = "Show";
}
@@ -1148,12 +1150,14 @@ namespace Disco.Web.Controllers
public readonly string _DeviceTable = "_DeviceTable";
public readonly string _ViewStart = "_ViewStart";
public readonly string AddOffline = "AddOffline";
public readonly string Import = "Import";
public readonly string Index = "Index";
public readonly string Show = "Show";
}
public readonly string _DeviceTable = "~/Views/Device/_DeviceTable.cshtml";
public readonly string _ViewStart = "~/Views/Device/_ViewStart.cshtml";
public readonly string AddOffline = "~/Views/Device/AddOffline.cshtml";
public readonly string Import = "~/Views/Device/Import.cshtml";
public readonly string Index = "~/Views/Device/Index.cshtml";
public readonly string Show = "~/Views/Device/Show.cshtml";
static readonly _DevicePartsClass s_DeviceParts = new _DevicePartsClass();
@@ -1213,6 +1217,15 @@ namespace Disco.Web.Controllers
return callInfo;
}
partial void ImportOverride(T4MVC_System_Web_Mvc_ActionResult callInfo);
public override System.Web.Mvc.ActionResult Import()
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Import);
ImportOverride(callInfo);
return callInfo;
}
partial void ShowOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string id);
public override System.Web.Mvc.ActionResult Show(string id)
@@ -3268,6 +3281,18 @@ namespace Disco.Web.Areas.API.Controllers
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.AttachmentRemove);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult ImportParse()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.ImportParse);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult ImportProcess()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.ImportProcess);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public DeviceController Actions { get { return MVC.API.Device; } }
@@ -3302,6 +3327,8 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string Attachment = "Attachment";
public readonly string Attachments = "Attachments";
public readonly string AttachmentRemove = "AttachmentRemove";
public readonly string ImportParse = "ImportParse";
public readonly string ImportProcess = "ImportProcess";
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
@@ -3325,6 +3352,8 @@ namespace Disco.Web.Areas.API.Controllers
public const string Attachment = "Attachment";
public const string Attachments = "Attachments";
public const string AttachmentRemove = "AttachmentRemove";
public const string ImportParse = "ImportParse";
public const string ImportProcess = "ImportProcess";
}
@@ -3492,6 +3521,22 @@ namespace Disco.Web.Areas.API.Controllers
{
public readonly string id = "id";
}
static readonly ActionParamsClass_ImportParse s_params_ImportParse = new ActionParamsClass_ImportParse();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_ImportParse ImportParseParams { get { return s_params_ImportParse; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_ImportParse
{
public readonly string ImportFile = "ImportFile";
}
static readonly ActionParamsClass_ImportProcess s_params_ImportProcess = new ActionParamsClass_ImportProcess();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_ImportProcess ImportProcessParams { get { return s_params_ImportProcess; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_ImportProcess
{
public readonly string ParseTaskSessionKey = "ParseTaskSessionKey";
}
static readonly ViewsClass s_views = new ViewsClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewsClass Views { get { return s_views; } }
@@ -3711,6 +3756,26 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo;
}
partial void ImportParseOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, System.Web.HttpPostedFileBase ImportFile);
public override System.Web.Mvc.ActionResult ImportParse(System.Web.HttpPostedFileBase ImportFile)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.ImportParse);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "ImportFile", ImportFile);
ImportParseOverride(callInfo, ImportFile);
return callInfo;
}
partial void ImportProcessOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string ParseTaskSessionKey);
public override System.Web.Mvc.ActionResult ImportProcess(string ParseTaskSessionKey)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.ImportProcess);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "ParseTaskSessionKey", ParseTaskSessionKey);
ImportProcessOverride(callInfo, ParseTaskSessionKey);
return callInfo;
}
}
}
+23
View File
@@ -0,0 +1,23 @@
@model Disco.Web.Models.Device.ImportModel
@{
ViewBag.Title = Html.ToBreadcrumb("Devices", MVC.Device.Index(), "Import Devices");
}
@using (Html.BeginForm(MVC.API.Device.ImportParse(), FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.ValidationSummary()
<div id="importDialog" class="form" style="width: 450px">
<table>
<tr>
<th>
@Html.LabelFor(m => m.ImportFile)
</th>
<td>
<input id="ImportFile" name="ImportFile" type="file" data-val="true" data-val-required="An Import File is required." />
</td>
</tr>
</table>
<p class="actions">
<input type="submit" class="button" value="Import" />
</p>
</div>
}
+129
View File
@@ -0,0 +1,129 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18051
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Disco.Web.Views.Device
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Web.Security;
using System.Web.UI;
using System.Web.WebPages;
using Disco.BI.Extensions;
using Disco.Models.Repository;
using Disco.Web;
using Disco.Web.Extensions;
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")]
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/Device/Import.cshtml")]
public partial class Import : System.Web.Mvc.WebViewPage<Disco.Web.Models.Device.ImportModel>
{
public Import()
{
}
public override void Execute()
{
#line 2 "..\..\Views\Device\Import.cshtml"
ViewBag.Title = Html.ToBreadcrumb("Devices", MVC.Device.Index(), "Import Devices");
#line default
#line hidden
WriteLiteral("\r\n");
#line 5 "..\..\Views\Device\Import.cshtml"
using (Html.BeginForm(MVC.API.Device.ImportParse(), FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#line default
#line hidden
#line 7 "..\..\Views\Device\Import.cshtml"
Write(Html.ValidationSummary());
#line default
#line hidden
#line 7 "..\..\Views\Device\Import.cshtml"
#line default
#line hidden
WriteLiteral(" <div");
WriteLiteral(" id=\"importDialog\"");
WriteLiteral(" class=\"form\"");
WriteLiteral(" style=\"width: 450px\"");
WriteLiteral(">\r\n <table>\r\n <tr>\r\n <th>\r\n");
WriteLiteral(" ");
#line 12 "..\..\Views\Device\Import.cshtml"
Write(Html.LabelFor(m => m.ImportFile));
#line default
#line hidden
WriteLiteral("\r\n </th>\r\n <td>\r\n <input");
WriteLiteral(" id=\"ImportFile\"");
WriteLiteral(" name=\"ImportFile\"");
WriteLiteral(" type=\"file\"");
WriteLiteral(" data-val=\"true\"");
WriteLiteral(" data-val-required=\"An Import File is required.\"");
WriteLiteral(" />\r\n </td>\r\n </tr>\r\n </table>\r\n <p");
WriteLiteral(" class=\"actions\"");
WriteLiteral(">\r\n <input");
WriteLiteral(" type=\"submit\"");
WriteLiteral(" class=\"button\"");
WriteLiteral(" value=\"Import\"");
WriteLiteral(" />\r\n </p>\r\n </div>\r\n");
#line 23 "..\..\Views\Device\Import.cshtml"
}
#line default
#line hidden
}
}
}
#pragma warning restore 1591
+1
View File
@@ -5,5 +5,6 @@
Search for a Device</h3>
@Html.Partial(MVC.Shared.Views._SearchDialog, "devices")
<div class="actionBar">
@Html.ActionLinkButton("Import Devices", MVC.Device.Import())
@Html.ActionLinkButton("Add Offline Device", MVC.Device.AddOffline())
</div>
+12 -1
View File
@@ -2,7 +2,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18033
// Runtime Version:4.0.30319.18051
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -67,6 +67,17 @@ WriteLiteral(" ");
#line 8 "..\..\Views\Device\Index.cshtml"
Write(Html.ActionLinkButton("Import Devices", MVC.Device.Import()));
#line default
#line hidden
WriteLiteral("\r\n");
WriteLiteral(" ");
#line 9 "..\..\Views\Device\Index.cshtml"
Write(Html.ActionLinkButton("Add Offline Device", MVC.Device.AddOffline()));