diff --git a/Disco.BI/BI/Extensions/JobActionExtensions.cs b/Disco.BI/BI/Extensions/JobActionExtensions.cs index da500cf6..07410120 100644 --- a/Disco.BI/BI/Extensions/JobActionExtensions.cs +++ b/Disco.BI/BI/Extensions/JobActionExtensions.cs @@ -170,7 +170,7 @@ namespace Disco.BI.Extensions j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now; j.JobMetaWarranty.ExternalName = WarrantyProvider.WarrantyProviderId; - if (providerRef.Length > 100) + if (providerRef != null && providerRef.Length > 100) j.JobMetaWarranty.ExternalReference = providerRef.Substring(0, 100); else j.JobMetaWarranty.ExternalReference = providerRef; @@ -186,18 +186,18 @@ namespace Disco.BI.Extensions Database.JobLogs.Add(jobLog); } } - public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, string CustomProviderName, string CustomProviderReference, OrganisationAddress Address, User TechUser) + public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser) { if (!j.CanLogWarranty()) throw new InvalidOperationException("Log Warranty was Denied"); j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now; - j.JobMetaWarranty.ExternalName = CustomProviderName; + j.JobMetaWarranty.ExternalName = ManualProviderName; - if (CustomProviderReference != null && CustomProviderReference.Length > 100) - j.JobMetaWarranty.ExternalReference = CustomProviderReference.Substring(0, 100); + if (ManualProviderReference != null && ManualProviderReference.Length > 100) + j.JobMetaWarranty.ExternalReference = ManualProviderReference.Substring(0, 100); else - j.JobMetaWarranty.ExternalReference = CustomProviderReference; + j.JobMetaWarranty.ExternalReference = ManualProviderReference; // Write Log JobLog jobLog = new JobLog() @@ -205,7 +205,7 @@ namespace Disco.BI.Extensions JobId = j.Id, TechUserId = TechUser.UserId, Timestamp = DateTime.Now, - Comments = string.Format("####Custom Warranty Claim Submitted\r\nCustom Provider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n{3}", CustomProviderName, Address.Name, CustomProviderReference ?? "", FaultDescription) + Comments = string.Format("####Manual Warranty Claim Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n{3}", ManualProviderName, Address.Name, ManualProviderReference ?? "", FaultDescription) }; Database.JobLogs.Add(jobLog); } @@ -341,7 +341,7 @@ namespace Disco.BI.Extensions !j.JobMetaNonWarranty.RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty.RepairerCompletedDate.HasValue; } - public static void OnLogRepair(this Job j, DiscoDataContext Database, string RepairDescription, PluginFeatureManifest RepairProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary ProviderProperties) + public static void OnLogRepair(this Job j, DiscoDataContext Database, string RepairDescription, PluginFeatureManifest RepairProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary RepairProviderProperties) { if (!j.CanLogRepair()) throw new InvalidOperationException("Log Repair was Denied"); @@ -353,12 +353,12 @@ namespace Disco.BI.Extensions using (RepairProviderFeature RepairProvider = RepairProviderDefinition.CreateInstance()) { - string providerRef = RepairProvider.SubmitJob(Database, j, Address, TechUser, RepairDescription, ProviderProperties); + string providerRef = RepairProvider.SubmitJob(Database, j, Address, TechUser, RepairDescription, RepairProviderProperties); j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now; j.JobMetaNonWarranty.RepairerName = RepairProvider.ProviderId; - if (providerRef.Length > 100) + if (providerRef != null && providerRef.Length > 100) j.JobMetaNonWarranty.RepairerReference = providerRef.Substring(0, 100); else j.JobMetaNonWarranty.RepairerReference = providerRef; @@ -374,6 +374,29 @@ namespace Disco.BI.Extensions Database.JobLogs.Add(jobLog); } } + public static void OnLogRepair(this Job j, DiscoDataContext Database, string FaultDescription, string ManualProviderName, string ManualProviderReference, OrganisationAddress Address, User TechUser) + { + if (!j.CanLogRepair()) + throw new InvalidOperationException("Log Repair was Denied"); + + j.JobMetaNonWarranty.RepairerLoggedDate = DateTime.Now; + j.JobMetaNonWarranty.RepairerName = ManualProviderName; + + if (ManualProviderReference != null && ManualProviderReference.Length > 100) + j.JobMetaNonWarranty.RepairerReference = ManualProviderReference.Substring(0, 100); + else + j.JobMetaNonWarranty.RepairerReference = ManualProviderReference; + + // Write Log + JobLog jobLog = new JobLog() + { + JobId = j.Id, + TechUserId = TechUser.UserId, + Timestamp = DateTime.Now, + Comments = string.Format("####Manual Repair Request Submitted\r\nProvider: **{0}**\r\nAddress: **{1}**\r\nReference: **{2}**\r\n___\r\n{3}", ManualProviderName, Address.Name, ManualProviderReference ?? "", FaultDescription) + }; + Database.JobLogs.Add(jobLog); + } #endregion #region Repair Complete diff --git a/Disco.Data/Disco.Data.csproj b/Disco.Data/Disco.Data.csproj index 6244f765..4eee00c7 100644 --- a/Disco.Data/Disco.Data.csproj +++ b/Disco.Data/Disco.Data.csproj @@ -143,6 +143,10 @@ 201406160912525_DBv14.cs + + + 201407100413342_DBv15.cs + @@ -200,6 +204,9 @@ 201406160912525_DBv14.cs + + 201407100413342_DBv15.cs + ResXFileCodeGenerator Resources.Designer.cs @@ -213,7 +220,7 @@ - + diff --git a/Disco.Data/Migrations/201407100413342_DBv15.Designer.cs b/Disco.Data/Migrations/201407100413342_DBv15.Designer.cs new file mode 100644 index 00000000..7553703c --- /dev/null +++ b/Disco.Data/Migrations/201407100413342_DBv15.Designer.cs @@ -0,0 +1,27 @@ +// +namespace Disco.Data.Migrations +{ + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + public sealed partial class DBv15 : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(DBv15)); + + string IMigrationMetadata.Id + { + get { return "201407100413342_DBv15"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/Disco.Data/Migrations/201407100413342_DBv15.cs b/Disco.Data/Migrations/201407100413342_DBv15.cs new file mode 100644 index 00000000..6474c94d --- /dev/null +++ b/Disco.Data/Migrations/201407100413342_DBv15.cs @@ -0,0 +1,18 @@ +namespace Disco.Data.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class DBv15 : DbMigration + { + public override void Up() + { + AddColumn("dbo.DeviceModels", "DefaultRepairProvider", c => c.String(maxLength: 40)); + } + + public override void Down() + { + DropColumn("dbo.DeviceModels", "DefaultRepairProvider"); + } + } +} diff --git a/Disco.Data/Migrations/201407100413342_DBv15.resx b/Disco.Data/Migrations/201407100413342_DBv15.resx new file mode 100644 index 00000000..9dd1a90b --- /dev/null +++ b/Disco.Data/Migrations/201407100413342_DBv15.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + \ No newline at end of file diff --git a/Disco.Models/Repository/Device/DeviceModel.cs b/Disco.Models/Repository/Device/DeviceModel.cs index 46cf2511..cc99b734 100644 --- a/Disco.Models/Repository/Device/DeviceModel.cs +++ b/Disco.Models/Repository/Device/DeviceModel.cs @@ -33,6 +33,9 @@ namespace Disco.Models.Repository [StringLength(40)] public string DefaultWarrantyProvider { get; set; } + [StringLength(40)] + public string DefaultRepairProvider { get; set; } + public virtual IList DeviceComponents { get; set; } public virtual IList Devices { get; set; } diff --git a/Disco.Services/Authorization/Claims.cs b/Disco.Services/Authorization/Claims.cs index af35dcc8..bd6cb98c 100644 --- a/Disco.Services/Authorization/Claims.cs +++ b/Disco.Services/Authorization/Claims.cs @@ -133,6 +133,7 @@ namespace Disco.Services.Authorization { "Job.Properties.NonWarrantyProperties.PurchaseOrderRaised", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.PurchaseOrderRaised, (c, v) => c.Job.Properties.NonWarrantyProperties.PurchaseOrderRaised = v, "Purchase Order Raised Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.PurchaseOrderReference", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.PurchaseOrderReference, (c, v) => c.Job.Properties.NonWarrantyProperties.PurchaseOrderReference = v, "Purchase Order Reference Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.PurchaseOrderSent", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.PurchaseOrderSent, (c, v) => c.Job.Properties.NonWarrantyProperties.PurchaseOrderSent = v, "Purchase Order Sent Property", "Can update property", false) }, + { "Job.Properties.NonWarrantyProperties.RepairProviderDetails", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairProviderDetails, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairProviderDetails = v, "Repair Provider Details", "Can access repair provider details", false) }, { "Job.Properties.NonWarrantyProperties.RepairerCompletedDate", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerCompletedDate, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerCompletedDate = v, "Repairer Completed Date Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.RepairerLoggedDate", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate = v, "Repairer Logged Date Property", "Can update property", false) }, { "Job.Properties.NonWarrantyProperties.RepairerName", new Tuple, Action, string, string, bool>(c => c.Job.Properties.NonWarrantyProperties.RepairerName, (c, v) => c.Job.Properties.NonWarrantyProperties.RepairerName = v, "Repairer Name Property", "Can update property", false) }, @@ -352,6 +353,7 @@ namespace Disco.Services.Authorization new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.PurchaseOrderRaised", false), new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.PurchaseOrderReference", false), new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.PurchaseOrderSent", false), + new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairProviderDetails", false), new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairerCompletedDate", false), new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairerLoggedDate", false), new ClaimNavigatorItem("Job.Properties.NonWarrantyProperties.RepairerName", false), @@ -645,6 +647,7 @@ namespace Disco.Services.Authorization c.Job.Properties.NonWarrantyProperties.PurchaseOrderRaised = true; c.Job.Properties.NonWarrantyProperties.PurchaseOrderReference = true; c.Job.Properties.NonWarrantyProperties.PurchaseOrderSent = true; + c.Job.Properties.NonWarrantyProperties.RepairProviderDetails = true; c.Job.Properties.NonWarrantyProperties.RepairerCompletedDate = true; c.Job.Properties.NonWarrantyProperties.RepairerLoggedDate = true; c.Job.Properties.NonWarrantyProperties.RepairerName = true; @@ -1424,6 +1427,11 @@ namespace Disco.Services.Authorization /// public const string PurchaseOrderSent = "Job.Properties.NonWarrantyProperties.PurchaseOrderSent"; + /// Repair Provider Details + /// Can access repair provider details + /// + public const string RepairProviderDetails = "Job.Properties.NonWarrantyProperties.RepairProviderDetails"; + /// Repairer Completed Date Property /// Can update property /// diff --git a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobNonWarrantyPropertiesClaims.cs b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobNonWarrantyPropertiesClaims.cs index 80026bc8..e8ebc189 100644 --- a/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobNonWarrantyPropertiesClaims.cs +++ b/Disco.Services/Authorization/Roles/ClaimGroups/Job/JobNonWarrantyPropertiesClaims.cs @@ -44,6 +44,9 @@ namespace Disco.Services.Authorization.Roles.ClaimGroups.Job [ClaimDetails("Repairer Reference Property", "Can update property")] public bool RepairerReference { get; set; } + [ClaimDetails("Repair Provider Details", "Can access repair provider details")] + public bool RepairProviderDetails { get; set; } + [ClaimDetails("Insurance Detail Properties", "Can update insurance detail properties")] public bool InsuranceDetails { get; set; } } diff --git a/Disco.Services/Authorization/Roles/RoleCache.cs b/Disco.Services/Authorization/Roles/RoleCache.cs index 87453290..7378bdcc 100644 --- a/Disco.Services/Authorization/Roles/RoleCache.cs +++ b/Disco.Services/Authorization/Roles/RoleCache.cs @@ -157,12 +157,15 @@ namespace Disco.Services.Authorization.Roles /// private static void MigrateAuthorizationRoles(DiscoDataContext Database) { - // Use 'MyJobs' (A new claim) to detect if the Role hasn't been migrated yet - var affectedRoles = Database.AuthorizationRoles.Where(r => !r.ClaimsJson.Contains("MyJobs")).ToList(); + // Determine roles which need migration from DBv11 -> DBv14 + var affectedRoles_DBv14 = Database.AuthorizationRoles.Where(r => !r.ClaimsJson.Contains("MyJobs")).ToList(); + + // Determine roles which need migration from DBv14 -> DBv15 + var affectedRoles_DBv15 = Database.AuthorizationRoles.Where(r => !r.ClaimsJson.Contains("RepairProviderDetails")).ToList(); - if (affectedRoles.Count > 0) + if (affectedRoles_DBv14.Count > 0) { - foreach (var role in affectedRoles) + foreach (var role in affectedRoles_DBv14) { var claims = JsonConvert.DeserializeObject(role.ClaimsJson); @@ -204,6 +207,24 @@ namespace Disco.Services.Authorization.Roles Database.SaveChanges(); } + + if (affectedRoles_DBv15.Count > 0) + { + foreach (var role in affectedRoles_DBv15) + { + var claims = JsonConvert.DeserializeObject(role.ClaimsJson); + + // If the user previously had the ability to view warranty provider details, they probably should be able to view repair provider details (new feature). + if (claims.Job.Properties.WarrantyProperties.ProviderDetails) + { + claims.Job.Properties.NonWarrantyProperties.RepairProviderDetails = true; + } + + role.ClaimsJson = Newtonsoft.Json.JsonConvert.SerializeObject(claims); + } + + Database.SaveChanges(); + } } } } diff --git a/Disco.Services/Disco.Services.csproj b/Disco.Services/Disco.Services.csproj index ed7546a2..1fec0c35 100644 --- a/Disco.Services/Disco.Services.csproj +++ b/Disco.Services/Disco.Services.csproj @@ -261,6 +261,8 @@ + + diff --git a/Disco.Services/Plugins/Features/RepairProvider/RepairProviderFeature.cs b/Disco.Services/Plugins/Features/RepairProvider/RepairProviderFeature.cs new file mode 100644 index 00000000..cb802d16 --- /dev/null +++ b/Disco.Services/Plugins/Features/RepairProvider/RepairProviderFeature.cs @@ -0,0 +1,94 @@ +using Disco.Data.Repository; +using Disco.Models.BI.Config; +using Disco.Models.Repository; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web.Mvc; + +namespace Disco.Services.Plugins.Features.RepairProvider +{ + [PluginFeatureCategory(DisplayName = "Repair Providers")] + public abstract class RepairProviderFeature : PluginFeature + { + /// + /// The repairer identifier. Used to link this provider to any . This identifier is used to automatically set the RepairerName when a job is submitted using this plugin. + /// + public abstract string ProviderId { get; } + + #region Job Submission + + /// + /// Called when a user selects this plugin to repair and allows a plugin to inject a View to collect additional information. + /// + /// A Tuple consisting of the Razor View type and a View Model + public virtual Tuple SubmitJobBegin(DiscoDataContext Database, Controller controller, Job Job, OrganisationAddress Address, User TechUser) + { + return null; + } + + /// + /// Called after the RepairDescription is completed and allows the plugin to parse any data collected from SubmitJobBegin. + /// + /// A Dictionary of key/value items which are persisted throughout the submission and passed into the final SubmitJob method. + public virtual Dictionary SubmitJobParseProperties(DiscoDataContext Database, FormCollection form, Controller controller, Job Job, OrganisationAddress Address, User TechUser, string RepairDescription) + { + return null; + } + + /// + /// Plugins are required to disclose any information that will be transmitted to any external party. This method is expected to return a clear list all data which will be transmitted. + /// + /// A Dictionary of key/value items which contain all information which will be disclosed to the plugin provider. + public abstract Dictionary SubmitJobDiscloseInfo(DiscoDataContext Database, Job Job, OrganisationAddress Address, User TechUser, string RepairDescription, Dictionary ProviderProperties); + + /// + /// Called when the plugin should submit the job to the external party. + /// + /// A reference number/identifier from the external party which is stored in + public abstract string SubmitJob(DiscoDataContext Database, Job Job, OrganisationAddress Address, User TechUser, string RepairDescription, Dictionary ProviderProperties); + + #endregion + + #region Job Details + + /// + /// when additional Job Details are supported by the external party. When , JobDetailsViewModel must be implemented. + /// + public abstract bool JobDetailsSupported { get; } + + /// + /// Called when a job repair information is shown. Allows a plugin to inject a View to display additional information. + /// + /// A Tuple consisting of the Razor View type and a View Model + public virtual Tuple JobDetails(DiscoDataContext Database, Controller controller, Job Job) + { + return null; + } + + #endregion + + public static PluginFeatureManifest FindPluginFeature(string PluginIdOrRepairProviderId) + { + var defs = Plugins.GetPluginFeatures(typeof(RepairProviderFeature)); + var def = defs.FirstOrDefault(d => d.PluginManifest.Id.Equals(PluginIdOrRepairProviderId, StringComparison.OrdinalIgnoreCase)); + if (def != null) + return def; + else + foreach (var d in defs) + { + using (var providerInstance = d.CreateInstance()) + { + if (providerInstance.ProviderId != null && providerInstance.ProviderId.Equals(PluginIdOrRepairProviderId, StringComparison.OrdinalIgnoreCase)) + { + return d; + } + } + } + + return null; + } + } +} diff --git a/Disco.Services/Plugins/Features/RepairProvider/RepairProviderSubmitJobException.cs b/Disco.Services/Plugins/Features/RepairProvider/RepairProviderSubmitJobException.cs new file mode 100644 index 00000000..b0cddc1f --- /dev/null +++ b/Disco.Services/Plugins/Features/RepairProvider/RepairProviderSubmitJobException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Disco.Services.Plugins.Features.RepairProvider +{ + public class RepairProviderSubmitJobException : Exception + { + public RepairProviderSubmitJobException(string Message) + : base(Message) + { + } + } +} \ No newline at end of file diff --git a/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs b/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs index 90a7d223..675f50eb 100644 --- a/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs +++ b/Disco.Web.Extensions/BIModelExtensions/PluginExtensions.cs @@ -26,12 +26,13 @@ namespace Disco.Web.Extensions public static List ToSelectListItems(this IEnumerable PluginDefinitions, string SelectedId = null, bool IncludeInstructionFirst = false, string InstructionMessage = "Select a Plugin", Dictionary AdditionalItems = null) { - List selectItems; + var items = PluginDefinitions + .Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name, Selected = (SelectedId != null && SelectedId.Equals(wpd.Id)) }); - selectItems = PluginDefinitions - .Select(wpd => new SelectListItem { Value = wpd.Id, Text = wpd.Name, Selected = (SelectedId != null && SelectedId.Equals(wpd.Id)) }) - .Concat(AdditionalItems.Select(i => new SelectListItem { Value = i.Key, Text = i.Value, Selected = (SelectedId != null && SelectedId.Equals(i.Key)) })) - .OrderBy(i => i.Text).ToList(); + if (AdditionalItems != null) + items = items.Concat(AdditionalItems.Select(i => new SelectListItem { Value = i.Key, Text = i.Value, Selected = (SelectedId != null && SelectedId.Equals(i.Key)) })); + + var selectItems = items.OrderBy(i => i.Text).ToList(); if (IncludeInstructionFirst) selectItems.Insert(0, new SelectListItem() { Value = String.Empty, Text = String.Format("<{0}>", InstructionMessage), Selected = String.IsNullOrEmpty(SelectedId) }); diff --git a/Disco.Web/Areas/API/Controllers/DeviceModelController.cs b/Disco.Web/Areas/API/Controllers/DeviceModelController.cs index e04f3edb..87b67da3 100644 --- a/Disco.Web/Areas/API/Controllers/DeviceModelController.cs +++ b/Disco.Web/Areas/API/Controllers/DeviceModelController.cs @@ -2,6 +2,7 @@ using Disco.Models.Repository; using Disco.Services.Authorization; using Disco.Services.Plugins; +using Disco.Services.Plugins.Features.RepairProvider; using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Web; using System; @@ -18,6 +19,7 @@ namespace Disco.Web.Areas.API.Controllers const string pDescription = "description"; const string pDefaultPurchaseDate = "defaultpurchasedate"; const string pDefaultWarrantyProvider = "defaultwarrantyprovider"; + const string pDefaultRepairProvider = "defaultrepairprovider"; [DiscoAuthorize(Claims.Config.DeviceModel.Configure)] public virtual ActionResult Update(int id, string key, string value = null, bool redirect = false) @@ -44,6 +46,9 @@ namespace Disco.Web.Areas.API.Controllers case pDefaultWarrantyProvider: UpdateDefaultWarrantyProvider(deviceModel, value); break; + case pDefaultRepairProvider: + UpdateDefaultRepairProvider(deviceModel, value); + break; default: throw new Exception("Invalid Update Key"); } @@ -86,6 +91,12 @@ namespace Disco.Web.Areas.API.Controllers return Update(id, pDefaultWarrantyProvider, DefaultWarrantyProvider, redirect); } + [DiscoAuthorize(Claims.Config.DeviceModel.Configure)] + public virtual ActionResult UpdateDefaultRepairProvider(int id, string DefaultRepairProvider = null, bool redirect = false) + { + return Update(id, pDefaultRepairProvider, DefaultRepairProvider, redirect); + } + #endregion #region Update Properties @@ -131,6 +142,20 @@ namespace Disco.Web.Areas.API.Controllers } Database.SaveChanges(); } + private void UpdateDefaultRepairProvider(Disco.Models.Repository.DeviceModel deviceModel, string DefaultRepairProvider) + { + if (string.IsNullOrEmpty(DefaultRepairProvider)) + { + deviceModel.DefaultRepairProvider = null; + } + else + { + // Validate + var RepairProvider = Plugins.GetPluginFeature(DefaultRepairProvider, typeof(RepairProviderFeature)); + deviceModel.DefaultRepairProvider = RepairProvider.Id; + } + Database.SaveChanges(); + } #endregion #region ModelImage diff --git a/Disco.Web/Areas/API/Controllers/JobController.cs b/Disco.Web/Areas/API/Controllers/JobController.cs index d6f47bde..bb96abb1 100644 --- a/Disco.Web/Areas/API/Controllers/JobController.cs +++ b/Disco.Web/Areas/API/Controllers/JobController.cs @@ -1599,31 +1599,6 @@ namespace Disco.Web.Areas.API.Controllers } } - [DiscoAuthorize(Claims.Job.Actions.LogRepair)] - public virtual ActionResult LogRepair(int id, string RepairerName, string RepairerReference, bool? redirect = null) - { - var j = Database.Jobs.Include("JobMetaNonWarranty").Where(job => job.Id == id).FirstOrDefault(); - if (j != null) - { - if (j.CanLogRepair()) - { - j.OnLogRepair(RepairerName, RepairerReference); - - Database.SaveChanges(); - - if (redirect.HasValue && redirect.Value) - return RedirectToAction(MVC.Job.Show(id)); - else - return Json("OK", JsonRequestBehavior.AllowGet); - } - else - { - return Json("Job's state doesn't allow this action", JsonRequestBehavior.AllowGet); - } - } - return Json("Invalid Job Number", JsonRequestBehavior.AllowGet); - } - [DiscoAuthorize(Claims.Job.Properties.DeviceReadyForReturn)] public virtual ActionResult DeviceReadyForReturn(int id, bool redirect) { diff --git a/Disco.Web/Areas/Config/Controllers/DeviceModelController.cs b/Disco.Web/Areas/Config/Controllers/DeviceModelController.cs index c113d315..10f40a22 100644 --- a/Disco.Web/Areas/Config/Controllers/DeviceModelController.cs +++ b/Disco.Web/Areas/Config/Controllers/DeviceModelController.cs @@ -2,6 +2,7 @@ using Disco.Models.UI.Config.DeviceModel; using Disco.Services.Authorization; using Disco.Services.Plugins; +using Disco.Services.Plugins.Features.RepairProvider; using Disco.Services.Plugins.Features.UIExtension; using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Web; @@ -29,6 +30,7 @@ namespace Disco.Web.Areas.Config.Controllers throw new ArgumentException("Invalid Device Model Id", "id"); m.WarrantyProviders = Plugins.GetPluginFeatures(typeof(WarrantyProviderFeature)); + m.RepairProviders = Plugins.GetPluginFeatures(typeof(RepairProviderFeature)); m.DeviceComponentsModel = new Models.DeviceModel.ComponentsModel() { diff --git a/Disco.Web/Areas/Config/Models/DeviceModel/ShowModel.cs b/Disco.Web/Areas/Config/Models/DeviceModel/ShowModel.cs index 79ab0044..e975b35f 100644 --- a/Disco.Web/Areas/Config/Models/DeviceModel/ShowModel.cs +++ b/Disco.Web/Areas/Config/Models/DeviceModel/ShowModel.cs @@ -14,6 +14,7 @@ namespace Disco.Web.Areas.Config.Models.DeviceModel public ConfigDeviceModelComponentsModel DeviceComponentsModel { get; set; } public List WarrantyProviders { get; set; } + public List RepairProviders { get; set; } public int DeviceCount { get; set; } public int DeviceDecommissionedCount { get; set; } diff --git a/Disco.Web/Areas/Config/Views/DeviceModel/Show.cshtml b/Disco.Web/Areas/Config/Views/DeviceModel/Show.cshtml index 66e33d5c..2962b799 100644 --- a/Disco.Web/Areas/Config/Views/DeviceModel/Show.cshtml +++ b/Disco.Web/Areas/Config/Views/DeviceModel/Show.cshtml @@ -3,6 +3,12 @@ Authorization.Require(Claims.Config.DeviceModel.Show); var canConfig = Authorization.Has(Claims.Config.DeviceModel.Configure); + var canViewPlugins = Authorization.Has(Claims.Config.Plugin.Install); + + if (canConfig) + { + Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers"); + } ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Device Models", MVC.Config.DeviceModel.Index(null), Model.DeviceModel.ToString()); } @@ -23,6 +29,16 @@ @Html.EditorFor(model => model.DeviceModel.Description) @AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxLoader() + } else { @@ -61,6 +77,19 @@ { @Html.EditorFor(model => model.DeviceModel.DefaultPurchaseDate) @AjaxHelpers.AjaxLoader() + } else { @@ -73,8 +102,33 @@ @if (canConfig) { + if (Model.WarrantyProviders.Count > 0) + { @Html.DropDownListFor(model => model.DeviceModel.DefaultWarrantyProvider, Model.WarrantyProviders.ToSelectListItems(Model.DeviceModel.DefaultWarrantyProvider, true, "None")) @AjaxHelpers.AjaxLoader() + + } + else + { + No warranty provider plugins installed + } + if (canViewPlugins) + { +
+

+ View the Plugin Catalogue to discover and install warranty provider plugins. +

+
+ } } else { @@ -97,6 +151,60 @@ } + + Default Repair Provider: + + @if (canConfig) + { + if (Model.RepairProviders.Count > 0) + { + @Html.DropDownListFor(model => model.DeviceModel.DefaultRepairProvider, Model.RepairProviders.ToSelectListItems(Model.DeviceModel.DefaultRepairProvider, true, "None")) + @AjaxHelpers.AjaxLoader() + + } + else + { +
No repair provider plugins installed
+ } + if (canViewPlugins) + { +
+

+ View the Plugin Catalogue to discover and install repair provider plugins. +

+
+ } + } + else + { + if (Model.DeviceModel.DefaultRepairProvider == null) + { + <None Specified> + } + else + { + var provider = Model.RepairProviders.FirstOrDefault(wp => wp.Id == Model.DeviceModel.DefaultRepairProvider); + if (provider == null) + { + <None Specified> + } + else + { + @provider.Name + } + } + } + + Type: @@ -109,135 +217,18 @@ Model Image + @if (canConfig) + { +
+ using (Html.BeginForm(MVC.API.DeviceModel.Image(Model.DeviceModel.Id, true, null), FormMethod.Post, new { enctype = "multipart/form-data" })) + { + + + } + } - @if (canConfig) - { - - - - - - @using (Html.BeginForm(MVC.API.DeviceModel.Image(Model.DeviceModel.Id, true, null), FormMethod.Post, new { enctype = "multipart/form-data" })) - { - - - } - - - } - @if (canConfig) - { - - - - }

Components

@Html.Partial(MVC.Config.DeviceModel.Views._DeviceComponentsTable, Model.DeviceComponentsModel) diff --git a/Disco.Web/Areas/Config/Views/DeviceModel/Show.generated.cs b/Disco.Web/Areas/Config/Views/DeviceModel/Show.generated.cs index 0d6aad20..f66158ad 100644 --- a/Disco.Web/Areas/Config/Views/DeviceModel/Show.generated.cs +++ b/Disco.Web/Areas/Config/Views/DeviceModel/Show.generated.cs @@ -50,6 +50,12 @@ namespace Disco.Web.Areas.Config.Views.DeviceModel Authorization.Require(Claims.Config.DeviceModel.Show); var canConfig = Authorization.Has(Claims.Config.DeviceModel.Configure); + var canViewPlugins = Authorization.Has(Claims.Config.Plugin.Install); + + if (canConfig) + { + Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers"); + } ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Device Models", MVC.Config.DeviceModel.Index(null), Model.DeviceModel.ToString()); @@ -71,7 +77,7 @@ WriteLiteral(">Id:\r\n \r\n \r\n"); WriteLiteral(" "); - #line 15 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 21 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.DisplayFor(model => model.DeviceModel.Id)); @@ -81,7 +87,7 @@ WriteLiteral("\r\n \r\n \r\n \r\n " \r\n "); - #line 21 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 27 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" if (canConfig) { @@ -89,43 +95,66 @@ WriteLiteral("\r\n \r\n \r\n \r\n #line default #line hidden - #line 23 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 29 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.EditorFor(model => model.DeviceModel.Description)); #line default #line hidden - #line 23 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 29 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" #line default #line hidden - #line 24 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 30 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(AjaxHelpers.AjaxSave()); #line default #line hidden - #line 24 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 30 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" #line default #line hidden - #line 25 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 31 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 25 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 31 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + + + #line default + #line hidden +WriteLiteral(@" \r\n"); + + + #line 42 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } else { @@ -134,14 +163,14 @@ WriteLiteral("\r\n \r\n \r\n \r\n #line default #line hidden - #line 29 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 45 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.DisplayFor(model => model.DeviceModel.Description)); #line default #line hidden - #line 29 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 45 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } @@ -154,7 +183,7 @@ WriteLiteral(" \r\n \r\n \r\n WriteLiteral(" "); - #line 37 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 53 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.DisplayFor(model => model.DeviceModel.Manufacturer)); @@ -166,7 +195,7 @@ WriteLiteral("\r\n \r\n \r\n \r\n WriteLiteral(" "); - #line 44 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 60 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.DisplayFor(model => model.DeviceModel.Model)); @@ -176,7 +205,7 @@ WriteLiteral("\r\n \r\n \r\n \r\n "\r\n \r\n
"); - #line 50 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 66 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Model.DeviceCount.ToString("n0")); @@ -185,7 +214,7 @@ WriteLiteral("\r\n \r\n \r\n \r\n WriteLiteral(" "); - #line 50 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 66 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Model.DeviceCount == 1 ? "devices is" : "devices are"); @@ -194,13 +223,13 @@ WriteLiteral(" "); WriteLiteral(" of this model type.
\r\n"); - #line 51 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 67 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" #line default #line hidden - #line 51 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 67 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" if (Model.DeviceDecommissionedCount > 0) { @@ -214,7 +243,7 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral(">"); - #line 53 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 69 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Model.DeviceDecommissionedCount.ToString("n0")); @@ -223,7 +252,7 @@ WriteLiteral(">"); WriteLiteral(" "); - #line 53 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 69 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Model.DeviceDecommissionedCount == 1 ? "device is" : "devices are"); @@ -232,7 +261,7 @@ WriteLiteral(" "); WriteLiteral(" decommissioned.\r\n"); - #line 54 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 70 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } @@ -242,7 +271,7 @@ WriteLiteral(" \r\n \r\n \r\n "Date:\r\n \r\n "); - #line 60 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 76 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" if (canConfig) { @@ -250,29 +279,54 @@ WriteLiteral(" \r\n \r\n \r\n #line default #line hidden - #line 62 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 78 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.EditorFor(model => model.DeviceModel.DefaultPurchaseDate)); #line default #line hidden - #line 62 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 78 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" #line default #line hidden - #line 63 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 79 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 63 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 79 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + + + #line default + #line hidden +WriteLiteral(@" \r\n"); + + + #line 93 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } else { @@ -281,14 +335,14 @@ WriteLiteral(" \r\n \r\n \r\n #line default #line hidden - #line 67 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 96 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(CommonHelpers.FriendlyDate(Model.DeviceModel.DefaultPurchaseDate, "Unknown")); #line default #line hidden - #line 67 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 96 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } @@ -299,37 +353,114 @@ WriteLiteral(" \r\n \r\n \r\n "Provider:\r\n \r\n "); - #line 74 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 103 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" if (canConfig) { + if (Model.WarrantyProviders.Count > 0) + { #line default #line hidden - #line 76 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 107 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.DropDownListFor(model => model.DeviceModel.DefaultWarrantyProvider, Model.WarrantyProviders.ToSelectListItems(Model.DeviceModel.DefaultWarrantyProvider, true, "None"))); #line default #line hidden - #line 76 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 107 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" #line default #line hidden - #line 77 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 108 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(AjaxHelpers.AjaxLoader()); #line default #line hidden - #line 77 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 108 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + + + #line default + #line hidden +WriteLiteral(@" \r\n"); + + + #line 119 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral(" No warranty provider plugins installed\r\n"); + + + #line 123 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + } + if (canViewPlugins) + { + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n View the (Url.Action(MVC.Config.Plugins.Install()) + + #line default + #line hidden +, 5032), false) +); + +WriteLiteral(">Plugin Catalogue to discover and install warranty provider plugins.\r\n " + +"

\r\n \r\n"); + + + #line 131 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + } } else { @@ -346,7 +477,7 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral("><None Specified>\r\n"); - #line 84 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 138 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } else { @@ -364,7 +495,7 @@ WriteLiteral(" class=\"smallMessage\""); WriteLiteral("><None Specified>\r\n"); - #line 91 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 145 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } else { @@ -373,14 +504,181 @@ WriteLiteral("><None Specified>\r\n"); #line default #line hidden - #line 94 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 148 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(provider.Name); #line default #line hidden - #line 94 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 148 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + + } + } + } + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n \r\n Default Repair Pr" + +"ovider:\r\n \r\n "); + + + #line 157 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + if (canConfig) + { + if (Model.RepairProviders.Count > 0) + { + + + #line default + #line hidden + + #line 161 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + Write(Html.DropDownListFor(model => model.DeviceModel.DefaultRepairProvider, Model.RepairProviders.ToSelectListItems(Model.DeviceModel.DefaultRepairProvider, true, "None"))); + + + #line default + #line hidden + + #line 161 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + + + + #line default + #line hidden + + #line 162 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + Write(AjaxHelpers.AjaxLoader()); + + + #line default + #line hidden + + #line 162 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + + + + #line default + #line hidden +WriteLiteral(@" \r\n"); + + + #line 173 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + } + else + { + + + #line default + #line hidden +WriteLiteral("
No repair provider plugins installed
\r\n"); + + + #line 177 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + } + if (canViewPlugins) + { + + + #line default + #line hidden +WriteLiteral(" \r\n \r\n View the (Url.Action(MVC.Config.Plugins.Install()) + + #line default + #line hidden +, 7333), false) +); + +WriteLiteral(">Plugin Catalogue to discover and install repair provider plugins.\r\n " + +"

\r\n \r\n"); + + + #line 185 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + } + } + else + { + if (Model.DeviceModel.DefaultRepairProvider == null) + { + + + #line default + #line hidden +WriteLiteral(" <None Specified>\r\n"); + + + #line 192 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + } + else + { + var provider = Model.RepairProviders.FirstOrDefault(wp => wp.Id == Model.DeviceModel.DefaultRepairProvider); + if (provider == null) + { + + + #line default + #line hidden +WriteLiteral(" <None Specified>\r\n"); + + + #line 199 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + } + else + { + + + #line default + #line hidden + + #line 202 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + Write(provider.Name); + + + #line default + #line hidden + + #line 202 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } } @@ -395,7 +693,7 @@ WriteLiteral(" \r\n \r\n \r\n WriteLiteral(" "); - #line 104 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 212 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.DisplayFor(model => model.DeviceModel.ModelType)); @@ -406,54 +704,43 @@ WriteLiteral("\r\n \r\n \r\n \r\n WriteLiteral(" alt=\"Model Image\""); -WriteAttribute("src", Tuple.Create(" src=\"", 3910), Tuple.Create("\"", 4007) +WriteAttribute("src", Tuple.Create(" src=\"", 8619), Tuple.Create("\"", 8716) - #line 111 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" -, Tuple.Create(Tuple.Create("", 3916), Tuple.Create(Url.Action(MVC.API.DeviceModel.Image(Model.DeviceModel.Id, Model.DeviceModel.ImageHash())) + #line 219 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" +, Tuple.Create(Tuple.Create("", 8625), Tuple.Create(Url.Action(MVC.API.DeviceModel.Image(Model.DeviceModel.Id, Model.DeviceModel.ImageHash())) #line default #line hidden -, 3916), false) +, 8625), false) ); -WriteLiteral(" />\r\n \r\n \r\n"); +WriteLiteral(" />\r\n"); - #line 114 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - + #line 220 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line default #line hidden - #line 114 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - if (canConfig) - { + #line 220 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + if (canConfig) + { #line default #line hidden -WriteLiteral(" \r\n \r\n \r\n Update Image:\r\n \r\n " + -" \r\n \r\n"); +WriteLiteral("
\r\n"); - #line 123 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - - - #line default - #line hidden - - #line 123 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - using (Html.BeginForm(MVC.API.DeviceModel.Image(Model.DeviceModel.Id, true, null), FormMethod.Post, new { enctype = "multipart/form-data" })) + #line 223 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + using (Html.BeginForm(MVC.API.DeviceModel.Image(Model.DeviceModel.Id, true, null), FormMethod.Post, new { enctype = "multipart/form-data" })) { #line default #line hidden -WriteLiteral(" \r\n"); -WriteLiteral(" \r\n"); - #line 127 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 227 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } + } #line default #line hidden -WriteLiteral(" \r\n \r\n"); +WriteLiteral(" \r\n \r\n \r\n\r\n

Components

\r\n"); - #line 130 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - } - - - #line default - #line hidden -WriteLiteral(" \r\n"); - - - #line 132 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - - - #line default - #line hidden - - #line 132 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - if (canConfig) - { - - - #line default - #line hidden -WriteLiteral(" - $(function () { - var $Description = $('#DeviceModel_Description'); - var $DescriptionAjaxSave = $Description.next('.ajaxSave'); - $Description - .watermark('Model Description') - .focus(function () { $Description.select() }) - .keydown(function (e) { - $DescriptionAjaxSave.show(); - if (e.which == 13) { - $(this).blur(); - } - }).blur(function () { - $DescriptionAjaxSave.hide(); - }) - .change(function () { - $DescriptionAjaxSave.hide(); - var $ajaxLoading = $DescriptionAjaxSave.next('.ajaxLoading').show(); - var data = { Description: $Description.val() }; - $.ajax({ - url: '"); - - - #line 154 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - Write(Url.Action(MVC.API.DeviceModel.UpdateDescription(Model.DeviceModel.Id))); - - - #line default - #line hidden -WriteLiteral(@"', - dataType: 'json', - data: data, - success: function (d) { - if (d == 'OK') { - $ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow'); - } else { - $ajaxLoading.hide(); - alert('Unable to update description: ' + d); - } - }, - error: function (jqXHR, textStatus, errorThrown) { - alert('Unable to update description: ' + textStatus); - $ajaxLoading.hide(); - } - }); - }); - }); - -"); - -WriteLiteral(" - $(function () { - var $dataField = $('#DeviceModel_DefaultPurchaseDate'); - var $ajaxLoading = $dataField.next('.ajaxLoading'); - var dateFieldValue = $dataField.val(); - var dateFieldChangeToken = null; - $dataField - .watermark('None') - .datepicker({ - changeYear: true, - changeMonth: true, - dateFormat: 'yy/mm/dd' - }) - .change(function () { - var dateText = $dataField.val(); - if (dateFieldValue.toLowerCase() != dateText.toLowerCase()) { - dateFieldValue = dateText; - if (dateFieldChangeToken) - window.clearTimeout(dateFieldChangeToken); - dateFieldChangeToken = window.setTimeout(function () { - $ajaxLoading.show(); - var data = {}; - data['DefaultPurchaseDate'] = dateFieldValue; - $.getJSON('"); - - - #line 196 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - Write(Url.Action(MVC.API.DeviceModel.UpdateDefaultPurchaseDate(Model.DeviceModel.Id))); - - - #line default - #line hidden -WriteLiteral(@"', data, function (response, result) { - if (result != 'success' || response != 'OK') { - alert('Unable to change Date:\n' + response); - $ajaxLoading.hide(); - } else { - $ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow'); - } - }) - dateFieldChangeToken = null; - }, 500); - } - }).focus(function () { - $(this).select(); - }); - }); - -"); - -WriteLiteral(" - $(function () { - var $DefaultWarrantyProvider = $('#DeviceModel_DefaultWarrantyProvider'); - var $ajaxLoading = $DefaultWarrantyProvider.next('.ajaxLoading'); - $DefaultWarrantyProvider - .change(function () { - $ajaxLoading.show(); - var data = { DefaultWarrantyProvider: $DefaultWarrantyProvider.val() }; - $.ajax({ - url: '"); - - - #line 221 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - Write(Url.Action(MVC.API.DeviceModel.UpdateDefaultWarrantyProvider(Model.DeviceModel.Id))); - - - #line default - #line hidden -WriteLiteral(@"', - dataType: 'json', - data: data, - success: function (d) { - if (d == 'OK') { - $ajaxLoading.hide().next('.ajaxOk').show().delay('fast').fadeOut('slow'); - } else { - $ajaxLoading.hide(); - alert('Unable to default warranty provider: ' + d); - } - }, - error: function (jqXHR, textStatus, errorThrown) { - alert('Unable to default warranty provider: ' + textStatus); - $ajaxLoading.hide(); - } - }); - }); - }); - -"); - - - #line 240 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" - } - - - #line default - #line hidden -WriteLiteral("\r\n

Components

\r\n"); - - - #line 243 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 234 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.Partial(MVC.Config.DeviceModel.Views._DeviceComponentsTable, Model.DeviceComponentsModel)); @@ -681,13 +786,13 @@ WriteLiteral(" class=\"actionBar\""); WriteLiteral(">\r\n"); - #line 245 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 236 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" #line default #line hidden - #line 245 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 236 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" if (Model.CanDelete) { @@ -695,14 +800,14 @@ WriteLiteral(">\r\n"); #line default #line hidden - #line 247 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 238 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.ActionLinkButton("Delete", MVC.API.DeviceModel.Delete(Model.DeviceModel.Id, true), "buttonDelete")); #line default #line hidden - #line 247 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 238 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } @@ -712,7 +817,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 249 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 240 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" if (Model.DeviceCount > 0) { if (Authorization.Has(Claims.Device.Actions.Export)) @@ -722,14 +827,14 @@ WriteLiteral(" "); #line default #line hidden - #line 253 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 244 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.ActionLinkButton("Export Devices", MVC.Device.Export(null, Disco.Models.Services.Devices.Exporting.DeviceExportTypes.Model, Model.DeviceModel.Id))); #line default #line hidden - #line 253 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 244 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } if (Authorization.Has(Claims.Device.Search) && Model.DeviceCount > 0) @@ -739,14 +844,14 @@ WriteLiteral(" "); #line default #line hidden - #line 257 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 248 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" Write(Html.ActionLinkButton(string.Format("View {0} Device{1}", Model.DeviceCount, (Model.DeviceCount != 1 ? "s" : null)), MVC.Search.Query(Model.DeviceModel.Id.ToString(), "DeviceModel"))); #line default #line hidden - #line 257 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" + #line 248 "..\..\Areas\Config\Views\DeviceModel\Show.cshtml" } } diff --git a/Disco.Web/ClientSource/Style/Job.css b/Disco.Web/ClientSource/Style/Job.css index 48380dc2..abcdb53a 100644 --- a/Disco.Web/ClientSource/Style/Job.css +++ b/Disco.Web/ClientSource/Style/Job.css @@ -706,6 +706,24 @@ width: 600px; height: 250px; } +#repairJobForm #repairDisclosedInformation table { + font-size: 0.9em; +} +#repairJobForm #repairDisclosedInformation table tr:not(:last-child) { + border-bottom: 1px dashed #aaa; +} +#repairJobForm #repairDisclosedInformation table th { + padding: 2px; + font-weight: bold; + width: 200px; +} +#repairJobForm #repairDisclosedInformation table td { + padding: 2px; +} +#repairJobRepairDescription #RepairDescription { + width: 600px; + height: 250px; +} #createJob_Container { margin: 0 -20px; } diff --git a/Disco.Web/ClientSource/Style/Job.less b/Disco.Web/ClientSource/Style/Job.less index ff68e370..27167d8c 100644 --- a/Disco.Web/ClientSource/Style/Job.less +++ b/Disco.Web/ClientSource/Style/Job.less @@ -735,6 +735,35 @@ } } +#repairJobForm { + #repairDisclosedInformation { + table { + font-size: 0.9em; + + tr:not(:last-child) { + border-bottom: 1px dashed #aaa; + } + + th { + padding: 2px; + font-weight: bold; + width: 200px; + } + + td { + padding: 2px; + } + } + } +} + +#repairJobRepairDescription { + #RepairDescription { + width: 600px; + height: 250px; + } +} + #createJob_Container { margin: 0 -20px; diff --git a/Disco.Web/ClientSource/Style/Job.min.css b/Disco.Web/ClientSource/Style/Job.min.css index b625badf..916c4064 100644 --- a/Disco.Web/ClientSource/Style/Job.min.css +++ b/Disco.Web/ClientSource/Style/Job.min.css @@ -1 +1 @@ -.tableData{border:solid 1px #f4f4f4;border-collapse:collapse}.tableData>tbody>tr>td{border:solid 1px #f4f4f4;background-color:#fff}.tableData>tbody>tr:nth-child(odd)>td{background-color:#fcfcfc}.tableData>thead>tr>th,.tableData>tbody>tr>th{background-color:#f4f4f4;border:solid 1px #f4f4f4}.tableData>tbody>tr:hover>td{background-color:#fefefe}.tableData>tbody>tr:hover:nth-child(odd)>td{background-color:#fafafa}.tableData>tfoot>tr>th,.tableData>tfoot>tr>td{background-color:#f4f4f4}.tableDataDark{border:solid 1px #d8d8d8;border-collapse:collapse}.tableDataDark td{border:solid 1px #d8d8d8;background-color:#fff}.tableDataDark th{background-color:#eee;border:solid 1px #d8d8d8}.tableDataContainer{background-color:#fff}.tableDataVertical{border:solid 1px #f4f4f4;border-collapse:collapse}.tableDataVertical>tbody>tr:nth-child(odd){background-color:#f4f4f4;margin:0;padding:0}.tableDataVertical>tbody>tr>th.name{width:170px;text-align:right}.tableDataVertical table.sub>tbody>tr:not(:first-child)>th,.tableDataVertical table.sub>tbody>tr:not(:first-child)>td{border-top:1px dashed #aaa}.tableDataVertical table.sub>tbody>tr>th{font-weight:normal;text-align:right}.tableDataVertical table.sub>tbody>tr>th.name{text-align:right}.icon16{display:inline-block;height:16px;width:16px;margin-left:2px;cursor:pointer}.subtleUntilHover{-moz-opacity:.3;opacity:.3}.subtleUntilHover:hover{-moz-opacity:1;opacity:1}#layout_PageHeading #Job_Show_Status{margin-left:20px;display:inline-block;height:50px;font-family:"Segoe UI",Arial,Verdana,Tahoma,sans-serif;font-weight:lighter;font-stretch:condensed;font-size:.7em;text-transform:uppercase}#layout_PageHeading #Job_Show_Status span.icon{margin-right:6px}#layout_PageHeading #Job_Show_QueueStatus{display:inline-block;float:right;height:50px;font-size:.6em}#Job_List{padding-top:20px}#Job_List>.jobTable>h3{margin:30px 0 50px 20px!important}#Job_Show #Job_Show_Subjects{table-layout:fixed}#Job_Show #Job_Show_Subjects>tbody>tr>td{padding-top:0;height:100%}#Job_Show #Job_Show_Subjects>tbody>tr>td>div{position:relative}#Job_Show #Job_Show_Subjects>tbody>tr>td>div div.status{margin-top:2px;padding-top:2px;border-top:1px dashed #ddd}#Job_Show #Job_Show_Subjects>tbody>tr>td>div input.discreet{margin-left:-2px}#Job_Show #Job_Show_Subjects>tbody>tr>td:not(:last-child){border-right:1px dashed #aaa}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Type>table{table-layout:fixed}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_SubTypes_1,#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_SubTypes_2{padding-left:16px;font-weight:bold}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_SubTypes_Update{margin-left:16px;font-size:.9em}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_SubTypes_Update_Dialog{display:none}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Dates{padding-bottom:6px}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Dates table{table-layout:fixed}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Dates table>tbody>tr>td{vertical-align:middle}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Dates table>tbody>tr>td:first-child{font-weight:bold;width:60px}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_GenerateDocument_Container{padding-top:4px}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_GenerateDocument_Container #Job_Show_GenerateDocument{padding:0}#Job_Show #Job_Show_Subjects #Job_Show_Device>div{padding-left:102px;min-height:100px}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Model_Image{position:absolute;left:0;top:0;height:96px;width:96px}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details{float:left}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details_HWar,#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details_HNWar{float:right;border-left:1px dashed #ddd;padding-left:4px;margin-right:2px}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details_HWar_Details_Button,#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details_HNWar_Details_Button{font-size:.9em}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_DeviceHeld table{table-layout:fixed}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_DeviceHeld table>tbody>tr>td:first-child{width:62px}#Job_Show #Job_Show_Subjects #Job_Show_User #Job_Show_User_Flags{margin:4px 0;font-size:16px}#Job_Show #Job_Show_Subjects #Job_Show_User #Job_Show_User_Flags>i{cursor:default}#Job_Show #Job_Show_Subjects #Job_Show_User #Job_Show_User_Flags>i>.details{display:none}#Job_Show #Job_Show_Subjects #Job_Show_Subjects_Actions>td{padding-top:4px}#Job_Show #Job_Show_Subjects #Job_Show_Subjects_Actions #Job_Show_Device_Actions{padding-left:111px}#jobDetailTabs{margin-top:10px;border-radius:0;background-image:none;background-color:#fff;border:none;padding:0}#jobDetailTabs #jobDetailTabItems{border-radius:0;border-top:1px solid #ddd;border-right:1px solid #ddd;border-left:1px solid #ddd;border-bottom:none;padding:2px 0 0 4px;background-image:none;background-color:#eee;display:table}#jobDetailTabs #jobDetailTabItems>li{top:0;border-radius:0;margin:0 5px 0 0;padding:0;line-height:normal;margin-right:4px}#jobDetailTabs #jobDetailTabItems>li>a{padding:5px 8px}#jobDetailTabs div.ui-tabs-panel{border-radius:0;padding:4px;border-right:1px solid #ddd;border-bottom:1px solid #ddd;border-left:1px solid #ddd;border-top:none;background-color:#eee}#jobShowResources #CommentsContainer{padding:0;width:375px}#jobShowResources #Comments{height:300px;padding:0;border:1px solid #ccc;background-color:#fff}#jobShowResources #Comments div.commentOutput{height:249px;overflow:auto;background-color:#fafafa;color:#000}#jobShowResources #Comments div.commentOutput>div{padding:3px;margin:4px 6px;border-bottom:1px solid #ccc}#jobShowResources #Comments div.commentOutput>div span.author{color:#444;display:block;font-weight:bold;font-size:.95em;float:left}#jobShowResources #Comments div.commentOutput>div span.timestamp{display:block;float:right;font-size:.9em;font-style:italic}#jobShowResources #Comments div.commentOutput>div div.comment{clear:both;display:block;margin-left:4px}#jobShowResources #Comments div.commentOutput>div div.comment p{line-height:1.2em}#jobShowResources #Comments div.commentOutput>div:hover span.remove{opacity:.5}#jobShowResources #Comments div.commentOutput>div span.remove{font-size:1.2em;color:#e51400;margin-left:6px;cursor:pointer;opacity:0}#jobShowResources #Comments div.commentOutput>div span.remove:hover{opacity:1}#jobShowResources #Comments div.commentOutput>div:last-child{border-bottom:none}#jobShowResources #Comments.cannotAddLogs div.commentOutput{height:300px}#jobShowResources #Comments div.commentInput{border-top:1px solid #ccc;height:40px;padding:5px}#jobShowResources #Comments div.commentInput textarea.commentInput{border:0;padding:0;margin:0;width:325px;height:40px;min-height:40px;overflow:auto;float:left;resize:none}#jobShowResources #Comments div.commentInput span.action{color:#333;font-size:1.5em;display:block;margin:0;cursor:pointer;float:left;border:1px solid #fff;padding:.5em}#jobShowResources #Comments div.commentInput span.action:hover{color:#335a87;background-color:#ededed;border:1px solid #ccc}#jobShowResources #AttachmentsContainer{padding:0}#jobShowResources #Attachments{position:relative;height:300px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc;background-color:#fff}#jobShowResources #Attachments div.attachmentOutput{position:relative;height:249px;overflow:auto}#jobShowResources #Attachments div.attachmentOutput>a{display:block;float:left;height:48px;width:221px;padding:2px;margin:2px;font-size:.95em;border:1px solid #fff;color:#000;text-decoration:none}#jobShowResources #Attachments div.attachmentOutput>a span.comments,#jobShowResources #Attachments div.attachmentOutput>a span.author,#jobShowResources #Attachments div.attachmentOutput>a span.timestamp{display:block;float:left;width:168px;overflow:hidden;height:16px}#jobShowResources #Attachments div.attachmentOutput>a span.author{color:#888;width:150px}#jobShowResources #Attachments div.attachmentOutput>a span.timestamp{color:#888;font-style:italic}#jobShowResources #Attachments div.attachmentOutput>a span.icon{display:block;float:left;height:48px;width:48px;margin-right:2px}#jobShowResources #Attachments div.attachmentOutput>a span.icon img{height:48px;width:48px}#jobShowResources #Attachments div.attachmentOutput>a span.icon img.loading{display:none}#jobShowResources #Attachments div.attachmentOutput>a:hover{background-color:#ededed;border:1px solid #ccc}#jobShowResources #Attachments div.attachmentOutput>a:hover span.remove{opacity:.5}#jobShowResources #Attachments div.attachmentOutput>a span.remove{font-size:1.2em;color:#e51400;margin-left:2px;cursor:pointer;opacity:0}#jobShowResources #Attachments div.attachmentOutput>a span.remove:hover{opacity:1}#jobShowResources #Attachments.cannotAddAttachments div.attachmentOutput{height:300px}#jobShowResources #Attachments div.attachmentInput{border-top:1px solid #ccc;height:40px;background-color:#fff;padding:5px}#jobShowResources #Attachments div.attachmentInput span.action{color:#333;display:block;margin:0 4px 0 0;font-size:1.5em;cursor:pointer;float:right;border:1px solid #fff;padding:.5em}#jobShowResources #Attachments div.attachmentInput span.action:hover{color:#335a87;background-color:#ededed;border:1px solid #ccc}#Job_Show_Job_Actions_AddQueue_Dialog{height:400px}#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker{position:absolute;width:250px;height:300px;overflow-y:auto;background-color:#fcfcfc;border:1px solid #ccc}#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker>div{background-color:#fff;border-bottom:1px solid #ddd;padding:6px 0 6px 6px;cursor:pointer}#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker>div:hover{background-color:#f4f4f4}#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker>div.selected,#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker>div.selected:hover{background-color:#eee}#Job_Show_Job_Actions_AddQueue_Dialog .details{display:none;position:absolute;left:280px;top:30px}#Job_Show_Job_Actions_AddQueue_Dialog .details h4{margin-bottom:4px}#Job_Show_Job_Actions_AddQueue_Dialog .details>div{margin:5px 0}#Job_Show_Job_Actions_AddQueue_Dialog .details select{min-width:270px}#Job_Show_Job_Actions_AddQueue_Dialog .details textarea{min-width:270px;height:100px}#jobDetailTab-Queues #jobQueues{border:solid 1px #d8d8d8;border-collapse:collapse;table-layout:fixed}#jobDetailTab-Queues #jobQueues td{border:solid 1px #d8d8d8;background-color:#fff}#jobDetailTab-Queues #jobQueues th{background-color:#eee;border:solid 1px #d8d8d8}#jobDetailTab-Queues #jobQueues i.fa-edit{float:right;margin-top:4px;font-size:1.1em;cursor:pointer;display:none;color:#335a87}#jobDetailTab-Queues #jobQueues i.fa-edit:hover{color:#5e8cc2}#jobDetailTab-Queues #jobQueues td:hover i.fa-edit{display:inline-block}#jobDetailTab-Queues #jobQueues th.name{width:200px}#jobDetailTab-Queues #jobQueues th.sla{width:130px}#jobDetailTab-Queues #jobQueues tr.removed td{background-color:#f4f4f4}#jobDetailTab-Queues #jobQueues td.name{vertical-align:middle}#jobDetailTab-Queues #jobQueues td.name .fa-stack{line-height:1.6em}#jobDetailTab-Queues #jobQueues td.added .when,#jobDetailTab-Queues #jobQueues td.removed .when{font-style:italic;margin-top:4px;font-size:.9em}#jobDetailTab-Queues #jobQueues td.added .commentsRaw,#jobDetailTab-Queues #jobQueues td.removed .commentsRaw{display:none}#jobDetailTab-Queues #jobQueues td.removed.na{vertical-align:middle;text-align:center}#jobDetailTab-Queues #jobQueues td.sla{vertical-align:middle}#jobDetailTab-Queues #jobQueues td.sla.overdue{color:#e51400}#jobDetailTab-Queues>.none{text-align:center;padding:30px 0;font-style:italic;background-color:#fff}#Job_Show_Queues_Actions_EditAddedComment_Dialog h4,#Job_Show_Queues_Actions_EditRemovedComment_Dialog h4,#Job_Show_Queues_Actions_EditSla_Dialog h4{margin-bottom:4px}#Job_Show_Queues_Actions_EditAddedComment_Dialog_Comment{width:280px}#Job_Show_Queues_Actions_EditRemovedComment_Dialog_Comment{width:280px}#jobComponents{border:solid 1px #d8d8d8;border-collapse:collapse}#jobComponents td{border:solid 1px #d8d8d8;background-color:#fff}#jobComponents th{background-color:#eee;border:solid 1px #d8d8d8}#jobComponents tr th.actions{width:18px}#jobComponents tr input.description{width:400px}#jobComponents tr input.cost{width:150px}#jobComponents tr span.remove{font-size:1.5em;color:#e51400;cursor:pointer;opacity:.5}#jobComponents tr span.remove:hover{opacity:1}#jobComponents tr input.updating{background-position:right center;background-repeat:no-repeat;background-image:url(data:image/gif;base64,R0lGODlhEAALAPQAAP///zNah+Hm7dng6O7x9DddiTNah1d3nJqtw3+Xs8fS3k5vlm6JqaGzx4KatcrU4FFymDZciHGMq+ru8t/l7Pb3+V9+oeLo7vT2+MTP3LLB0dTc5fHz9gAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCwAAACwAAAAAEAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJCwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJCwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHTuBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V55zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAAABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7AAAAAAAAAAAA)}#jobComponents tr .totalCost{font-weight:bold}#jobWarrantyDetails{border:solid 1px #d8d8d8;border-collapse:collapse}#jobWarrantyDetails td{border:solid 1px #d8d8d8;background-color:#fff}#jobWarrantyDetails th{background-color:#eee;border:solid 1px #d8d8d8}#jobWarrantyDetails tr th{width:200px;text-align:right}#jobNonWarrantyFinance{border:solid 1px #d8d8d8;border-collapse:collapse}#jobNonWarrantyFinance td{border:solid 1px #d8d8d8;background-color:#fff}#jobNonWarrantyFinance th{background-color:#eee;border:solid 1px #d8d8d8}#jobNonWarrantyFinance tr th{width:200px;text-align:right}#jobNonWarrantyRepairs{border:solid 1px #d8d8d8;border-collapse:collapse}#jobNonWarrantyRepairs td{border:solid 1px #d8d8d8;background-color:#fff}#jobNonWarrantyRepairs th{background-color:#eee;border:solid 1px #d8d8d8}#jobNonWarrantyRepairs tr th{width:200px;text-align:right}#jobNonWarrantyInsurance{border:solid 1px #d8d8d8;border-collapse:collapse}#jobNonWarrantyInsurance td{border:solid 1px #d8d8d8;background-color:#fff}#jobNonWarrantyInsurance th{background-color:#eee;border:solid 1px #d8d8d8}#jobNonWarrantyInsurance tr th{width:200px;text-align:right}#jobNonWarrantyInsurance tr td textarea{width:400px}#jobFlags{border:solid 1px #d8d8d8;border-collapse:collapse}#jobFlags td{border:solid 1px #d8d8d8;background-color:#fff}#jobFlags th{background-color:#eee;border:solid 1px #d8d8d8}#jobFlags tr th{width:200px;text-align:right}#warrantyJobForm #warrantyDisclosedInformation table{font-size:.9em}#warrantyJobForm #warrantyDisclosedInformation table tr:not(:last-child){border-bottom:1px dashed #aaa}#warrantyJobForm #warrantyDisclosedInformation table th{padding:2px;font-weight:bold;width:200px}#warrantyJobForm #warrantyDisclosedInformation table td{padding:2px}#warrantyJobFaultDescription #FaultDescription{width:600px;height:250px}#createJob_Container{margin:0 -20px}#createJob_Container img.modelImage{width:64px;height:64px}#createJob_Container .createJob_Component{margin:0 10px;padding:5px 0;border-bottom:1px dashed #ccc}#createJob_Container .createJob_Component:last-child{border-bottom:none}#createJob_Container #createJob_Type{border:1px solid #ccc;background-color:#f2f2f2;padding:2px 4px}#createJob_Container #createJob_SubTypes{margin:-1px 0 0 20px;border:1px solid #ccc;border-top:none;padding:2px 4px;background-color:#f2f2f2}#createJob_Container #createJob_SubTypes .createJob_SubType{display:none}#createJob_Container #createJob_Type li,#createJob_Container #createJob_SubTypes li{margin:2px 0;padding:0 0 0 4px}#createJob_Container #createJob_Type li i,#createJob_Container #createJob_SubTypes li i{display:none;cursor:default;font-weight:normal}#createJob_Container #createJob_Type li:hover i,#createJob_Container #createJob_SubTypes li:hover i{display:inline-block}#createJob_Container #createJob_Type li.highlight,#createJob_Container #createJob_SubTypes li.highlight{background-color:#cddbec;font-weight:600;color:#000}#createJob_Container #createJob_Type li.highlight i,#createJob_Container #createJob_SubTypes li.highlight i{display:inline-block}#createJob_Container #createJob_SubTypes.isQuickLog li i{display:none}#createJob_Container #createJob_CommentsContainer #Comments{width:100%;min-width:500px}#createJob_Container #createJob_QuickLogAutoCloseContainer h3{margin-bottom:4px}#createJob_Container #createJob_QuickLogAutoCloseContainer input{margin-left:4px}#createJob_Container #createJob_QuickLogTaskTimeContainer{display:none;margin:4px 0 0 25px;padding:4px 4px;background-color:#f2f2f2;border-left:4px solid #d8d8d8}#createJob_Container #createJob_QuickLogTaskTimeContainer h4{display:inline-block;padding-right:10px}#createJob_Container #createJob_QuickLogTaskTimeContainer label{margin-right:15px}#createJob_Container #createJob_QuickLogTaskTimeContainer #createJob_TaskTimeOtherMinutesContainer{display:none}#createJob_Container #createJob_QuickLogTaskTimeContainer #createJob_TaskTimeOtherMinutes{width:50px}#createJobRedirect h1{margin-top:60px!important;margin-bottom:60px}#createJobRedirect>div{text-align:right}#createJobRedirect>div i{margin-right:10px} \ No newline at end of file +.tableData{border:solid 1px #f4f4f4;border-collapse:collapse}.tableData>tbody>tr>td{border:solid 1px #f4f4f4;background-color:#fff}.tableData>tbody>tr:nth-child(odd)>td{background-color:#fcfcfc}.tableData>thead>tr>th,.tableData>tbody>tr>th{background-color:#f4f4f4;border:solid 1px #f4f4f4}.tableData>tbody>tr:hover>td{background-color:#fefefe}.tableData>tbody>tr:hover:nth-child(odd)>td{background-color:#fafafa}.tableData>tfoot>tr>th,.tableData>tfoot>tr>td{background-color:#f4f4f4}.tableDataDark{border:solid 1px #d8d8d8;border-collapse:collapse}.tableDataDark td{border:solid 1px #d8d8d8;background-color:#fff}.tableDataDark th{background-color:#eee;border:solid 1px #d8d8d8}.tableDataContainer{background-color:#fff}.tableDataVertical{border:solid 1px #f4f4f4;border-collapse:collapse}.tableDataVertical>tbody>tr:nth-child(odd){background-color:#f4f4f4;margin:0;padding:0}.tableDataVertical>tbody>tr>th.name{width:170px;text-align:right}.tableDataVertical table.sub>tbody>tr:not(:first-child)>th,.tableDataVertical table.sub>tbody>tr:not(:first-child)>td{border-top:1px dashed #aaa}.tableDataVertical table.sub>tbody>tr>th{font-weight:normal;text-align:right}.tableDataVertical table.sub>tbody>tr>th.name{text-align:right}.icon16{display:inline-block;height:16px;width:16px;margin-left:2px;cursor:pointer}.subtleUntilHover{-moz-opacity:.3;opacity:.3}.subtleUntilHover:hover{-moz-opacity:1;opacity:1}#layout_PageHeading #Job_Show_Status{margin-left:20px;display:inline-block;height:50px;font-family:"Segoe UI",Arial,Verdana,Tahoma,sans-serif;font-weight:lighter;font-stretch:condensed;font-size:.7em;text-transform:uppercase}#layout_PageHeading #Job_Show_Status span.icon{margin-right:6px}#layout_PageHeading #Job_Show_QueueStatus{display:inline-block;float:right;height:50px;font-size:.6em}#Job_List{padding-top:20px}#Job_List>.jobTable>h3{margin:30px 0 50px 20px!important}#Job_Show #Job_Show_Subjects{table-layout:fixed}#Job_Show #Job_Show_Subjects>tbody>tr>td{padding-top:0;height:100%}#Job_Show #Job_Show_Subjects>tbody>tr>td>div{position:relative}#Job_Show #Job_Show_Subjects>tbody>tr>td>div div.status{margin-top:2px;padding-top:2px;border-top:1px dashed #ddd}#Job_Show #Job_Show_Subjects>tbody>tr>td>div input.discreet{margin-left:-2px}#Job_Show #Job_Show_Subjects>tbody>tr>td:not(:last-child){border-right:1px dashed #aaa}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Type>table{table-layout:fixed}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_SubTypes_1,#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_SubTypes_2{padding-left:16px;font-weight:bold}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_SubTypes_Update{margin-left:16px;font-size:.9em}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_SubTypes_Update_Dialog{display:none}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Dates{padding-bottom:6px}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Dates table{table-layout:fixed}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Dates table>tbody>tr>td{vertical-align:middle}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_Job_Dates table>tbody>tr>td:first-child{font-weight:bold;width:60px}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_GenerateDocument_Container{padding-top:4px}#Job_Show #Job_Show_Subjects #Job_Show_Job #Job_Show_GenerateDocument_Container #Job_Show_GenerateDocument{padding:0}#Job_Show #Job_Show_Subjects #Job_Show_Device>div{padding-left:102px;min-height:100px}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Model_Image{position:absolute;left:0;top:0;height:96px;width:96px}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details{float:left}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details_HWar,#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details_HNWar{float:right;border-left:1px dashed #ddd;padding-left:4px;margin-right:2px}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details_HWar_Details_Button,#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_Details_HNWar_Details_Button{font-size:.9em}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_DeviceHeld table{table-layout:fixed}#Job_Show #Job_Show_Subjects #Job_Show_Device #Job_Show_Device_DeviceHeld table>tbody>tr>td:first-child{width:62px}#Job_Show #Job_Show_Subjects #Job_Show_User #Job_Show_User_Flags{margin:4px 0;font-size:16px}#Job_Show #Job_Show_Subjects #Job_Show_User #Job_Show_User_Flags>i{cursor:default}#Job_Show #Job_Show_Subjects #Job_Show_User #Job_Show_User_Flags>i>.details{display:none}#Job_Show #Job_Show_Subjects #Job_Show_Subjects_Actions>td{padding-top:4px}#Job_Show #Job_Show_Subjects #Job_Show_Subjects_Actions #Job_Show_Device_Actions{padding-left:111px}#jobDetailTabs{margin-top:10px;border-radius:0;background-image:none;background-color:#fff;border:none;padding:0}#jobDetailTabs #jobDetailTabItems{border-radius:0;border-top:1px solid #ddd;border-right:1px solid #ddd;border-left:1px solid #ddd;border-bottom:none;padding:2px 0 0 4px;background-image:none;background-color:#eee;display:table}#jobDetailTabs #jobDetailTabItems>li{top:0;border-radius:0;margin:0 5px 0 0;padding:0;line-height:normal;margin-right:4px}#jobDetailTabs #jobDetailTabItems>li>a{padding:5px 8px}#jobDetailTabs div.ui-tabs-panel{border-radius:0;padding:4px;border-right:1px solid #ddd;border-bottom:1px solid #ddd;border-left:1px solid #ddd;border-top:none;background-color:#eee}#jobShowResources #CommentsContainer{padding:0;width:375px}#jobShowResources #Comments{height:300px;padding:0;border:1px solid #ccc;background-color:#fff}#jobShowResources #Comments div.commentOutput{height:249px;overflow:auto;background-color:#fafafa;color:#000}#jobShowResources #Comments div.commentOutput>div{padding:3px;margin:4px 6px;border-bottom:1px solid #ccc}#jobShowResources #Comments div.commentOutput>div span.author{color:#444;display:block;font-weight:bold;font-size:.95em;float:left}#jobShowResources #Comments div.commentOutput>div span.timestamp{display:block;float:right;font-size:.9em;font-style:italic}#jobShowResources #Comments div.commentOutput>div div.comment{clear:both;display:block;margin-left:4px}#jobShowResources #Comments div.commentOutput>div div.comment p{line-height:1.2em}#jobShowResources #Comments div.commentOutput>div:hover span.remove{opacity:.5}#jobShowResources #Comments div.commentOutput>div span.remove{font-size:1.2em;color:#e51400;margin-left:6px;cursor:pointer;opacity:0}#jobShowResources #Comments div.commentOutput>div span.remove:hover{opacity:1}#jobShowResources #Comments div.commentOutput>div:last-child{border-bottom:none}#jobShowResources #Comments.cannotAddLogs div.commentOutput{height:300px}#jobShowResources #Comments div.commentInput{border-top:1px solid #ccc;height:40px;padding:5px}#jobShowResources #Comments div.commentInput textarea.commentInput{border:0;padding:0;margin:0;width:325px;height:40px;min-height:40px;overflow:auto;float:left;resize:none}#jobShowResources #Comments div.commentInput span.action{color:#333;font-size:1.5em;display:block;margin:0;cursor:pointer;float:left;border:1px solid #fff;padding:.5em}#jobShowResources #Comments div.commentInput span.action:hover{color:#335a87;background-color:#ededed;border:1px solid #ccc}#jobShowResources #AttachmentsContainer{padding:0}#jobShowResources #Attachments{position:relative;height:300px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc;background-color:#fff}#jobShowResources #Attachments div.attachmentOutput{position:relative;height:249px;overflow:auto}#jobShowResources #Attachments div.attachmentOutput>a{display:block;float:left;height:48px;width:221px;padding:2px;margin:2px;font-size:.95em;border:1px solid #fff;color:#000;text-decoration:none}#jobShowResources #Attachments div.attachmentOutput>a span.comments,#jobShowResources #Attachments div.attachmentOutput>a span.author,#jobShowResources #Attachments div.attachmentOutput>a span.timestamp{display:block;float:left;width:168px;overflow:hidden;height:16px}#jobShowResources #Attachments div.attachmentOutput>a span.author{color:#888;width:150px}#jobShowResources #Attachments div.attachmentOutput>a span.timestamp{color:#888;font-style:italic}#jobShowResources #Attachments div.attachmentOutput>a span.icon{display:block;float:left;height:48px;width:48px;margin-right:2px}#jobShowResources #Attachments div.attachmentOutput>a span.icon img{height:48px;width:48px}#jobShowResources #Attachments div.attachmentOutput>a span.icon img.loading{display:none}#jobShowResources #Attachments div.attachmentOutput>a:hover{background-color:#ededed;border:1px solid #ccc}#jobShowResources #Attachments div.attachmentOutput>a:hover span.remove{opacity:.5}#jobShowResources #Attachments div.attachmentOutput>a span.remove{font-size:1.2em;color:#e51400;margin-left:2px;cursor:pointer;opacity:0}#jobShowResources #Attachments div.attachmentOutput>a span.remove:hover{opacity:1}#jobShowResources #Attachments.cannotAddAttachments div.attachmentOutput{height:300px}#jobShowResources #Attachments div.attachmentInput{border-top:1px solid #ccc;height:40px;background-color:#fff;padding:5px}#jobShowResources #Attachments div.attachmentInput span.action{color:#333;display:block;margin:0 4px 0 0;font-size:1.5em;cursor:pointer;float:right;border:1px solid #fff;padding:.5em}#jobShowResources #Attachments div.attachmentInput span.action:hover{color:#335a87;background-color:#ededed;border:1px solid #ccc}#Job_Show_Job_Actions_AddQueue_Dialog{height:400px}#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker{position:absolute;width:250px;height:300px;overflow-y:auto;background-color:#fcfcfc;border:1px solid #ccc}#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker>div{background-color:#fff;border-bottom:1px solid #ddd;padding:6px 0 6px 6px;cursor:pointer}#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker>div:hover{background-color:#f4f4f4}#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker>div.selected,#Job_Show_Job_Actions_AddQueue_Dialog .queuePicker>div.selected:hover{background-color:#eee}#Job_Show_Job_Actions_AddQueue_Dialog .details{display:none;position:absolute;left:280px;top:30px}#Job_Show_Job_Actions_AddQueue_Dialog .details h4{margin-bottom:4px}#Job_Show_Job_Actions_AddQueue_Dialog .details>div{margin:5px 0}#Job_Show_Job_Actions_AddQueue_Dialog .details select{min-width:270px}#Job_Show_Job_Actions_AddQueue_Dialog .details textarea{min-width:270px;height:100px}#jobDetailTab-Queues #jobQueues{border:solid 1px #d8d8d8;border-collapse:collapse;table-layout:fixed}#jobDetailTab-Queues #jobQueues td{border:solid 1px #d8d8d8;background-color:#fff}#jobDetailTab-Queues #jobQueues th{background-color:#eee;border:solid 1px #d8d8d8}#jobDetailTab-Queues #jobQueues i.fa-edit{float:right;margin-top:4px;font-size:1.1em;cursor:pointer;display:none;color:#335a87}#jobDetailTab-Queues #jobQueues i.fa-edit:hover{color:#5e8cc2}#jobDetailTab-Queues #jobQueues td:hover i.fa-edit{display:inline-block}#jobDetailTab-Queues #jobQueues th.name{width:200px}#jobDetailTab-Queues #jobQueues th.sla{width:130px}#jobDetailTab-Queues #jobQueues tr.removed td{background-color:#f4f4f4}#jobDetailTab-Queues #jobQueues td.name{vertical-align:middle}#jobDetailTab-Queues #jobQueues td.name .fa-stack{line-height:1.6em}#jobDetailTab-Queues #jobQueues td.added .when,#jobDetailTab-Queues #jobQueues td.removed .when{font-style:italic;margin-top:4px;font-size:.9em}#jobDetailTab-Queues #jobQueues td.added .commentsRaw,#jobDetailTab-Queues #jobQueues td.removed .commentsRaw{display:none}#jobDetailTab-Queues #jobQueues td.removed.na{vertical-align:middle;text-align:center}#jobDetailTab-Queues #jobQueues td.sla{vertical-align:middle}#jobDetailTab-Queues #jobQueues td.sla.overdue{color:#e51400}#jobDetailTab-Queues>.none{text-align:center;padding:30px 0;font-style:italic;background-color:#fff}#Job_Show_Queues_Actions_EditAddedComment_Dialog h4,#Job_Show_Queues_Actions_EditRemovedComment_Dialog h4,#Job_Show_Queues_Actions_EditSla_Dialog h4{margin-bottom:4px}#Job_Show_Queues_Actions_EditAddedComment_Dialog_Comment{width:280px}#Job_Show_Queues_Actions_EditRemovedComment_Dialog_Comment{width:280px}#jobComponents{border:solid 1px #d8d8d8;border-collapse:collapse}#jobComponents td{border:solid 1px #d8d8d8;background-color:#fff}#jobComponents th{background-color:#eee;border:solid 1px #d8d8d8}#jobComponents tr th.actions{width:18px}#jobComponents tr input.description{width:400px}#jobComponents tr input.cost{width:150px}#jobComponents tr span.remove{font-size:1.5em;color:#e51400;cursor:pointer;opacity:.5}#jobComponents tr span.remove:hover{opacity:1}#jobComponents tr input.updating{background-position:right center;background-repeat:no-repeat;background-image:url(data:image/gif;base64,R0lGODlhEAALAPQAAP///zNah+Hm7dng6O7x9DddiTNah1d3nJqtw3+Xs8fS3k5vlm6JqaGzx4KatcrU4FFymDZciHGMq+ru8t/l7Pb3+V9+oeLo7vT2+MTP3LLB0dTc5fHz9gAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCwAAACwAAAAAEAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJCwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJCwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHTuBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V55zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAAABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7AAAAAAAAAAAA)}#jobComponents tr .totalCost{font-weight:bold}#jobWarrantyDetails{border:solid 1px #d8d8d8;border-collapse:collapse}#jobWarrantyDetails td{border:solid 1px #d8d8d8;background-color:#fff}#jobWarrantyDetails th{background-color:#eee;border:solid 1px #d8d8d8}#jobWarrantyDetails tr th{width:200px;text-align:right}#jobNonWarrantyFinance{border:solid 1px #d8d8d8;border-collapse:collapse}#jobNonWarrantyFinance td{border:solid 1px #d8d8d8;background-color:#fff}#jobNonWarrantyFinance th{background-color:#eee;border:solid 1px #d8d8d8}#jobNonWarrantyFinance tr th{width:200px;text-align:right}#jobNonWarrantyRepairs{border:solid 1px #d8d8d8;border-collapse:collapse}#jobNonWarrantyRepairs td{border:solid 1px #d8d8d8;background-color:#fff}#jobNonWarrantyRepairs th{background-color:#eee;border:solid 1px #d8d8d8}#jobNonWarrantyRepairs tr th{width:200px;text-align:right}#jobNonWarrantyInsurance{border:solid 1px #d8d8d8;border-collapse:collapse}#jobNonWarrantyInsurance td{border:solid 1px #d8d8d8;background-color:#fff}#jobNonWarrantyInsurance th{background-color:#eee;border:solid 1px #d8d8d8}#jobNonWarrantyInsurance tr th{width:200px;text-align:right}#jobNonWarrantyInsurance tr td textarea{width:400px}#jobFlags{border:solid 1px #d8d8d8;border-collapse:collapse}#jobFlags td{border:solid 1px #d8d8d8;background-color:#fff}#jobFlags th{background-color:#eee;border:solid 1px #d8d8d8}#jobFlags tr th{width:200px;text-align:right}#warrantyJobForm #warrantyDisclosedInformation table{font-size:.9em}#warrantyJobForm #warrantyDisclosedInformation table tr:not(:last-child){border-bottom:1px dashed #aaa}#warrantyJobForm #warrantyDisclosedInformation table th{padding:2px;font-weight:bold;width:200px}#warrantyJobForm #warrantyDisclosedInformation table td{padding:2px}#warrantyJobFaultDescription #FaultDescription{width:600px;height:250px}#repairJobForm #repairDisclosedInformation table{font-size:.9em}#repairJobForm #repairDisclosedInformation table tr:not(:last-child){border-bottom:1px dashed #aaa}#repairJobForm #repairDisclosedInformation table th{padding:2px;font-weight:bold;width:200px}#repairJobForm #repairDisclosedInformation table td{padding:2px}#repairJobRepairDescription #RepairDescription{width:600px;height:250px}#createJob_Container{margin:0 -20px}#createJob_Container img.modelImage{width:64px;height:64px}#createJob_Container .createJob_Component{margin:0 10px;padding:5px 0;border-bottom:1px dashed #ccc}#createJob_Container .createJob_Component:last-child{border-bottom:none}#createJob_Container #createJob_Type{border:1px solid #ccc;background-color:#f2f2f2;padding:2px 4px}#createJob_Container #createJob_SubTypes{margin:-1px 0 0 20px;border:1px solid #ccc;border-top:none;padding:2px 4px;background-color:#f2f2f2}#createJob_Container #createJob_SubTypes .createJob_SubType{display:none}#createJob_Container #createJob_Type li,#createJob_Container #createJob_SubTypes li{margin:2px 0;padding:0 0 0 4px}#createJob_Container #createJob_Type li i,#createJob_Container #createJob_SubTypes li i{display:none;cursor:default;font-weight:normal}#createJob_Container #createJob_Type li:hover i,#createJob_Container #createJob_SubTypes li:hover i{display:inline-block}#createJob_Container #createJob_Type li.highlight,#createJob_Container #createJob_SubTypes li.highlight{background-color:#cddbec;font-weight:600;color:#000}#createJob_Container #createJob_Type li.highlight i,#createJob_Container #createJob_SubTypes li.highlight i{display:inline-block}#createJob_Container #createJob_SubTypes.isQuickLog li i{display:none}#createJob_Container #createJob_CommentsContainer #Comments{width:100%;min-width:500px}#createJob_Container #createJob_QuickLogAutoCloseContainer h3{margin-bottom:4px}#createJob_Container #createJob_QuickLogAutoCloseContainer input{margin-left:4px}#createJob_Container #createJob_QuickLogTaskTimeContainer{display:none;margin:4px 0 0 25px;padding:4px 4px;background-color:#f2f2f2;border-left:4px solid #d8d8d8}#createJob_Container #createJob_QuickLogTaskTimeContainer h4{display:inline-block;padding-right:10px}#createJob_Container #createJob_QuickLogTaskTimeContainer label{margin-right:15px}#createJob_Container #createJob_QuickLogTaskTimeContainer #createJob_TaskTimeOtherMinutesContainer{display:none}#createJob_Container #createJob_QuickLogTaskTimeContainer #createJob_TaskTimeOtherMinutes{width:50px}#createJobRedirect h1{margin-top:60px!important;margin-bottom:60px}#createJobRedirect>div{text-align:right}#createJobRedirect>div i{margin-right:10px} \ No newline at end of file diff --git a/Disco.Web/Controllers/JobController.cs b/Disco.Web/Controllers/JobController.cs index 891e2f1a..452a2034 100644 --- a/Disco.Web/Controllers/JobController.cs +++ b/Disco.Web/Controllers/JobController.cs @@ -1,5 +1,4 @@ using Disco.BI.Extensions; -using Disco.Data.Repository; using Disco.Models.BI.Job; using Disco.Models.Repository; using Disco.Models.Services.Jobs.JobLists; @@ -8,6 +7,7 @@ using Disco.Services; using Disco.Services.Authorization; using Disco.Services.Jobs.JobLists; using Disco.Services.Jobs.JobQueues; +using Disco.Services.Plugins.Features.RepairProvider; using Disco.Services.Plugins.Features.UIExtension; using Disco.Services.Plugins.Features.WarrantyProvider; using Disco.Services.Users; @@ -503,7 +503,7 @@ namespace Disco.Web.Controllers if (ModelState.IsValid) { - switch (m.WarrantyAction) + switch (m.SubmissionAction) { case "Update": var updatedModel = new Models.Job.LogWarrantyModel() @@ -528,15 +528,15 @@ namespace Disco.Web.Controllers } return View(updatedModel); - case "Custom": - if (string.IsNullOrWhiteSpace(m.CustomProviderName)) + case "Manual": + if (string.IsNullOrWhiteSpace(m.ManualProviderName)) { - ModelState.AddModelError("CustomProviderName", "The Custom Warranty Provider Name is required"); + ModelState.AddModelError("ManualProviderName", "The Warranty Provider Name is required"); return View(Views.LogWarranty, m); } try { - m.Job.OnLogWarranty(Database, m.FaultDescription, m.CustomProviderName, m.CustomProviderReference, m.OrganisationAddress, m.TechUser); + m.Job.OnLogWarranty(Database, m.FaultDescription, m.ManualProviderName, m.ManualProviderReference, m.OrganisationAddress, m.TechUser); Database.SaveChanges(); return RedirectToAction(MVC.Job.Show(m.JobId)); } @@ -564,7 +564,7 @@ namespace Disco.Web.Controllers if (warrantyProviderProperties != null) { - m.WarrantyProviderPropertiesJson = JsonConvert.SerializeObject(warrantyProviderProperties); + m.ProviderPropertiesJson = JsonConvert.SerializeObject(warrantyProviderProperties); } m.DiscloseProperties = p.SubmitJobDiscloseInfo(Database, m.Job, m.OrganisationAddress, m.TechUser, m.FaultDescription, warrantyProviderProperties); return View(Views.LogWarrantyDisclose, m); @@ -572,7 +572,7 @@ namespace Disco.Web.Controllers case "Submit": try { - m.Job.OnLogWarranty(Database, m.FaultDescription, m.WarrantyProvider, m.OrganisationAddress, m.TechUser, m.WarrantyProviderProperties()); + m.Job.OnLogWarranty(Database, m.FaultDescription, m.WarrantyProvider, m.OrganisationAddress, m.TechUser, m.ProviderProperties()); Database.SaveChanges(); return RedirectToAction(MVC.Job.Show(m.JobId)); } @@ -596,7 +596,7 @@ namespace Disco.Web.Controllers [DiscoAuthorize(Claims.Job.Properties.WarrantyProperties.ProviderDetails)] public virtual ActionResult WarrantyProviderJobDetails(int id) { - Models.Job.WarrantyProviderJobDetailsModel model = new Models.Job.WarrantyProviderJobDetailsModel(); + Models.Job.ProviderJobDetailsModel model = new Models.Job.ProviderJobDetailsModel(); Job job = Database.Jobs.Include("Device.DeviceModel").Include("JobMetaWarranty").Include("JobSubTypes").Where(j => j.Id == id).FirstOrDefault(); if (job != null) @@ -654,5 +654,185 @@ namespace Disco.Web.Controllers } #endregion + #region Log Repair + [DiscoAuthorize(Claims.Job.Actions.LogRepair)] + public virtual ActionResult LogRepair(int id, string RepairProviderId, int? OrganisationAddressId) + { + var m = new Models.Job.LogRepairModel() + { + JobId = id, + RepairProviderId = RepairProviderId, + OrganisationAddressId = OrganisationAddressId + }; + m.UpdateModel(Database, false); + m.RepairDescription = m.Job.GenerateFaultDescription(Database); + + if (m.RepairProvider != null) + { + using (var rp = m.RepairProvider.CreateInstance()) + { + m.RepairProviderSubmitJobBeginResult = rp.SubmitJobBegin(Database, this, m.Job, m.OrganisationAddress, m.TechUser); + } + } + + return View(m); + } + [HttpPost, DiscoAuthorize(Claims.Job.Actions.LogRepair)] + public virtual ActionResult LogRepair(Models.Job.LogRepairModel m, FormCollection form) + { + m.UpdateModel(Database, true); + + if (ModelState.IsValid) + { + switch (m.SubmissionAction) + { + case "Update": + var updatedModel = new Models.Job.LogRepairModel() + { + JobId = m.JobId, + RepairProviderId = m.RepairProviderId, + OrganisationAddressId = m.OrganisationAddressId, + RepairDescription = m.RepairDescription + }; + updatedModel.UpdateModel(Database, false); + + if (updatedModel.RepairProvider != null) + { + using (var wp = updatedModel.RepairProvider.CreateInstance()) + { + using (var rp = m.RepairProvider.CreateInstance()) + { + m.RepairProviderSubmitJobBeginResult = rp.SubmitJobBegin(Database, this, updatedModel.Job, updatedModel.OrganisationAddress, updatedModel.TechUser); + } + } + } + + return View(updatedModel); + case "Manual": + if (string.IsNullOrWhiteSpace(m.ManualProviderName)) + { + ModelState.AddModelError("ManualProviderName", "The Repair Provider Name is required"); + return View(Views.LogRepair, m); + } + try + { + m.Job.OnLogRepair(Database, m.RepairDescription, m.ManualProviderName, m.ManualProviderReference, m.OrganisationAddress, m.TechUser); + Database.SaveChanges(); + return RedirectToAction(MVC.Job.Show(m.JobId)); + } + catch (Exception ex) + { + m.Error = ex; + return View(Views.LogRepairError, m); + throw; + } + case "Disclose": + using (var p = m.RepairProvider.CreateInstance()) + { + Dictionary warrantyProviderProperties; + try + { + warrantyProviderProperties = p.SubmitJobParseProperties(Database, form, this, m.Job, m.OrganisationAddress, m.TechUser, m.RepairDescription); + } + catch (Exception ex) + { + m.Error = ex; + return View(Views.LogRepairError, m); + } + if (!ModelState.IsValid) + return View(Views.LogRepair, m); + + if (warrantyProviderProperties != null) + { + m.ProviderPropertiesJson = JsonConvert.SerializeObject(warrantyProviderProperties); + } + m.DiscloseProperties = p.SubmitJobDiscloseInfo(Database, m.Job, m.OrganisationAddress, m.TechUser, m.RepairDescription, warrantyProviderProperties); + return View(Views.LogRepairDisclose, m); + } + case "Submit": + try + { + m.Job.OnLogRepair(Database, m.RepairDescription, m.RepairProvider, m.OrganisationAddress, m.TechUser, m.ProviderProperties()); + Database.SaveChanges(); + return RedirectToAction(MVC.Job.Show(m.JobId)); + } + catch (Exception ex) + { + m.Error = ex; + return View(Views.LogRepairError, m); + throw; + } + default: + return RedirectToAction(MVC.Job.Show(m.JobId)); + } + + } + else + { + return View(Views.LogRepair, m); + } + } + + [DiscoAuthorize(Claims.Job.Properties.NonWarrantyProperties.RepairProviderDetails)] + public virtual ActionResult RepairProviderJobDetails(int id) + { + Models.Job.ProviderJobDetailsModel model = new Models.Job.ProviderJobDetailsModel(); + + Job job = Database.Jobs.Include("Device.DeviceModel").Include("JobMetaNonWarranty").Include("JobSubTypes").Where(j => j.Id == id).FirstOrDefault(); + if (job != null) + { + if (job.JobMetaNonWarranty != null && !string.IsNullOrEmpty(job.JobMetaNonWarranty.RepairerName)) + { + var providerDef = RepairProviderFeature.FindPluginFeature(job.JobMetaNonWarranty.RepairerName); + + if (providerDef != null) + { + using (RepairProviderFeature providerInstance = providerDef.CreateInstance()) + { + if (providerInstance.JobDetailsSupported) + { + try + { + Tuple details = providerInstance.JobDetails(Database, this, job); + + model.JobDetailsSupported = true; + model.ViewType = details.Item1; + model.ViewModel = details.Item2; + return View(model); + } + catch (Exception ex) + { + model.JobDetailsSupported = false; + model.JobDetailsException = ex; + return View(model); + } + } + else + { + model.JobDetailsSupported = false; + model.JobDetailsNotSupportedMessage = string.Format("Plugin '{0} ({1})' (Repair Provider for '{2}') doesn't support Job Details", providerInstance.Manifest.Name, providerInstance.Manifest.Id, providerInstance.ProviderId); + return View(model); + } + } + } + + model.JobDetailsSupported = false; + model.JobDetailsNotSupportedMessage = string.Format("Repair Provider '{0}' is not integrated with Disco", job.JobMetaNonWarranty.RepairerName); + return View(model); + } + else + { + model.JobDetailsSupported = false; + model.JobDetailsNotSupportedMessage = "Job not in the correct state"; + return View(model); + } + } + else + { + return HttpNotFound("Invalid Job Id"); + } + } + #endregion + } -} +} \ No newline at end of file diff --git a/Disco.Web/Disco.Web.csproj b/Disco.Web/Disco.Web.csproj index 2cbf119d..4b655d5f 100644 --- a/Disco.Web/Disco.Web.csproj +++ b/Disco.Web/Disco.Web.csproj @@ -594,6 +594,7 @@ + True True @@ -614,6 +615,26 @@ True True + + LogRepair.cshtml + True + True + + + LogRepairDisclose.cshtml + True + True + + + LogRepairError.cshtml + True + True + + + RepairProviderJobDetails.cshtml + True + True + True True @@ -674,7 +695,7 @@ - + @@ -1712,6 +1733,22 @@ RazorGenerator Welcome.generated.cs
+ + RazorGenerator + RepairProviderJobDetails.generated.cs + + + RazorGenerator + LogRepair.generated.cs + + + RazorGenerator + LogRepairDisclose.generated.cs + + + RazorGenerator + LogRepairError.generated.cs + RazorGenerator Create_Redirect.generated.cs diff --git a/Disco.Web/Models/Job/CreateModelOld.cs b/Disco.Web/Models/Job/CreateModelOld.cs deleted file mode 100644 index a7fc03b6..00000000 --- a/Disco.Web/Models/Job/CreateModelOld.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using Disco.Models; -using System.ComponentModel.DataAnnotations; -using Disco.Data.Repository; - -namespace Disco.Web.Models.Job -{ - [CustomValidation(typeof(CreateModelValidation), "ValidateCreateModel")] - public class CreateModelOld - { - private Disco.Models.Repository.Device _Device; - private Disco.Models.Repository.User _User; - - public Disco.Models.Repository.Device Device - { - get - { - return _Device; - } - set - { - _Device = value; - DeviceSerialNumber = value.SerialNumber; - } - } - public Disco.Models.Repository.User User - { - get - { - return _User; - } - set - { - _User = value; - UserId = value.Id; - } - } - - public string DeviceSerialNumber { get; set; } - public string UserId { get; set; } - - [Required] - public string Type { get; set; } - [Required] - public List SubTypes { get; set; } - - public List JobTypes { get; set; } - public List JobSubTypes { get; set; } - - public Disco.Models.Repository.JobType GetJobType - { - get - { - if (!string.IsNullOrEmpty(this.Type)) - { - return this.JobTypes.FirstOrDefault(m => m.Id == this.Type); - } - return null; - } - } - public List GetJobSubTypes - { - get - { - if (SubTypes != null) - { - var subTypes = this.SubTypes; - return this.JobSubTypes.Where(m => subTypes.Contains(String.Format("{0}_{1}", m.JobTypeId, m.Id))).ToList(); - } - return null; - } - } - - public void UpdateModel(DiscoDataContext dbContext) - { - if (this.JobTypes == null) - JobTypes = dbContext.JobTypes.ToList(); - if (this.JobSubTypes == null) - JobSubTypes = dbContext.JobSubTypes.ToList(); - - if (!string.IsNullOrEmpty(DeviceSerialNumber)) - { - this.Device = dbContext.Devices.Include("DeviceModel").Where(d => d.SerialNumber == DeviceSerialNumber).FirstOrDefault(); - if (this.Device == null) - { - throw new ArgumentException("Invalid Device Serial Number Specified", "DeviceSerialNumber"); - } - if (string.IsNullOrEmpty(this.UserId) && !string.IsNullOrEmpty(this.Device.AssignedUserId)) - { - this.UserId = this.Device.AssignedUserId; - } - if (string.IsNullOrEmpty(this.Type)) - this.Type = this.JobTypes.First(jt => jt.Id == "HWar").Id; - } - else - { - // No Device - Remove Hardware Types - foreach (var jobType in JobTypes.ToArray()) - { - if (jobType.Id != Disco.Models.Repository.JobType.JobTypeIds.SApp) - { - JobTypes.Remove(jobType); - JobSubTypes.RemoveAll(jst => jst.JobType == jobType); - } - } - } - if (!string.IsNullOrEmpty(UserId)) - { - this.User = dbContext.Users.Find(UserId); - if (this.User == null) - { - throw new ArgumentException("Invalid User Id Specified", "UserId"); - } - if (string.IsNullOrEmpty(this.Type)) - this.Type = Disco.Models.Repository.JobType.JobTypeIds.SApp; - } - if (this.User == null && this.Device == null) - { - throw new InvalidOperationException("A Job must reference a Device and/or a User"); - } - } - - } - - public class CreateModelValidation - { - - public static ValidationResult ValidateCreateModel(CreateModelOld model) - { - - // Device && User both can't be null - if (string.IsNullOrEmpty(model.DeviceSerialNumber) && string.IsNullOrEmpty(model.UserId)) - return new ValidationResult("A Job must reference a Device and/or a User"); - - if (!string.IsNullOrEmpty(model.Type) && model.SubTypes != null) - { - var typeId = string.Format("{0}_", model.Type); - model.SubTypes = model.SubTypes.Where(m => m.StartsWith(typeId)).ToList(); - if (model.SubTypes.Count == 0) - { - model.SubTypes = null; - return new ValidationResult("At least one Sub Type is required", new string[] { "SubTypes" }); - } - } - - return ValidationResult.Success; - } - - } - -} \ No newline at end of file diff --git a/Disco.Web/Models/Job/LogRepairModel.cs b/Disco.Web/Models/Job/LogRepairModel.cs new file mode 100644 index 00000000..0c89062d --- /dev/null +++ b/Disco.Web/Models/Job/LogRepairModel.cs @@ -0,0 +1,121 @@ +using Disco.Data.Repository; +using Disco.Services.Plugins; +using Disco.Services.Plugins.Features.RepairProvider; +using Disco.Services.Users; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; + +namespace Disco.Web.Models.Job +{ + public class LogRepairModel + { + public Disco.Models.Repository.Job Job { get; set; } + public List RepairProviders { get; set; } + public PluginFeatureManifest RepairProvider { get; set; } + public List OrganisationAddresses { get; set; } + public Disco.Models.BI.Config.OrganisationAddress OrganisationAddress { get; set; } + + public Disco.Models.Repository.User TechUser { get; set; } + + [Required] + public int JobId { get; set; } + [Required(ErrorMessage = "Please specify a Repair Address")] + public Nullable OrganisationAddressId { get; set; } + [Required(ErrorMessage = "Please specify a Repair Provider")] + public string RepairProviderId { get; set; } + [Required(ErrorMessage = "A fault description is required"), DataType(System.ComponentModel.DataAnnotations.DataType.MultilineText)] + public string RepairDescription { get; set; } + [Required] + public string SubmissionAction { get; set; } + + public bool IsManualProvider + { + get + { + return RepairProviderId == "MANUAL"; + } + } + public string ManualProviderName { get; set; } + public string ManualProviderReference { get; set; } + + public Tuple RepairProviderSubmitJobBeginResult { get; set; } + public string ProviderPropertiesJson { get; set; } + public Dictionary ProviderProperties() + { + Dictionary p = default(Dictionary); + if (!string.IsNullOrEmpty(this.ProviderPropertiesJson)) + { + try + { + p = JsonConvert.DeserializeObject>(this.ProviderPropertiesJson); + } + catch (Exception) + { + // Ignore Errors + } + } + return p; + } + + public Dictionary DiscloseProperties { get; set; } + + public Exception Error { get; set; } + + public void UpdateModel(DiscoDataContext Database, bool IsPostBack) + { + Database.Configuration.LazyLoadingEnabled = true; + if (Job == null) + { + // Update Job User's Details [#12] + string jobUserId = Database.Jobs.Where(j => j.Id == JobId).Select(j => j.UserId).FirstOrDefault(); + if (jobUserId != null) + { + // Ignore update errors (Most commonly when the User Id no longer exists in AD) + try + { + UserService.GetUser(jobUserId, Database, true); + } catch (Exception) {} + } + + Job = (from j in Database.Jobs.Include("Device.DeviceModel").Include("JobMetaNonWarranty").Include("JobSubTypes") + where (j.Id == JobId) + select j).FirstOrDefault(); + if (Job == null) + { + throw new ArgumentException("Invalid Job Number Specified", "JobId"); + } + } + + // Update TechUser's Details [#12] + this.TechUser = UserService.GetUser(UserService.CurrentUserId, Database, true); + + RepairProviders = Plugins.GetPluginFeatures(typeof(RepairProviderFeature)); + + if (!IsPostBack && string.IsNullOrEmpty(RepairProviderId)) + { + RepairProviderId = Job.Device.DeviceModel.DefaultRepairProvider; + + if (string.IsNullOrEmpty(RepairProviderId)) + RepairProviderId = "MANUAL"; + } + + if (!string.IsNullOrEmpty(RepairProviderId) && RepairProviderId != "MANUAL") + RepairProvider = Plugins.GetPluginFeature(RepairProviderId, typeof(RepairProviderFeature)); + + this.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses.OrderBy(a => a.Name).ToList(); + + if (!IsPostBack && !this.OrganisationAddressId.HasValue) + { + OrganisationAddressId = Job.Device.DeviceProfile.DefaultOrganisationAddress; + } + if (this.OrganisationAddressId.HasValue) + this.OrganisationAddress = this.OrganisationAddresses.FirstOrDefault(oa => oa.Id == this.OrganisationAddressId.Value); + + if (!string.IsNullOrEmpty(RepairDescription)) + RepairDescription = RepairDescription.Trim(); + } + } +} \ No newline at end of file diff --git a/Disco.Web/Models/Job/LogWarrantyModel.cs b/Disco.Web/Models/Job/LogWarrantyModel.cs index 8dc61113..b33b0aff 100644 --- a/Disco.Web/Models/Job/LogWarrantyModel.cs +++ b/Disco.Web/Models/Job/LogWarrantyModel.cs @@ -1,15 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using Disco.Data.Repository; -using System.ComponentModel.DataAnnotations; -using Disco.BI; -using System.Web.Script.Serialization; +using Disco.Data.Repository; using Disco.Services.Plugins; using Disco.Services.Plugins.Features.WarrantyProvider; -using Newtonsoft.Json; using Disco.Services.Users; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; namespace Disco.Web.Models.Job { @@ -32,29 +29,29 @@ namespace Disco.Web.Models.Job [Required(ErrorMessage = "A fault description is required"), DataType(System.ComponentModel.DataAnnotations.DataType.MultilineText)] public string FaultDescription { get; set; } [Required] - public string WarrantyAction { get; set; } + public string SubmissionAction { get; set; } - public bool IsCustomProvider + public bool IsManualProvider { get { - return WarrantyProviderId == "CUSTOM"; + return WarrantyProviderId == "MANUAL"; } } - public string CustomProviderName { get; set; } - public string CustomProviderReference { get; set; } + public string ManualProviderName { get; set; } + public string ManualProviderReference { get; set; } public Type WarrantyProviderSubmitJobViewType { get; set; } public object WarrantyProviderSubmitJobModel { get; set; } - public string WarrantyProviderPropertiesJson { get; set; } - public Dictionary WarrantyProviderProperties() + public string ProviderPropertiesJson { get; set; } + public Dictionary ProviderProperties() { Dictionary p = default(Dictionary); - if (!string.IsNullOrEmpty(this.WarrantyProviderPropertiesJson)) + if (!string.IsNullOrEmpty(this.ProviderPropertiesJson)) { try { - p = JsonConvert.DeserializeObject>(this.WarrantyProviderPropertiesJson); + p = JsonConvert.DeserializeObject>(this.ProviderPropertiesJson); } catch (Exception) { @@ -101,9 +98,12 @@ namespace Disco.Web.Models.Job if (!IsPostBack && string.IsNullOrEmpty(WarrantyProviderId)) { WarrantyProviderId = Job.Device.DeviceModel.DefaultWarrantyProvider; + + if (string.IsNullOrEmpty(WarrantyProviderId)) + WarrantyProviderId = "MANUAL"; } - if (!string.IsNullOrEmpty(WarrantyProviderId) && WarrantyProviderId != "CUSTOM") + if (!string.IsNullOrEmpty(WarrantyProviderId) && WarrantyProviderId != "MANUAL") WarrantyProvider = Plugins.GetPluginFeature(WarrantyProviderId, typeof(WarrantyProviderFeature)); this.OrganisationAddresses = Database.DiscoConfiguration.OrganisationAddresses.Addresses.OrderBy(a => a.Name).ToList(); diff --git a/Disco.Web/Models/Job/WarrantyProviderJobDetailsModel.cs b/Disco.Web/Models/Job/ProviderJobDetailsModel.cs similarity index 89% rename from Disco.Web/Models/Job/WarrantyProviderJobDetailsModel.cs rename to Disco.Web/Models/Job/ProviderJobDetailsModel.cs index 99c71161..33e4d66a 100644 --- a/Disco.Web/Models/Job/WarrantyProviderJobDetailsModel.cs +++ b/Disco.Web/Models/Job/ProviderJobDetailsModel.cs @@ -5,7 +5,7 @@ using System.Web; namespace Disco.Web.Models.Job { - public class WarrantyProviderJobDetailsModel + public class ProviderJobDetailsModel { public Type ViewType { get; set; } public object ViewModel { get; set; } diff --git a/Disco.Web/T4MVC.cs b/Disco.Web/T4MVC.cs index 6fed53ad..5ea058fe 100644 --- a/Disco.Web/T4MVC.cs +++ b/Disco.Web/T4MVC.cs @@ -319,7 +319,7 @@ namespace Links public static string Url() { return T4MVCHelpers.ProcessVirtualPath(URLPATH); } public static string Url(string fileName) { return T4MVCHelpers.ProcessVirtualPath(URLPATH + "/" + fileName); } public static readonly string disco_hubs_js = T4MVCHelpers.IsProduction() && T4Extensions.FileExists(URLPATH + "/disco-hubs.min.js") ? Url("disco-hubs.min.js") : Url("disco-hubs.js"); - public static readonly string jquery_signalR_2_0_3_js = T4MVCHelpers.IsProduction() && T4Extensions.FileExists(URLPATH + "/jquery.signalR-2.0.3.min.js") ? Url("jquery.signalR-2.0.3.min.js") : Url("jquery.signalR-2.0.3.js"); + public static readonly string jquery_signalR_2_1_0_js = T4MVCHelpers.IsProduction() && T4Extensions.FileExists(URLPATH + "/jquery.signalR-2.1.0.min.js") ? Url("jquery.signalR-2.1.0.min.js") : Url("jquery.signalR-2.1.0.js"); } public static readonly string jQuery_SignalR_js_bundle = Url("jQuery-SignalR.js.bundle"); @@ -1612,6 +1612,18 @@ namespace Disco.Web.Controllers { return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.WarrantyProviderJobDetails); } + [NonAction] + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public virtual System.Web.Mvc.ActionResult LogRepair() + { + return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LogRepair); + } + [NonAction] + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public virtual System.Web.Mvc.ActionResult RepairProviderJobDetails() + { + return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.RepairProviderJobDetails); + } [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] public JobController Actions { get { return MVC.Job; } } @@ -1648,6 +1660,8 @@ namespace Disco.Web.Controllers public readonly string Create = "Create"; public readonly string LogWarranty = "LogWarranty"; public readonly string WarrantyProviderJobDetails = "WarrantyProviderJobDetails"; + public readonly string LogRepair = "LogRepair"; + public readonly string RepairProviderJobDetails = "RepairProviderJobDetails"; } [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] @@ -1673,6 +1687,8 @@ namespace Disco.Web.Controllers public const string Create = "Create"; public const string LogWarranty = "LogWarranty"; public const string WarrantyProviderJobDetails = "WarrantyProviderJobDetails"; + public const string LogRepair = "LogRepair"; + public const string RepairProviderJobDetails = "RepairProviderJobDetails"; } @@ -1722,6 +1738,26 @@ namespace Disco.Web.Controllers { public readonly string id = "id"; } + static readonly ActionParamsClass_LogRepair s_params_LogRepair = new ActionParamsClass_LogRepair(); + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public ActionParamsClass_LogRepair LogRepairParams { get { return s_params_LogRepair; } } + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public class ActionParamsClass_LogRepair + { + public readonly string id = "id"; + public readonly string RepairProviderId = "RepairProviderId"; + public readonly string OrganisationAddressId = "OrganisationAddressId"; + public readonly string m = "m"; + public readonly string form = "form"; + } + static readonly ActionParamsClass_RepairProviderJobDetails s_params_RepairProviderJobDetails = new ActionParamsClass_RepairProviderJobDetails(); + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public ActionParamsClass_RepairProviderJobDetails RepairProviderJobDetailsParams { get { return s_params_RepairProviderJobDetails; } } + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public class ActionParamsClass_RepairProviderJobDetails + { + public readonly string id = "id"; + } static readonly ViewsClass s_views = new ViewsClass(); [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] public ViewsClass Views { get { return s_views; } } @@ -1738,9 +1774,13 @@ namespace Disco.Web.Controllers public readonly string Create_Redirect = "Create_Redirect"; public readonly string Index = "Index"; public readonly string List = "List"; + public readonly string LogRepair = "LogRepair"; + public readonly string LogRepairDisclose = "LogRepairDisclose"; + public readonly string LogRepairError = "LogRepairError"; public readonly string LogWarranty = "LogWarranty"; public readonly string LogWarrantyDisclose = "LogWarrantyDisclose"; public readonly string LogWarrantyError = "LogWarrantyError"; + public readonly string RepairProviderJobDetails = "RepairProviderJobDetails"; public readonly string Show = "Show"; public readonly string WarrantyProviderJobDetails = "WarrantyProviderJobDetails"; } @@ -1750,9 +1790,13 @@ namespace Disco.Web.Controllers public readonly string Create_Redirect = "~/Views/Job/Create_Redirect.cshtml"; public readonly string Index = "~/Views/Job/Index.cshtml"; public readonly string List = "~/Views/Job/List.cshtml"; + public readonly string LogRepair = "~/Views/Job/LogRepair.cshtml"; + public readonly string LogRepairDisclose = "~/Views/Job/LogRepairDisclose.cshtml"; + public readonly string LogRepairError = "~/Views/Job/LogRepairError.cshtml"; public readonly string LogWarranty = "~/Views/Job/LogWarranty.cshtml"; public readonly string LogWarrantyDisclose = "~/Views/Job/LogWarrantyDisclose.cshtml"; public readonly string LogWarrantyError = "~/Views/Job/LogWarrantyError.cshtml"; + public readonly string RepairProviderJobDetails = "~/Views/Job/RepairProviderJobDetails.cshtml"; public readonly string Show = "~/Views/Job/Show.cshtml"; public readonly string WarrantyProviderJobDetails = "~/Views/Job/WarrantyProviderJobDetails.cshtml"; static readonly _JobPartsClass s_JobParts = new _JobPartsClass(); @@ -2049,6 +2093,45 @@ namespace Disco.Web.Controllers return callInfo; } + [NonAction] + partial void LogRepairOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string RepairProviderId, int? OrganisationAddressId); + + [NonAction] + public override System.Web.Mvc.ActionResult LogRepair(int id, string RepairProviderId, int? OrganisationAddressId) + { + var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LogRepair); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "RepairProviderId", RepairProviderId); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "OrganisationAddressId", OrganisationAddressId); + LogRepairOverride(callInfo, id, RepairProviderId, OrganisationAddressId); + return callInfo; + } + + [NonAction] + partial void LogRepairOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, Disco.Web.Models.Job.LogRepairModel m, System.Web.Mvc.FormCollection form); + + [NonAction] + public override System.Web.Mvc.ActionResult LogRepair(Disco.Web.Models.Job.LogRepairModel m, System.Web.Mvc.FormCollection form) + { + var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LogRepair); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "m", m); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "form", form); + LogRepairOverride(callInfo, m, form); + return callInfo; + } + + [NonAction] + partial void RepairProviderJobDetailsOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id); + + [NonAction] + public override System.Web.Mvc.ActionResult RepairProviderJobDetails(int id) + { + var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.RepairProviderJobDetails); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id); + RepairProviderJobDetailsOverride(callInfo, id); + return callInfo; + } + } } @@ -4774,6 +4857,12 @@ namespace Disco.Web.Areas.API.Controllers } [NonAction] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public virtual System.Web.Mvc.ActionResult UpdateDefaultRepairProvider() + { + return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateDefaultRepairProvider); + } + [NonAction] + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] public virtual System.Web.Mvc.ActionResult Image() { return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Image); @@ -4834,6 +4923,7 @@ namespace Disco.Web.Areas.API.Controllers public readonly string UpdateDescription = "UpdateDescription"; public readonly string UpdateDefaultPurchaseDate = "UpdateDefaultPurchaseDate"; public readonly string UpdateDefaultWarrantyProvider = "UpdateDefaultWarrantyProvider"; + public readonly string UpdateDefaultRepairProvider = "UpdateDefaultRepairProvider"; public readonly string Image = "Image"; public readonly string Delete = "Delete"; public readonly string Component = "Component"; @@ -4851,6 +4941,7 @@ namespace Disco.Web.Areas.API.Controllers public const string UpdateDescription = "UpdateDescription"; public const string UpdateDefaultPurchaseDate = "UpdateDefaultPurchaseDate"; public const string UpdateDefaultWarrantyProvider = "UpdateDefaultWarrantyProvider"; + public const string UpdateDefaultRepairProvider = "UpdateDefaultRepairProvider"; public const string Image = "Image"; public const string Delete = "Delete"; public const string Component = "Component"; @@ -4903,6 +4994,16 @@ namespace Disco.Web.Areas.API.Controllers public readonly string DefaultWarrantyProvider = "DefaultWarrantyProvider"; public readonly string redirect = "redirect"; } + static readonly ActionParamsClass_UpdateDefaultRepairProvider s_params_UpdateDefaultRepairProvider = new ActionParamsClass_UpdateDefaultRepairProvider(); + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public ActionParamsClass_UpdateDefaultRepairProvider UpdateDefaultRepairProviderParams { get { return s_params_UpdateDefaultRepairProvider; } } + [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] + public class ActionParamsClass_UpdateDefaultRepairProvider + { + public readonly string id = "id"; + public readonly string DefaultRepairProvider = "DefaultRepairProvider"; + public readonly string redirect = "redirect"; + } static readonly ActionParamsClass_Image s_params_Image = new ActionParamsClass_Image(); [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] public ActionParamsClass_Image ImageParams { get { return s_params_Image; } } @@ -5044,6 +5145,20 @@ namespace Disco.Web.Areas.API.Controllers return callInfo; } + [NonAction] + partial void UpdateDefaultRepairProviderOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string DefaultRepairProvider, bool redirect); + + [NonAction] + public override System.Web.Mvc.ActionResult UpdateDefaultRepairProvider(int id, string DefaultRepairProvider, bool redirect) + { + var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateDefaultRepairProvider); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "DefaultRepairProvider", DefaultRepairProvider); + ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "redirect", redirect); + UpdateDefaultRepairProviderOverride(callInfo, id, DefaultRepairProvider, redirect); + return callInfo; + } + [NonAction] partial void ImageOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int? id, string v); @@ -6864,12 +6979,6 @@ namespace Disco.Web.Areas.API.Controllers } [NonAction] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] - public virtual System.Web.Mvc.ActionResult LogRepair() - { - return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LogRepair); - } - [NonAction] - [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] public virtual System.Web.Mvc.ActionResult DeviceReadyForReturn() { return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.DeviceReadyForReturn); @@ -7058,7 +7167,6 @@ namespace Disco.Web.Areas.API.Controllers public readonly string UpdateFlag = "UpdateFlag"; public readonly string WaitingForUserAction = "WaitingForUserAction"; public readonly string NotWaitingForUserAction = "NotWaitingForUserAction"; - public readonly string LogRepair = "LogRepair"; public readonly string DeviceReadyForReturn = "DeviceReadyForReturn"; public readonly string DeviceHeld = "DeviceHeld"; public readonly string DeviceReturned = "DeviceReturned"; @@ -7130,7 +7238,6 @@ namespace Disco.Web.Areas.API.Controllers public const string UpdateFlag = "UpdateFlag"; public const string WaitingForUserAction = "WaitingForUserAction"; public const string NotWaitingForUserAction = "NotWaitingForUserAction"; - public const string LogRepair = "LogRepair"; public const string DeviceReadyForReturn = "DeviceReadyForReturn"; public const string DeviceHeld = "DeviceHeld"; public const string DeviceReturned = "DeviceReturned"; @@ -7581,17 +7688,6 @@ namespace Disco.Web.Areas.API.Controllers public readonly string Resolution = "Resolution"; public readonly string redirect = "redirect"; } - static readonly ActionParamsClass_LogRepair s_params_LogRepair = new ActionParamsClass_LogRepair(); - [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] - public ActionParamsClass_LogRepair LogRepairParams { get { return s_params_LogRepair; } } - [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] - public class ActionParamsClass_LogRepair - { - public readonly string id = "id"; - public readonly string RepairerName = "RepairerName"; - public readonly string RepairerReference = "RepairerReference"; - public readonly string redirect = "redirect"; - } static readonly ActionParamsClass_DeviceReadyForReturn s_params_DeviceReadyForReturn = new ActionParamsClass_DeviceReadyForReturn(); [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] public ActionParamsClass_DeviceReadyForReturn DeviceReadyForReturnParams { get { return s_params_DeviceReadyForReturn; } } @@ -8394,21 +8490,6 @@ namespace Disco.Web.Areas.API.Controllers return callInfo; } - [NonAction] - partial void LogRepairOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string RepairerName, string RepairerReference, bool? redirect); - - [NonAction] - public override System.Web.Mvc.ActionResult LogRepair(int id, string RepairerName, string RepairerReference, bool? redirect) - { - var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.LogRepair); - ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id); - ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "RepairerName", RepairerName); - ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "RepairerReference", RepairerReference); - ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "redirect", redirect); - LogRepairOverride(callInfo, id, RepairerName, RepairerReference, redirect); - return callInfo; - } - [NonAction] partial void DeviceReadyForReturnOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, bool redirect); diff --git a/Disco.Web/Views/Job/JobParts/Repairs.cshtml b/Disco.Web/Views/Job/JobParts/Repairs.cshtml index 0ef0b6e5..e6fb3500 100644 --- a/Disco.Web/Views/Job/JobParts/Repairs.cshtml +++ b/Disco.Web/Views/Job/JobParts/Repairs.cshtml @@ -1,91 +1,177 @@ @model Disco.Web.Models.Job.ShowModel @{ - Authorization.Require(Claims.Job.ShowNonWarrantyFinance); + Authorization.Require(Claims.Job.ShowNonWarrantyRepairs); Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers"); } - - - - - - - - - - - + + + + - - - - - + { + if (string.IsNullOrWhiteSpace(Model.Job.JobMetaNonWarranty.RepairerReference)) + {<Unknown/None>} + else + {@Model.Job.JobMetaNonWarranty.RepairerReference} + } + + + if (Model.Job.JobMetaNonWarranty.RepairerLoggedDate.HasValue) + { + + + + + } + if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairProviderDetails)) + { + Html.BundleDeferred("~/ClientScripts/Modules/Disco-AjaxHelperIcons"); + + + + + } + } + else + { + + + + + }
Repairer Name - - @if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerName)) - { - @Html.EditorFor(m => m.Job.JobMetaNonWarranty.RepairerName) - @AjaxHelpers.AjaxSave() - @AjaxHelpers.AjaxLoader() - - } - else - { - if (string.IsNullOrWhiteSpace(Model.Job.JobMetaNonWarranty.RepairerName)) - {<Unknown/None>} + }); + + } else - {@Model.Job.JobMetaNonWarranty.RepairerName} - } -
Repair Logged - - @CommonHelpers.FriendlyDate(Model.Job.JobMetaNonWarranty.RepairerLoggedDate, "Not Logged", "Job_JobMetaNonWarranty_RepairerLoggedDate") -
Repair Reference - - @if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerReference)) - { - @Html.EditorFor(m => m.Job.JobMetaNonWarranty.RepairerReference) - @AjaxHelpers.AjaxSave() - @AjaxHelpers.AjaxLoader() - + } + else + { + @CommonHelpers.FriendlyDate(Model.Job.JobMetaNonWarranty.RepairerLoggedDate, "Not Logged", null) + } +
Repair Reference + + @if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerReference)) + { + @Html.EditorFor(m => m.Job.JobMetaNonWarranty.RepairerReference) + @AjaxHelpers.AjaxSave() + @AjaxHelpers.AjaxLoader() + - } - else - { - if (string.IsNullOrWhiteSpace(Model.Job.JobMetaNonWarranty.RepairerReference)) - {<Unknown/None>} + }); + + } else - {@Model.Job.JobMetaNonWarranty.RepairerReference} - } -
Repair Completed - - @CommonHelpers.FriendlyDate(Model.Job.JobMetaNonWarranty.RepairerCompletedDate, "Not Completed", "Job_JobMetaNonWarranty_RepairerCompletedDate") -
Repair Completed + + @if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerCompletedDate)) + { + @CommonHelpers.FriendlyDate(Model.Job.JobMetaNonWarranty.RepairerCompletedDate, "Not Completed", "Job_JobMetaNonWarranty_RepairerCompletedDate") + @AjaxHelpers.AjaxLoader() + + } + else + { + @CommonHelpers.FriendlyDate(Model.Job.JobMetaNonWarranty.RepairerCompletedDate, "Not Completed", null) + } +
Actions + + @if (Model.Job.CanLogRepair()) + { + @Html.ActionLinkSmallButton("Log Repair", MVC.Job.LogRepair(Model.Job.Id, null, null), "Job_Show_Repair_Actions_LogRepair_Button") + } + else + { + <None> + } +
- diff --git a/Disco.Web/Views/Job/JobParts/Repairs.generated.cs b/Disco.Web/Views/Job/JobParts/Repairs.generated.cs index 56d8e777..0c77f0ee 100644 --- a/Disco.Web/Views/Job/JobParts/Repairs.generated.cs +++ b/Disco.Web/Views/Job/JobParts/Repairs.generated.cs @@ -47,7 +47,7 @@ namespace Disco.Web.Views.Job.JobParts #line 2 "..\..\Views\Job\JobParts\Repairs.cshtml" - Authorization.Require(Claims.Job.ShowNonWarrantyFinance); + Authorization.Require(Claims.Job.ShowNonWarrantyRepairs); Html.BundleDeferred("~/ClientScripts/Modules/Disco-PropertyChangeHelpers"); @@ -58,96 +58,112 @@ WriteLiteral("\r\n\r\n \r\n \r\n"); + + + #line 8 "..\..\Views\Job\JobParts\Repairs.cshtml" + + + #line default + #line hidden + + #line 8 "..\..\Views\Job\JobParts\Repairs.cshtml" + if (Model.Job.JobMetaNonWarranty.RepairerName != null || Model.Job.JobMetaNonWarranty.RepairerLoggedDate.HasValue || Model.Job.JobMetaNonWarranty.RepairerReference != null) + { + + + #line default + #line hidden +WriteLiteral(" \r\n Repairer Name\r\n \r\n \r\n"); +WriteLiteral(">Repairer Name\r\n \r\n \r\n"); - #line 12 "..\..\Views\Job\JobParts\Repairs.cshtml" - - - #line default - #line hidden - - #line 12 "..\..\Views\Job\JobParts\Repairs.cshtml" - if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerName)) - { + #line 14 "..\..\Views\Job\JobParts\Repairs.cshtml" #line default #line hidden #line 14 "..\..\Views\Job\JobParts\Repairs.cshtml" - Write(Html.EditorFor(m => m.Job.JobMetaNonWarranty.RepairerName)); - - - #line default - #line hidden - - #line 14 "..\..\Views\Job\JobParts\Repairs.cshtml" - - - - #line default - #line hidden - - #line 15 "..\..\Views\Job\JobParts\Repairs.cshtml" - Write(AjaxHelpers.AjaxSave()); - - - #line default - #line hidden - - #line 15 "..\..\Views\Job\JobParts\Repairs.cshtml" - - + if (Authorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerName)) + { + #line default #line hidden #line 16 "..\..\Views\Job\JobParts\Repairs.cshtml" - Write(AjaxHelpers.AjaxLoader()); + Write(Html.EditorFor(m => m.Job.JobMetaNonWarranty.RepairerName)); #line default #line hidden #line 16 "..\..\Views\Job\JobParts\Repairs.cshtml" - + + + + #line default + #line hidden + + #line 17 "..\..\Views\Job\JobParts\Repairs.cshtml" + Write(AjaxHelpers.AjaxSave()); #line default #line hidden -WriteLiteral("